fix(auto-import): don't suggest # imports that only resolve via condition fallback - #64177
fix(auto-import): don't suggest # imports that only resolve via condition fallback#64177Marwan (marwan562) wants to merge 3 commits into
Conversation
…tion fallback Reverse mapping in tryGetModuleNameFromExportsOrImports mirrored TS resolver fallback across conditions, suggesting specifiers like #utils/summarize/summarize that resolve via default only after node misses. Node picks first matching condition and throws on miss, so such suggestions crash at runtime with ERR_MODULE_NOT_FOUND. Mirror Node first-match semantics: when a runtime-active condition misses, block later conditions. Types-only conditions are ignored at runtime and don't block. Handles nested conditionals without active runtime keys and preserves array fallback. Closes microsoft#64171
There was a problem hiding this comment.
🟡 Changes recommended
Two moderate resolution-semantics issues could still produce incorrect auto-import behavior.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Updates auto-import reverse mapping to better match Node.js conditional import resolution.
Changes:
- Stops fallback after matching runtime conditions.
- Adds conditional, nested, types-only, and array mapping tests.
File summaries
| File | Review |
|---|---|
tsc/internal/modulespecifiers/specifiers.go |
Requires fixes for deeper conditional objects and Node array-target semantics. |
tsc/internal/modulespecifiers/specifiers_test.go |
Adds regression coverage, but incorrectly expects file-existence fallback for arrays. |
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 2
- Review effort level: Balanced
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
|
@microsoft-github-policy-service agree |
…rays Address Copilot review: arrays select first valid string target at runtime (no file-existence fallback), and deeper nested conditionals with inactive keys return undefined and should fallback. Switch reverse mapping to tri-state (matched/blocked/skipped) so terminal misses block later fallback while undefined continues.
|
Addressed both Copilot comments:
Added deeper-nesting + array-undefined-first cases. All Copilot review |
There was a problem hiding this comment.
🟡 Changes recommended
The critical and moderate fallback-handling issues must be resolved before approval.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (2)
tsc/internal/modulespecifiers/specifiers.go:1337
- An exhausted array is not always equivalent to an undefined nested conditional. Node treats an empty array as
null(terminal), and throws the last invalid-target error when all entries are invalid; only an array whose entries all resolve toundefinedmay fall through. Returningblocked=falsehere makes maps such as{ "node": [], "default": "./dist/index.js" }suggest the default even though Node rejects that specifier. Track these outcomes separately and propagate a terminal result for empty/all-invalid arrays.
return "", false
tsc/internal/modulespecifiers/specifiers_test.go:393
- These cases only invoke the private reverse-mapping helper, but the regression is specifically the LSP auto-import/Quick Fix result. Add a Fourslash regression using the issue's package.json/project layout and assert the exact list with
VerifyImportFixModuleSpecifiers; existing package-import auto-import coverage uses that path (for example,tsc/internal/fourslash/tests/autoImportPackageJsonImportsConditions_test.go:10-29). This ensures the invalid suggestion is actually filtered through the full language-server flow.
result := tryGetModuleNameFromExportsOrImports(
- Files reviewed: 2/2 changed files
- Comments generated: 2
- Review effort level: Balanced
…s fallback, handle empty/all-invalid arrays Address Copilot review on PR 64177: - String misses now check target validity (same rules as forward resolver): invalid targets skipped in arrays, terminal in conditionals; valid misses stay terminal. - Thread inTypesOnly through conditional/array recursion so types-only subtrees never block, preserving TS declaration fallback that Node ignores at runtime. - Empty and all-invalid arrays are terminal at runtime; only all-undefined arrays fall through. - Add unit cases and Fourslash regression for issue 64171.
|
Addressed the two Sep 8 Copilot threads:
Also handled suppressed feedback: empty and all-invalid arrays are terminal at runtime (only all-undefined falls through), and added Fourslash regression All Copilot review |
With
imports": { "#*": { "node": "./dist/*/index.js", "default": "./dist/*.js" } }and nodenext, auto-import offered both#utils/summarizeand#utils/summarize/summarize. The second only resolves in TS by falling back fromnodetodefaultafter thenodetarget misses. Node picks the first matching condition and throwsERR_MODULE_NOT_FOUNDinstead, so picking that suggestion crashes at runtime.Reverse mapping in
tryGetModuleNameFromExportsOrImportsdid the same fallback as the resolver. It now mirrors Node first-match: when a runtime-active condition misses, later conditions aren't tried.types/types@don't block since Node ignores them, nested objects with no active runtime key still fall through, and array fallback still works.Added cases alongside the existing ones in
tsc/internal/modulespecifiers/specifiers_test.go.Fixes #64171
Related #62439, #50762
Disclosure: I used AI assistance to draft this patch and reviewed and tested it myself.