Skip to content

Commit fe5949c

Browse files
authored
Port more resolveExternalModule, fix copy paste error in GetResolutionDiagnostic (#1248)
1 parent 652b18c commit fe5949c

File tree

27 files changed

+181
-359
lines changed

27 files changed

+181
-359
lines changed

internal/checker/checker.go

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14482,14 +14482,24 @@ func (c *Checker) resolveExternalModule(location *ast.Node, moduleReference stri
1448214482
mode = c.program.GetDefaultResolutionModeForFile(importingSourceFile)
1448314483
}
1448414484

14485-
var sourceFile *ast.SourceFile
1448614485
resolvedModule := c.program.GetResolvedModule(importingSourceFile, moduleReference, mode)
14487-
if resolvedModule.IsResolved() {
14486+
14487+
var resolutionDiagnostic *diagnostics.Message
14488+
if errorNode != nil && resolvedModule.IsResolved() {
14489+
resolutionDiagnostic = module.GetResolutionDiagnostic(c.compilerOptions, resolvedModule, importingSourceFile)
14490+
}
14491+
14492+
var sourceFile *ast.SourceFile
14493+
if resolvedModule.IsResolved() && (resolutionDiagnostic == nil || resolutionDiagnostic == diagnostics.Module_0_was_resolved_to_1_but_jsx_is_not_set) {
1448814494
sourceFile = c.program.GetSourceFileForResolvedModule(resolvedModule.ResolvedFileName)
1448914495
}
1449014496

1449114497
if sourceFile != nil {
14492-
// !!!
14498+
// If there's a resolutionDiagnostic we need to report it even if a sourceFile is found.
14499+
if resolutionDiagnostic != nil {
14500+
c.error(errorNode, resolutionDiagnostic, moduleReference, resolvedModule.ResolvedFileName)
14501+
}
14502+
1449314503
if errorNode != nil {
1449414504
if resolvedModule.ResolvedUsingTsExtension && tspath.IsDeclarationFileName(moduleReference) {
1449514505
if ast.FindAncestor(location, ast.IsEmittableImport) != nil {
@@ -14577,7 +14587,7 @@ func (c *Checker) resolveExternalModule(location *ast.Node, moduleReference stri
1457714587

1457814588
if sourceFile.Symbol != nil {
1457914589
if errorNode != nil {
14580-
if resolvedModule.IsExternalLibraryImport && !(tspath.ExtensionIsTs(resolvedModule.Extension) || resolvedModule.Extension == tspath.ExtensionJson) {
14590+
if resolvedModule.IsExternalLibraryImport && !resolutionExtensionIsTSOrJson(resolvedModule.Extension) {
1458114591
c.errorOnImplicitAnyModule(false /*isError*/, errorNode, mode, resolvedModule, moduleReference)
1458214592
}
1458314593
if c.moduleKind == core.ModuleKindNode16 || c.moduleKind == core.ModuleKindNode18 {
@@ -14633,7 +14643,7 @@ func (c *Checker) resolveExternalModule(location *ast.Node, moduleReference stri
1463314643
return nil
1463414644
}
1463514645

14636-
if resolvedModule.IsResolved() && !(tspath.ExtensionIsTs(resolvedModule.Extension) || resolvedModule.Extension == tspath.ExtensionJson) {
14646+
if resolvedModule.IsResolved() && !resolutionExtensionIsTSOrJson(resolvedModule.Extension) && resolutionDiagnostic == nil || resolutionDiagnostic == diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type {
1463714647
if isForAugmentation {
1463814648
c.error(
1463914649
errorNode,
@@ -14648,7 +14658,6 @@ func (c *Checker) resolveExternalModule(location *ast.Node, moduleReference stri
1464814658
}
1464914659

1465014660
if moduleNotFoundError != nil {
14651-
1465214661
// See if this was possibly a projectReference redirect
1465314662
if resolvedModule.IsResolved() {
1465414663
redirect := c.program.GetOutputAndProjectReference(tspath.ToPath(resolvedModule.ResolvedFileName, c.program.GetCurrentDirectory(), c.program.UseCaseSensitiveFileNames()))
@@ -14663,29 +14672,36 @@ func (c *Checker) resolveExternalModule(location *ast.Node, moduleReference stri
1466314672
}
1466414673
}
1466514674

14666-
// !!!
14667-
isExtensionlessRelativePathImport := tspath.PathIsRelative(moduleReference) && !tspath.HasExtension(moduleReference)
14668-
resolutionIsNode16OrNext := c.moduleResolutionKind == core.ModuleResolutionKindNode16 || c.moduleResolutionKind == core.ModuleResolutionKindNodeNext
14669-
if !c.compilerOptions.GetResolveJsonModule() && tspath.FileExtensionIs(moduleReference, tspath.ExtensionJson) {
14670-
c.error(errorNode, diagnostics.Cannot_find_module_0_Consider_using_resolveJsonModule_to_import_module_with_json_extension, moduleReference)
14671-
} else if mode == core.ResolutionModeESM && resolutionIsNode16OrNext && isExtensionlessRelativePathImport {
14672-
absoluteRef := tspath.GetNormalizedAbsolutePath(moduleReference, tspath.GetDirectoryPath(importingSourceFile.FileName()))
14673-
if suggestedExt := c.getSuggestedImportExtension(absoluteRef); suggestedExt != "" {
14674-
c.error(errorNode, diagnostics.Relative_import_paths_need_explicit_file_extensions_in_ECMAScript_imports_when_moduleResolution_is_node16_or_nodenext_Did_you_mean_0, moduleReference+suggestedExt)
14675+
if resolutionDiagnostic != nil {
14676+
c.error(errorNode, resolutionDiagnostic, moduleReference, resolvedModule.ResolvedFileName)
14677+
} else {
14678+
isExtensionlessRelativePathImport := tspath.PathIsRelative(moduleReference) && !tspath.HasExtension(moduleReference)
14679+
resolutionIsNode16OrNext := c.moduleResolutionKind == core.ModuleResolutionKindNode16 || c.moduleResolutionKind == core.ModuleResolutionKindNodeNext
14680+
if !c.compilerOptions.GetResolveJsonModule() && tspath.FileExtensionIs(moduleReference, tspath.ExtensionJson) {
14681+
c.error(errorNode, diagnostics.Cannot_find_module_0_Consider_using_resolveJsonModule_to_import_module_with_json_extension, moduleReference)
14682+
} else if mode == core.ResolutionModeESM && resolutionIsNode16OrNext && isExtensionlessRelativePathImport {
14683+
absoluteRef := tspath.GetNormalizedAbsolutePath(moduleReference, tspath.GetDirectoryPath(importingSourceFile.FileName()))
14684+
if suggestedExt := c.getSuggestedImportExtension(absoluteRef); suggestedExt != "" {
14685+
c.error(errorNode, diagnostics.Relative_import_paths_need_explicit_file_extensions_in_ECMAScript_imports_when_moduleResolution_is_node16_or_nodenext_Did_you_mean_0, moduleReference+suggestedExt)
14686+
} else {
14687+
c.error(errorNode, diagnostics.Relative_import_paths_need_explicit_file_extensions_in_ECMAScript_imports_when_moduleResolution_is_node16_or_nodenext_Consider_adding_an_extension_to_the_import_path)
14688+
}
14689+
} else if resolvedModule != nil && resolvedModule.AlternateResult != "" {
14690+
errorInfo := c.createModuleNotFoundChain(resolvedModule, errorNode, moduleReference, mode, moduleReference)
14691+
c.diagnostics.Add(NewDiagnosticChainForNode(errorInfo, errorNode, moduleNotFoundError, moduleReference))
1467514692
} else {
14676-
c.error(errorNode, diagnostics.Relative_import_paths_need_explicit_file_extensions_in_ECMAScript_imports_when_moduleResolution_is_node16_or_nodenext_Consider_adding_an_extension_to_the_import_path)
14693+
c.error(errorNode, moduleNotFoundError, moduleReference)
1467714694
}
14678-
} else if resolvedModule != nil && resolvedModule.AlternateResult != "" {
14679-
errorInfo := c.createModuleNotFoundChain(resolvedModule, errorNode, moduleReference, mode, moduleReference)
14680-
c.diagnostics.Add(NewDiagnosticChainForNode(errorInfo, errorNode, moduleNotFoundError, moduleReference))
14681-
} else {
14682-
c.error(errorNode, moduleNotFoundError, moduleReference)
1468314695
}
1468414696
}
1468514697

1468614698
return nil
1468714699
}
1468814700

14701+
func resolutionExtensionIsTSOrJson(ext string) bool {
14702+
return tspath.ExtensionIsTs(ext) || ext == tspath.ExtensionJson
14703+
}
14704+
1468914705
func (c *Checker) getSuggestedImportSource(moduleReference string, tsExtension string, mode core.ResolutionMode) string {
1469014706
importSourceWithoutExtension := tspath.RemoveExtension(moduleReference, tsExtension)
1469114707

internal/compiler/fileloader.go

Lines changed: 1 addition & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"github.com/microsoft/typescript-go/internal/ast"
1111
"github.com/microsoft/typescript-go/internal/collections"
1212
"github.com/microsoft/typescript-go/internal/core"
13-
"github.com/microsoft/typescript-go/internal/diagnostics"
1413
"github.com/microsoft/typescript-go/internal/module"
1514
"github.com/microsoft/typescript-go/internal/tsoptions"
1615
"github.com/microsoft/typescript-go/internal/tspath"
@@ -432,7 +431,7 @@ func (p *fileLoader) resolveImportsAndModuleAugmentations(t *parseTask) {
432431
importIndex := index - importsStart
433432

434433
shouldAddFile := moduleName != "" &&
435-
getResolutionDiagnostic(optionsForFile, resolvedModule, file) == nil &&
434+
module.GetResolutionDiagnostic(optionsForFile, resolvedModule, file) == nil &&
436435
!optionsForFile.NoResolve.IsTrue() &&
437436
!(isJsFile && !optionsForFile.GetAllowJS()) &&
438437
(importIndex < 0 || (importIndex < len(file.Imports()) && (ast.IsInJSFile(file.Imports()[importIndex]) || file.Imports()[importIndex].Flags&ast.NodeFlagsJSDoc == 0)))
@@ -451,57 +450,6 @@ func (p *fileLoader) resolveImportsAndModuleAugmentations(t *parseTask) {
451450
}
452451
}
453452

454-
// Returns a DiagnosticMessage if we won't include a resolved module due to its extension.
455-
// The DiagnosticMessage's parameters are the imported module name, and the filename it resolved to.
456-
// This returns a diagnostic even if the module will be an untyped module.
457-
func getResolutionDiagnostic(options *core.CompilerOptions, resolvedModule *module.ResolvedModule, file *ast.SourceFile) *diagnostics.Message {
458-
needJsx := func() *diagnostics.Message {
459-
if options.Jsx != core.JsxEmitNone {
460-
return nil
461-
}
462-
return diagnostics.Module_0_was_resolved_to_1_but_jsx_is_not_set
463-
}
464-
465-
needAllowJs := func() *diagnostics.Message {
466-
if options.GetAllowJS() || !options.NoImplicitAny.DefaultIfUnknown(options.Strict).IsTrue() {
467-
return nil
468-
}
469-
return diagnostics.Module_0_was_resolved_to_1_but_resolveJsonModule_is_not_used
470-
}
471-
472-
needResolveJsonModule := func() *diagnostics.Message {
473-
if options.GetResolveJsonModule() {
474-
return nil
475-
}
476-
return diagnostics.Module_0_was_resolved_to_1_but_resolveJsonModule_is_not_used
477-
}
478-
479-
needAllowArbitraryExtensions := func() *diagnostics.Message {
480-
if file.IsDeclarationFile || options.AllowArbitraryExtensions.IsTrue() {
481-
return nil
482-
}
483-
return diagnostics.Module_0_was_resolved_to_1_but_allowArbitraryExtensions_is_not_set
484-
}
485-
486-
switch resolvedModule.Extension {
487-
case tspath.ExtensionTs, tspath.ExtensionDts,
488-
tspath.ExtensionMts, tspath.ExtensionDmts,
489-
tspath.ExtensionCts, tspath.ExtensionDcts:
490-
// These are always allowed.
491-
return nil
492-
case tspath.ExtensionTsx:
493-
return needJsx()
494-
case tspath.ExtensionJsx:
495-
return core.Coalesce(needJsx(), needAllowJs())
496-
case tspath.ExtensionJs, tspath.ExtensionMjs, tspath.ExtensionCjs:
497-
return needAllowJs()
498-
case tspath.ExtensionJson:
499-
return needResolveJsonModule()
500-
default:
501-
return needAllowArbitraryExtensions()
502-
}
503-
}
504-
505453
func (p *fileLoader) createSyntheticImport(text string, file *ast.SourceFile) *ast.Node {
506454
p.factoryMu.Lock()
507455
defer p.factoryMu.Unlock()

internal/module/util.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ package module
33
import (
44
"strings"
55

6+
"github.com/microsoft/typescript-go/internal/ast"
67
"github.com/microsoft/typescript-go/internal/core"
8+
"github.com/microsoft/typescript-go/internal/diagnostics"
79
"github.com/microsoft/typescript-go/internal/semver"
810
"github.com/microsoft/typescript-go/internal/tspath"
911
)
@@ -97,3 +99,57 @@ func ComparePatternKeys(a, b string) int {
9799
}
98100
return 0
99101
}
102+
103+
// Returns a DiagnosticMessage if we won't include a resolved module due to its extension.
104+
// The DiagnosticMessage's parameters are the imported module name, and the filename it resolved to.
105+
// This returns a diagnostic even if the module will be an untyped module.
106+
func GetResolutionDiagnostic(options *core.CompilerOptions, resolvedModule *ResolvedModule, file *ast.SourceFile) *diagnostics.Message {
107+
needJsx := func() *diagnostics.Message {
108+
if options.Jsx != core.JsxEmitNone {
109+
return nil
110+
}
111+
return diagnostics.Module_0_was_resolved_to_1_but_jsx_is_not_set
112+
}
113+
114+
needAllowJs := func() *diagnostics.Message {
115+
if options.GetAllowJS() || !options.NoImplicitAny.DefaultIfUnknown(options.Strict).IsTrue() {
116+
return nil
117+
}
118+
return diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type
119+
}
120+
121+
needResolveJsonModule := func() *diagnostics.Message {
122+
if options.GetResolveJsonModule() {
123+
return nil
124+
}
125+
return diagnostics.Module_0_was_resolved_to_1_but_resolveJsonModule_is_not_used
126+
}
127+
128+
needAllowArbitraryExtensions := func() *diagnostics.Message {
129+
if file.IsDeclarationFile || options.AllowArbitraryExtensions.IsTrue() {
130+
return nil
131+
}
132+
return diagnostics.Module_0_was_resolved_to_1_but_allowArbitraryExtensions_is_not_set
133+
}
134+
135+
switch resolvedModule.Extension {
136+
case tspath.ExtensionTs, tspath.ExtensionDts,
137+
tspath.ExtensionMts, tspath.ExtensionDmts,
138+
tspath.ExtensionCts, tspath.ExtensionDcts:
139+
// These are always allowed.
140+
return nil
141+
case tspath.ExtensionTsx:
142+
return needJsx()
143+
case tspath.ExtensionJsx:
144+
if message := needJsx(); message != nil {
145+
return message
146+
}
147+
return needAllowJs()
148+
case tspath.ExtensionJs, tspath.ExtensionMjs, tspath.ExtensionCjs:
149+
return needAllowJs()
150+
case tspath.ExtensionJson:
151+
return needResolveJsonModule()
152+
default:
153+
return needAllowArbitraryExtensions()
154+
}
155+
}

testdata/baselines/reference/submodule/compiler/checkJsxNotSetError.errors.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/bar.jsx(1,17): error TS6142: Module '/foo' was resolved to '/foo.jsx', but '--jsx' is not set.
12
/bar.jsx(2,11): error TS17004: Cannot use JSX unless the '--jsx' flag is provided.
23
/foo.jsx(2,5): error TS17004: Cannot use JSX unless the '--jsx' flag is provided.
34

@@ -10,8 +11,10 @@
1011
);
1112
export default Foo;
1213

13-
==== /bar.jsx (1 errors) ====
14+
==== /bar.jsx (2 errors) ====
1415
import Foo from '/foo';
16+
~~~~~~
17+
!!! error TS6142: Module '/foo' was resolved to '/foo.jsx', but '--jsx' is not set.
1518
const a = <Foo />
1619
~~~~~~~
1720
!!! error TS17004: Cannot use JSX unless the '--jsx' flag is provided.

testdata/baselines/reference/submodule/compiler/moduleResolutionWithExtensions_notSupported.errors.txt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
/a.ts(1,17): error TS2307: Cannot find module './tsx' or its corresponding type declarations.
1+
/a.ts(1,17): error TS6142: Module './tsx' was resolved to '/tsx.tsx', but '--jsx' is not set.
2+
/a.ts(2,17): error TS6142: Module './jsx' was resolved to '/jsx.jsx', but '--jsx' is not set.
23

34

4-
==== /a.ts (1 errors) ====
5+
==== /a.ts (2 errors) ====
56
import tsx from "./tsx"; // Not allowed.
67
~~~~~~~
7-
!!! error TS2307: Cannot find module './tsx' or its corresponding type declarations.
8+
!!! error TS6142: Module './tsx' was resolved to '/tsx.tsx', but '--jsx' is not set.
89
import jsx from "./jsx"; // Not allowed.
10+
~~~~~~~
11+
!!! error TS6142: Module './jsx' was resolved to '/jsx.jsx', but '--jsx' is not set.
912
import js from "./js"; // OK because it's an untyped module.
1013

1114
==== /tsx.tsx (0 errors) ====

testdata/baselines/reference/submodule/compiler/moduleResolutionWithExtensions_notSupported.errors.txt.diff

Lines changed: 0 additions & 22 deletions
This file was deleted.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/a.ts(1,17): error TS6142: Module './jsx' was resolved to '/jsx.jsx', but '--jsx' is not set.
2+
3+
4+
==== /a.ts (1 errors) ====
5+
import jsx from "./jsx";
6+
~~~~~~~
7+
!!! error TS6142: Module './jsx' was resolved to '/jsx.jsx', but '--jsx' is not set.
8+
9+
==== /jsx.jsx (0 errors) ====
10+

testdata/baselines/reference/submodule/compiler/moduleResolutionWithExtensions_notSupported2.errors.txt.diff

Lines changed: 0 additions & 14 deletions
This file was deleted.

testdata/baselines/reference/submodule/conformance/bundlerImportTsExtensions(allowimportingtsextensions=false,noemit=false).errors.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
/project/main.ts(8,16): error TS2846: A declaration file cannot be imported without 'import type'. Did you mean to import an implementation file './b.js' instead?
44
/project/main.ts(11,16): error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
55
/project/main.ts(12,16): error TS5097: An import path can only end with a '.tsx' extension when 'allowImportingTsExtensions' is enabled.
6+
/project/main.ts(12,16): error TS6142: Module './c.tsx' was resolved to '/project/c.tsx', but '--jsx' is not set.
67
/project/main.ts(16,16): error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
78
/project/types.d.ts(2,16): error TS2846: A declaration file cannot be imported without 'import type'. Did you mean to import an implementation file './a.js' instead?
89

@@ -43,7 +44,7 @@
4344
==== /project/e.txt.ts (0 errors) ====
4445
export {};
4546

46-
==== /project/main.ts (6 errors) ====
47+
==== /project/main.ts (7 errors) ====
4748
import {} from "./a";
4849
import {} from "./a.js";
4950
import {} from "./a.ts";
@@ -66,6 +67,8 @@
6667
import {} from "./c.tsx";
6768
~~~~~~~~~
6869
!!! error TS5097: An import path can only end with a '.tsx' extension when 'allowImportingTsExtensions' is enabled.
70+
~~~~~~~~~
71+
!!! error TS6142: Module './c.tsx' was resolved to '/project/c.tsx', but '--jsx' is not set.
6972

7073
import {} from "./d";
7174
import {} from "./d/index";

testdata/baselines/reference/submodule/conformance/bundlerImportTsExtensions(allowimportingtsextensions=false,noemit=true).errors.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
/project/main.ts(8,16): error TS2846: A declaration file cannot be imported without 'import type'. Did you mean to import an implementation file './b.js' instead?
44
/project/main.ts(11,16): error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
55
/project/main.ts(12,16): error TS5097: An import path can only end with a '.tsx' extension when 'allowImportingTsExtensions' is enabled.
6+
/project/main.ts(12,16): error TS6142: Module './c.tsx' was resolved to '/project/c.tsx', but '--jsx' is not set.
67
/project/main.ts(16,16): error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
78
/project/types.d.ts(2,16): error TS2846: A declaration file cannot be imported without 'import type'. Did you mean to import an implementation file './a.js' instead?
89

@@ -43,7 +44,7 @@
4344
==== /project/e.txt.ts (0 errors) ====
4445
export {};
4546

46-
==== /project/main.ts (6 errors) ====
47+
==== /project/main.ts (7 errors) ====
4748
import {} from "./a";
4849
import {} from "./a.js";
4950
import {} from "./a.ts";
@@ -66,6 +67,8 @@
6667
import {} from "./c.tsx";
6768
~~~~~~~~~
6869
!!! error TS5097: An import path can only end with a '.tsx' extension when 'allowImportingTsExtensions' is enabled.
70+
~~~~~~~~~
71+
!!! error TS6142: Module './c.tsx' was resolved to '/project/c.tsx', but '--jsx' is not set.
6972

7073
import {} from "./d";
7174
import {} from "./d/index";

0 commit comments

Comments
 (0)