Files
reverse-engineering-anything/scripts/lib/import-specifiers.mjs
T
morlutoandCursor Agent 249b90c5e3 refactor(javascript): break the semantic analysis import cycle (#8063)
* refactor(javascript): break the semantic analysis import cycle

Split shared semantic facts out of the analysis hub so projectors of
effects, evaluation, and identity no longer import one another in a cycle.

* refactor(javascript): share the import specifier reader

Read static imports in one module used by the boundary checker and both
cycle guards, so those rules cannot drift apart.

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-10-30 06:07:49 +08:00

44 lines
1.4 KiB
JavaScript

import { parse } from "@babel/parser";
import { traverseFast } from "@babel/types";
const literalValue = (node) => {
if (node?.type === "StringLiteral") return node.value;
if (node?.type === "TemplateLiteral" && node.expressions.length === 0)
return node.quasis[0]?.value.cooked ?? undefined;
return undefined;
};
/** Static string specifier on one import or re-export node, when it has one. */
export const importSpecifier = (node) => {
switch (node.type) {
case "ImportDeclaration":
case "ExportNamedDeclaration":
case "ExportAllDeclaration":
case "ImportExpression":
case "TSImportType":
return literalValue(node.source);
case "TSImportEqualsDeclaration":
return node.moduleReference.type === "TSExternalModuleReference"
? literalValue(node.moduleReference.expression)
: undefined;
default:
return undefined;
}
};
/**
* Static import and re-export specifiers in source order.
* Comments and string literals are not imports. Non-string dynamic imports
* are omitted. Callers decide which specifiers are in-repo edges.
*/
export const readImportSpecifiers = (source) => {
const specifiers = [];
const tree = parse(source, { sourceType: "module", plugins: ["typescript"] });
traverseFast(tree, (node) => {
const specifier = importSpecifier(node);
if (specifier === undefined) return;
specifiers.push({ specifier, line: node.loc?.start.line ?? 1 });
});
return specifiers;
};