Path: blob/main/tools/sass-variable-explainer/_attic/print-dependency-graph.ts
12921 views
import { parse } from "npm:scss-parser";1import { assert } from "jsr:@std/assert";2import * as prettier from "npm:prettier";3import { propagateDeclarationTypes } from "./sass-analyzer/declaration-types.ts";4import { getVariableDependencies } from "./sass-analyzer/get-dependencies.ts";5import { cleanSassAst } from "./sass-analyzer/clean-ast.ts";6import { makeParserModule } from "./sass-analyzer/parse.ts";78export const getSassAst = makeParserModule(parse, prettier.format).getSassAst;910const drawColorDependencyGraph = (ast: any) => {11const declarations = propagateDeclarationTypes(ast);1213let labelCount = 0;14const labels: Map<string, string> = new Map();15const dotNodeName = (name: string) => {16if (labels.has(name)) {17return { id: labels.get(name) };18}19const newName = `N${labelCount++}`;20labels.set(name, newName);21return { id: newName, nodeDecl: `${newName}[label="${name}"]` };22}2324console.log("```{dot}");25console.log("digraph G {\n rankdir=LR;\n");26console.log(" splines=false;");27console.log(" node [shape=rectangle, color=gray]");28console.log(" edge [color=gray]");2930const varDeps = getVariableDependencies(declarations);31const inverseVarDeps = new Map<string, Set<string>>();32const origins = new Map<string, Set<string>>();33const addToSetMap = (map: Map<string, Set<string>>, key: string, value: string) => {34if (!map.has(key)) {35map.set(key, new Set());36}37map.get(key)!.add(value);38}3940for (const [name, deps] of varDeps) {41// update origin sets42const node = deps.node;43const origin = node?.annotation?.origin ?? "unknown";44addToSetMap(origins, origin, name);45// update inverse dependencies46for (const dep of deps.dependencies) {47if (declarations.get(name)?.valueType !== "color" ||48declarations.get(dep)?.valueType !== "color") {49continue;50}51addToSetMap(inverseVarDeps, dep, name);52}53}54let subgraphCount = 0;55for (const [name, vars] of origins) {56if (name === "unknown") {57continue;58}59subgraphCount++;60console.log(`subgraph subgraph_${subgraphCount} {`);61for (const varName of vars) {62// only show numbered colors if they have inverse dependencies63if (varName.match(/^.+-[0-9]00$/) && !inverseVarDeps.get(varName)?.size) {64continue;65}66const { nodeDecl: sourceNodeDecl } = dotNodeName(varName);67if (!sourceNodeDecl) {68throw new Error("multiple origins for a variable? " + varName);69}70assert(sourceNodeDecl);71console.log(` ${sourceNodeDecl}`);72}73console.log(` label = "${name}"`);74console.log(` color=red`);75console.log("}");76}7778for (const [name, deps] of varDeps) {79if (deps.node.valueType !== "color") {80continue;81}82// only show numbered colors if they have inverse dependencies83if (name.match(/^.+-[0-9]00$/) && !inverseVarDeps.get(name)?.size) {84continue;85}86for (const dep of deps.dependencies) {87if (declarations.get(dep)?.valueType !== "color") {88continue;89}90const {id: sourceId, nodeDecl: sourceNodeDecl } = dotNodeName(dep);91const {id: targetId, nodeDecl: targetNodeDecl } = dotNodeName(name);92if (sourceNodeDecl) {93console.log(` ${sourceNodeDecl}`);94}95if (targetNodeDecl) {96console.log(` ${targetNodeDecl}`);97}9899console.log(` ${sourceId} -> ${targetId}`);100}101}102103console.log("}");104console.log("```");105}106107if (import.meta.main) {108const ast = await getSassAst(Deno.readTextFileSync(Deno.args[0] || "/dev/stdin"));109let cleaned = cleanSassAst(ast);110drawColorDependencyGraph(cleaned);111// const declarations = propagateDeclarationTypes(cleaned);112// for (const [name, node] of declarations) {113// if (node.valueType === "color") {114// console.log(name, node.line);115// }116// // console.log(name, node);117// }118}119120