fix(ingestion): let unresolved explicit imports shadow Nuxt auto-imports

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) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T4W25WLfYD1JNy8icxeLPU
This commit is contained in:
Gergo Magyar 2026-06-24 08:41:52 +00:00
parent 6fbe4abb73
commit 8571d9e090
3 changed files with 22 additions and 1 deletions

View file

@ -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);
}
}

View file

@ -0,0 +1,5 @@
import { useAuto } from '@vueuse/core';
export function renderExternal() {
useAuto();
}

View file

@ -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();