33namespace ts . moduleSpecifiers {
44 export interface ModuleSpecifierPreferences {
55 importModuleSpecifierPreference ?: "relative" | "non-relative" ;
6- includingJsExtensionOnAutoImports ?: boolean ;
6+ includeExtensionInImports ?: Extension . Js | Extension . Jsx ;
77 }
88
99 // Note: fromSourceFile is just for usesJsExtensionOnImports
@@ -38,39 +38,39 @@ namespace ts.moduleSpecifiers {
3838
3939 interface Info {
4040 readonly moduleResolutionKind : ModuleResolutionKind ;
41- readonly addJsExtension : boolean ;
41+ readonly addExtension : Extension . Js | Extension . Jsx | undefined ;
4242 readonly getCanonicalFileName : GetCanonicalFileName ;
4343 readonly sourceDirectory : string ;
4444 }
4545 // importingSourceFileName is separate because getEditsForFileRename may need to specify an updated path
4646 function getInfo ( compilerOptions : CompilerOptions , importingSourceFile : SourceFile , importingSourceFileName : string , host : ModuleSpecifierResolutionHost , preferences : ModuleSpecifierPreferences ) : Info {
4747 const moduleResolutionKind = getEmitModuleResolutionKind ( compilerOptions ) ;
48- const addJsExtension = usesJsExtensionOnImports ( importingSourceFile , preferences ) ;
48+ const addExtension = usesExtensionOnImports ( importingSourceFile , preferences ) ;
4949 const getCanonicalFileName = createGetCanonicalFileName ( host . useCaseSensitiveFileNames ? host . useCaseSensitiveFileNames ( ) : true ) ;
5050 const sourceDirectory = getDirectoryPath ( importingSourceFileName ) ;
51- return { moduleResolutionKind, addJsExtension , getCanonicalFileName, sourceDirectory } ;
51+ return { moduleResolutionKind, addExtension , getCanonicalFileName, sourceDirectory } ;
5252 }
5353
5454 function getGlobalModuleSpecifier (
5555 moduleFileName : string ,
56- { addJsExtension , getCanonicalFileName, sourceDirectory } : Info ,
56+ { addExtension , getCanonicalFileName, sourceDirectory } : Info ,
5757 host : ModuleSpecifierResolutionHost ,
5858 compilerOptions : CompilerOptions ,
5959 ) {
60- return tryGetModuleNameFromTypeRoots ( compilerOptions , host , getCanonicalFileName , moduleFileName , addJsExtension )
60+ return tryGetModuleNameFromTypeRoots ( compilerOptions , host , getCanonicalFileName , moduleFileName , addExtension )
6161 || tryGetModuleNameAsNodeModule ( compilerOptions , moduleFileName , host , getCanonicalFileName , sourceDirectory )
6262 || compilerOptions . rootDirs && tryGetModuleNameFromRootDirs ( compilerOptions . rootDirs , moduleFileName , sourceDirectory , getCanonicalFileName ) ;
6363 }
6464
6565 function getLocalModuleSpecifiers (
6666 moduleFileName : string ,
67- { moduleResolutionKind, addJsExtension , getCanonicalFileName, sourceDirectory } : Info ,
67+ { moduleResolutionKind, addExtension , getCanonicalFileName, sourceDirectory } : Info ,
6868 compilerOptions : CompilerOptions ,
6969 preferences : ModuleSpecifierPreferences ,
7070 ) {
7171 const { baseUrl, paths } = compilerOptions ;
7272
73- const relativePath = removeExtensionAndIndexPostFix ( ensurePathIsNonModuleName ( getRelativePathFromDirectory ( sourceDirectory , moduleFileName , getCanonicalFileName ) ) , moduleResolutionKind , addJsExtension ) ;
73+ const relativePath = removeExtensionAndIndexPostFix ( ensurePathIsNonModuleName ( getRelativePathFromDirectory ( sourceDirectory , moduleFileName , getCanonicalFileName ) ) , moduleResolutionKind , addExtension ) ;
7474 if ( ! baseUrl || preferences . importModuleSpecifierPreference === "relative" ) {
7575 return [ relativePath ] ;
7676 }
@@ -80,7 +80,7 @@ namespace ts.moduleSpecifiers {
8080 return [ relativePath ] ;
8181 }
8282
83- const importRelativeToBaseUrl = removeExtensionAndIndexPostFix ( relativeToBaseUrl , moduleResolutionKind , addJsExtension ) ;
83+ const importRelativeToBaseUrl = removeExtensionAndIndexPostFix ( relativeToBaseUrl , moduleResolutionKind , addExtension ) ;
8484 if ( paths ) {
8585 const fromPaths = tryGetModuleNameFromPaths ( removeFileExtension ( relativeToBaseUrl ) , importRelativeToBaseUrl , paths ) ;
8686 if ( fromPaths ) {
@@ -130,8 +130,14 @@ namespace ts.moduleSpecifiers {
130130 return relativeFirst ? [ relativePath , importRelativeToBaseUrl ] : [ importRelativeToBaseUrl , relativePath ] ;
131131 }
132132
133- function usesJsExtensionOnImports ( { imports } : SourceFile , preferences : ModuleSpecifierPreferences ) : boolean {
134- return firstDefined ( imports , ( { text } ) => pathIsRelative ( text ) ? fileExtensionIs ( text , Extension . Js ) : undefined ) || ! ! preferences . includingJsExtensionOnAutoImports ;
133+ function tryGetFileExtension ( text : string ) {
134+ return pathIsRelative ( text ) && fileExtensionIsOneOf ( text , [ Extension . Js , Extension . Jsx ] ) ? (
135+ fileExtensionIs ( text , Extension . Js ) ? Extension . Js : Extension . Jsx
136+ ) : undefined ;
137+ }
138+
139+ function usesExtensionOnImports ( { imports } : SourceFile , preferences : ModuleSpecifierPreferences ) : Extension . Js | Extension . Jsx | undefined {
140+ return preferences . includeExtensionInImports === undefined ? firstDefined ( imports , ( { text } ) => tryGetFileExtension ( text ) ) : preferences . includeExtensionInImports ;
135141 }
136142
137143 function discoverProbableSymlinks ( files : ReadonlyArray < SourceFile > , getCanonicalFileName : ( file : string ) => string , host : ModuleSpecifierResolutionHost ) {
@@ -245,14 +251,14 @@ namespace ts.moduleSpecifiers {
245251 host : GetEffectiveTypeRootsHost ,
246252 getCanonicalFileName : ( file : string ) => string ,
247253 moduleFileName : string ,
248- addJsExtension : boolean ,
254+ addExtension : Extension . Js | Extension . Jsx | undefined ,
249255 ) : string | undefined {
250256 const roots = getEffectiveTypeRoots ( options , host ) ;
251257 return firstDefined ( roots , unNormalizedTypeRoot => {
252258 const typeRoot = toPath ( unNormalizedTypeRoot , /*basePath*/ undefined , getCanonicalFileName ) ;
253259 if ( startsWith ( moduleFileName , typeRoot ) ) {
254260 // For a type definition, we can strip `/index` even with classic resolution.
255- return removeExtensionAndIndexPostFix ( moduleFileName . substring ( typeRoot . length + 1 ) , ModuleResolutionKind . NodeJs , addJsExtension ) ;
261+ return removeExtensionAndIndexPostFix ( moduleFileName . substring ( typeRoot . length + 1 ) , ModuleResolutionKind . NodeJs , addExtension ) ;
256262 }
257263 } ) ;
258264 }
@@ -397,10 +403,10 @@ namespace ts.moduleSpecifiers {
397403 } ) ;
398404 }
399405
400- function removeExtensionAndIndexPostFix ( fileName : string , moduleResolutionKind : ModuleResolutionKind , addJsExtension : boolean ) : string {
406+ function removeExtensionAndIndexPostFix ( fileName : string , moduleResolutionKind : ModuleResolutionKind , addExtension : Extension . Js | Extension . Jsx | undefined ) : string {
401407 const noExtension = removeFileExtension ( fileName ) ;
402- return addJsExtension
403- ? noExtension + ".js"
408+ return addExtension
409+ ? noExtension + addExtension
404410 : moduleResolutionKind === ModuleResolutionKind . NodeJs
405411 ? removeSuffix ( noExtension , "/index" )
406412 : noExtension ;
0 commit comments