From 8571d9e090f9b728e1921bda662c7c0fb9536719 Mon Sep 17 00:00:00 2001 From: Gergo Magyar Date: Wed, 24 Jun 2026 08:41:52 +0000 Subject: [PATCH] fix(ingestion): let unresolved explicit imports shadow Nuxt auto-imports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The explicit-import suppression index only recorded import local names whose edge resolved to a file (`edge.targetFile !== null`). An explicit import from an unresolved external package — `import { useAuto } from '@vueuse/core'; useAuto()` — therefore escaped suppression, and the post-resolution hook emitted a spurious Nuxt auto-import CALLS edge for a name the file already imports explicitly. Record the local name regardless of whether the import resolved: an explicit import is authoritative shadowing intent. Adds an integration fixture importing from an external package and a (non-vacuous) assertion that it emits no nuxt edge. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01T4W25WLfYD1JNy8icxeLPU --- .../ingestion/languages/typescript/scope-resolver.ts | 6 +++++- .../nuxt-auto-imports/pages/external-import.ts | 5 +++++ .../test/integration/resolvers/nuxt-scope.test.ts | 12 ++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 gitnexus/test/fixtures/lang-resolution/nuxt-auto-imports/pages/external-import.ts diff --git a/gitnexus/src/core/ingestion/languages/typescript/scope-resolver.ts b/gitnexus/src/core/ingestion/languages/typescript/scope-resolver.ts index 6c77e4c29..09301de71 100644 --- a/gitnexus/src/core/ingestion/languages/typescript/scope-resolver.ts +++ b/gitnexus/src/core/ingestion/languages/typescript/scope-resolver.ts @@ -212,7 +212,11 @@ const typescriptScopeResolver: ScopeResolver = { explicitImportNamesByFile.set(scope.filePath, names); } for (const edge of edges) { - if (edge.targetFile !== null) names.add(edge.localName); + // Record the local name whether or not the import resolved to a file. + // An explicit import of a name — even from an unresolved external + // package (`import { useAuto } from '@vueuse/core'`) — is authoritative + // shadowing intent and must suppress the auto-import for that name. + if (edge.localName) names.add(edge.localName); } } diff --git a/gitnexus/test/fixtures/lang-resolution/nuxt-auto-imports/pages/external-import.ts b/gitnexus/test/fixtures/lang-resolution/nuxt-auto-imports/pages/external-import.ts new file mode 100644 index 000000000..ff21af299 --- /dev/null +++ b/gitnexus/test/fixtures/lang-resolution/nuxt-auto-imports/pages/external-import.ts @@ -0,0 +1,5 @@ +import { useAuto } from '@vueuse/core'; + +export function renderExternal() { + useAuto(); +} diff --git a/gitnexus/test/integration/resolvers/nuxt-scope.test.ts b/gitnexus/test/integration/resolvers/nuxt-scope.test.ts index 9dc453e8a..ad86d83b8 100644 --- a/gitnexus/test/integration/resolvers/nuxt-scope.test.ts +++ b/gitnexus/test/integration/resolvers/nuxt-scope.test.ts @@ -121,6 +121,18 @@ describe('Nuxt/Nitro auto-import scope resolution', () => { ).toBeDefined(); }); + it('suppresses an auto-import shadowed by an explicit unresolved external import', () => { + const calls = nuxtCalls(); + // Guard against a vacuous pass: the feature must have emitted edges elsewhere. + expect(calls.length).toBeGreaterThan(0); + // pages/external-import.ts does `import { useAuto } from '@vueuse/core'` (an + // unresolved external) then calls useAuto(). The explicit import shadows the + // Nuxt auto-import, so no nuxt edge is emitted from that file. + expect( + calls.filter((edge) => edge.sourceFilePath.endsWith('pages/external-import.ts')), + ).toHaveLength(0); + }); + it('suppresses only explicitly imported local names, not every symbol from the same source', () => { const calls = nuxtCalls();