Files
reverse-engineering-anything/src/domain/javascript/javascriptSemanticRequireOrigin.ts
T
hhangandhhang 86fab11fbe fix(javascript): preserve import-equals declaration and export evidence (#2062)
* fix(javascript): retain TypeScript import-equals dependencies

* test(mcp): align completion checks with warm provider state

* fix(javascript): propagate require origins through exported aliases

* fix(javascript): normalize equivalent CTS binding origins

---------

Co-authored-by: hhang <169027046+xu91102@users.noreply.github.com>
2026-10-13 06:04:21 +09:00

65 lines
1.8 KiB
TypeScript

import * as t from "@babel/types";
import type { JavaScriptModuleOrigin } from "./javascriptSemanticIr.js";
import {
resolveSemanticBindingState,
semanticResolutionBlocked,
type JavaScriptSemanticAnalysisState,
} from "./javascriptSemanticState.js";
import {
semanticStaticPropertyKey,
unwrapJavaScriptExpression,
} from "./javascriptAstValues.js";
import { stringValue } from "./javascriptStaticAnalysisHelpers.js";
interface JavaScriptRequireOrigin {
readonly origin: JavaScriptModuleOrigin;
readonly call: t.CallExpression;
}
/** Recover an unshadowed literal require origin and its exact member path. */
export const semanticRequireOrigin = (
node: t.Node | null | undefined,
state: JavaScriptSemanticAnalysisState,
): JavaScriptRequireOrigin | undefined => {
const members: string[] = [];
let current = node;
while (current !== null && current !== undefined) {
current = unwrapJavaScriptExpression(current).node;
if (
!t.isMemberExpression(current) &&
!t.isOptionalMemberExpression(current)
)
break;
const member = semanticStaticPropertyKey(
current.property,
current.computed,
);
if (member === null || !t.isNode(current.object)) return undefined;
members.push(member);
current = current.object;
}
if (
!t.isCallExpression(current) ||
!t.isIdentifier(current.callee, { name: "require" })
)
return undefined;
if (
resolveSemanticBindingState(state, current.callee, "require") !==
undefined ||
semanticResolutionBlocked(state, current.callee, "require")
)
return undefined;
const specifier = stringValue(current.arguments[0]);
return specifier === undefined
? undefined
: {
origin: {
specifier,
importedPath: members.reverse(),
resolutionMode: "require",
},
call: current,
};
};