UNPKG

@rx-now/analysis

Version:

analysis tool for visualizing for code dependencies in typescript

99 lines (98 loc) 3.66 kB
import { MethodDeclaration, Project, SyntaxKind } from "ts-morph"; import minimatch from "minimatch"; import { Graph } from "./graph"; import { getName } from "./toG6"; export class Workspace extends Graph { constructor(entryPath, tsConfigFilePath, ignoreList) { super(); this.ignoreList = []; this.project = new Project({ tsConfigFilePath }); const entryFile = this.project.getSourceFileOrThrow(entryPath); this.ignoreList = ignoreList; this.graph = { value: entryFile, parent: new Set(), children: new Set(), }; this.vertices.add(this.graph); this.collectDescendants(this.graph); } getG6Data() { throw new Error("Method not implemented."); } generateHtmlFile() { throw new Error("Method not implemented."); } getId(v) { if (v instanceof MethodDeclaration) { return `${v.getSourceFile().getFilePath()}.${v.getName()}`; } return v.getFilePath(); } getName(v) { if (v instanceof MethodDeclaration) { return `${getName(v.getSourceFile())}.${v.getName()}`; } return getName(v); } collectDescendants(current) { const sourceFile = current.value; const allImports = []; // static import statements sourceFile .getImportDeclarations() .map((i) => i .getNamedImports() .map((o) => o.getNameNode().getDefinitionNodes()) .reduce((prev, curr) => prev.concat(curr), [])) .reduce((prev, curr) => prev.concat(curr), []) .filter((n) => !this.ignoreFile(n.getSourceFile())) .forEach((n) => { allImports.push(n.getSourceFile()); }); // dynamic import statements sourceFile .getVariableStatements() .filter((o) => o.getDescendantsOfKind(SyntaxKind.ImportKeyword).length > 0) .forEach((o) => { const dynamicImports = o.getDescendantsOfKind(SyntaxKind.ImportKeyword); if (dynamicImports.length > 0) { dynamicImports.forEach((d) => { var _a; const str = d .getParentOrThrow() .getDescendantsOfKind(SyntaxKind.StringLiteral)[0]; (_a = str .getSymbol()) === null || _a === void 0 ? void 0 : _a.getDeclarations().filter((p) => !this.ignoreFile(p.getSourceFile())).map((p) => p.getSourceFile()).forEach((p) => allImports.push(p)); }); } }); // eslint-disable-next-line no-param-reassign current.children = new Set(); allImports.forEach((dest) => { const node = (this.getNodeByValue(dest) || { value: dest, parent: new Set(), children: new Set(), }); node.parent.add(current); current.children.add(node); if (!this.vertices.has(node)) { this.vertices.add(node); this.collectDescendants(node); } }); } ignoreFile(source) { return !!this.ignoreList.find((rule) => minimatch(source.getFilePath(), rule)); } toString() { const res = []; Array.from(this.vertices).forEach((o) => { res.push(`${o.value.getSourceFile().getFilePath()} => ${Array.from(o.children) .map((p) => p.value.getSourceFile().getFilePath()) .join(", ")}`); }); return res.join("\n"); } }