mirror of
https://github.com/morluto/rea.git
synced 2026-10-27 09:55:46 +00:00
* 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>
65 lines
1.8 KiB
TypeScript
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,
|
|
};
|
|
};
|