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>
This commit is contained in:
hhangandhhang authored and GitHub committed 2026-10-13 06:04:21 +09:00
1 parent 6ce5903e7a
commit 86fab11fbe
16 files changed
+498 -48

No files matched your search

@@ -134,8 +134,11 @@ export function* indexJavaScriptBindingsSteps(
/** Recover semantics from an already parsed JavaScript artifact. */
export const analyzeParsedJavaScriptSemantics = (
file: ParsedJavaScriptSource,
staticImportResolutionMode: "import" | "require" = "import",
): JavaScriptSemanticIr =>
completeSemanticSteps(analyzeParsedJavaScriptSemanticsSteps(file));
completeSemanticSteps(
analyzeParsedJavaScriptSemanticsSteps(file, staticImportResolutionMode),
);
/**
* Recover semantics from a parsed artifact with a yield between analysis
@@ -145,8 +148,9 @@ export const analyzeParsedJavaScriptSemantics = (
*/
export function* analyzeParsedJavaScriptSemanticsSteps(
file: ParsedJavaScriptSource,
staticImportResolutionMode: "import" | "require" = "import",
): Generator<void, JavaScriptSemanticIr> {
const state = createState(file.program);
const state = createState(file.program, staticImportResolutionMode);
yield* collectDefinitionsSteps(file.program, state);
yield* collectSemanticMemberMutationsSteps(file.program, state);
yield* traverseJavaScriptAstSteps(file.program, {
@@ -159,7 +163,11 @@ export function* analyzeParsedJavaScriptSemanticsSteps(
yield;
const callables = collectSemanticReturns(state, parserPartial);
yield;
const moduleLinks = resolveSemanticModuleCallables(state, callables);
const moduleLinks = resolveSemanticModuleCallables(
state,
callables,
bindings,
);
const derived = yield* collectJavaScriptDerivedSemanticsSteps(
file.program,
state,
@@ -517,7 +525,10 @@ const bindingOrigin = (
: { ...origin, importedPath: [...origin.importedPath, ...projection] };
};
const createState = (program: t.Program): JavaScriptSemanticAnalysisState => {
const createState = (
program: t.Program,
staticImportResolutionMode: "import" | "require" = "import",
): JavaScriptSemanticAnalysisState => {
const root: JavaScriptSemanticScopeState = {
scopeId: semanticScopeId("program", program),
parentScopeId: null,
@@ -527,6 +538,7 @@ const createState = (program: t.Program): JavaScriptSemanticAnalysisState => {
bindings: new Map(),
};
return {
staticImportResolutionMode,
parentsByNode: new WeakMap(),
scopes: [root],
scopesById: new Map([[root.scopeId, root]]),
@@ -803,7 +815,7 @@ const bindImportEquals = (
mutable: false,
definitionNode: node.id,
initializer: null,
directOrigin: { specifier, importedPath: [] },
directOrigin: { specifier, importedPath: [], resolutionMode: "require" },
});
};
@@ -1181,7 +1193,13 @@ const addBinding = (input: AddBindingInput): void => {
binding.definitions.push({ kind, location: range(definitionNode) });
if (initializer !== null)
binding.initializers.push({ node: initializer, projection });
if (directOrigin !== undefined) binding.directOrigins.push(directOrigin);
if (directOrigin !== undefined)
binding.directOrigins.push(
directOrigin.resolutionMode === undefined &&
state.staticImportResolutionMode === "require"
? { ...directOrigin, resolutionMode: "require" }
: directOrigin,
);
};
const createBinding = (