mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-09 02:30:15 -06:00
In import fixes, use a ".js" extension if other imports do (#20624)
* In import fixes, use a ".js" extension if other imports do * Code review
This commit is contained in:
parent
29378b2ce2
commit
74b8160430
@ -306,6 +306,10 @@ namespace ts.codefix {
|
||||
return literal;
|
||||
}
|
||||
|
||||
function usesJsExtensionOnImports(sourceFile: SourceFile): boolean {
|
||||
return firstDefined(sourceFile.imports, ({ text }) => pathIsRelative(text) ? fileExtensionIs(text, Extension.Js) : undefined) || false;
|
||||
}
|
||||
|
||||
function createImportClauseOfKind(kind: ImportKind.Default | ImportKind.Named | ImportKind.Namespace, symbolName: string) {
|
||||
const id = createIdentifier(symbolName);
|
||||
switch (kind) {
|
||||
@ -329,18 +333,19 @@ namespace ts.codefix {
|
||||
host: LanguageServiceHost,
|
||||
): string[] {
|
||||
const { baseUrl, paths, rootDirs } = options;
|
||||
const addJsExtension = usesJsExtensionOnImports(sourceFile);
|
||||
const choicesForEachExportingModule = flatMap(moduleSymbols, moduleSymbol =>
|
||||
getAllModulePaths(program, moduleSymbol.valueDeclaration.getSourceFile()).map(moduleFileName => {
|
||||
const sourceDirectory = getDirectoryPath(sourceFile.fileName);
|
||||
const global = tryGetModuleNameFromAmbientModule(moduleSymbol)
|
||||
|| tryGetModuleNameFromTypeRoots(options, host, getCanonicalFileName, moduleFileName)
|
||||
|| tryGetModuleNameFromTypeRoots(options, host, getCanonicalFileName, moduleFileName, addJsExtension)
|
||||
|| tryGetModuleNameAsNodeModule(options, moduleFileName, host, getCanonicalFileName, sourceDirectory)
|
||||
|| rootDirs && tryGetModuleNameFromRootDirs(rootDirs, moduleFileName, sourceDirectory, getCanonicalFileName);
|
||||
if (global) {
|
||||
return [global];
|
||||
}
|
||||
|
||||
const relativePath = removeExtensionAndIndexPostFix(getRelativePath(moduleFileName, sourceDirectory, getCanonicalFileName), options);
|
||||
const relativePath = removeExtensionAndIndexPostFix(getRelativePath(moduleFileName, sourceDirectory, getCanonicalFileName), options, addJsExtension);
|
||||
if (!baseUrl) {
|
||||
return [relativePath];
|
||||
}
|
||||
@ -350,7 +355,7 @@ namespace ts.codefix {
|
||||
return [relativePath];
|
||||
}
|
||||
|
||||
const importRelativeToBaseUrl = removeExtensionAndIndexPostFix(relativeToBaseUrl, options);
|
||||
const importRelativeToBaseUrl = removeExtensionAndIndexPostFix(relativeToBaseUrl, options, addJsExtension);
|
||||
if (paths) {
|
||||
const fromPaths = tryGetModuleNameFromPaths(removeFileExtension(relativeToBaseUrl), importRelativeToBaseUrl, paths);
|
||||
if (fromPaths) {
|
||||
@ -459,12 +464,13 @@ namespace ts.codefix {
|
||||
host: GetEffectiveTypeRootsHost,
|
||||
getCanonicalFileName: (file: string) => string,
|
||||
moduleFileName: string,
|
||||
addJsExtension: boolean,
|
||||
): string | undefined {
|
||||
const roots = getEffectiveTypeRoots(options, host);
|
||||
return roots && firstDefined(roots, unNormalizedTypeRoot => {
|
||||
const typeRoot = toPath(unNormalizedTypeRoot, /*basePath*/ undefined, getCanonicalFileName);
|
||||
if (startsWith(moduleFileName, typeRoot)) {
|
||||
return removeExtensionAndIndexPostFix(moduleFileName.substring(typeRoot.length + 1), options);
|
||||
return removeExtensionAndIndexPostFix(moduleFileName.substring(typeRoot.length + 1), options, addJsExtension);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -598,9 +604,13 @@ namespace ts.codefix {
|
||||
return firstDefined(rootDirs, rootDir => getRelativePathIfInDirectory(path, rootDir, getCanonicalFileName));
|
||||
}
|
||||
|
||||
function removeExtensionAndIndexPostFix(fileName: string, options: CompilerOptions): string {
|
||||
function removeExtensionAndIndexPostFix(fileName: string, options: CompilerOptions, addJsExtension: boolean): string {
|
||||
const noExtension = removeFileExtension(fileName);
|
||||
return getEmitModuleResolutionKind(options) === ModuleResolutionKind.NodeJs ? removeSuffix(noExtension, "/index") : noExtension;
|
||||
return addJsExtension
|
||||
? noExtension + ".js"
|
||||
: getEmitModuleResolutionKind(options) === ModuleResolutionKind.NodeJs
|
||||
? removeSuffix(noExtension, "/index")
|
||||
: noExtension;
|
||||
}
|
||||
|
||||
function getRelativePathIfInDirectory(path: string, directoryPath: string, getCanonicalFileName: GetCanonicalFileName): string | undefined {
|
||||
|
||||
22
tests/cases/fourslash/importNameCodeFix_jsExtension.ts
Normal file
22
tests/cases/fourslash/importNameCodeFix_jsExtension.ts
Normal file
@ -0,0 +1,22 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
// @moduleResolution: node
|
||||
// @noLib: true
|
||||
|
||||
// @Filename: /a.ts
|
||||
////export function a() {}
|
||||
|
||||
// @Filename: /b.ts
|
||||
////export function b() {}
|
||||
|
||||
// @Filename: /c.ts
|
||||
////import * as g from "global"; // Global imports skipped
|
||||
////import { a } from "./a.js";
|
||||
////import { a as a2 } from "./a"; // Ignored, only the first relative import is considered
|
||||
////[|b;|]
|
||||
|
||||
goTo.file("/c.ts");
|
||||
verify.importFixAtPosition([
|
||||
`import { b } from "./b.js";
|
||||
b;`,
|
||||
]);
|
||||
@ -11,7 +11,7 @@
|
||||
////import { foo } from "link";
|
||||
|
||||
// @Filename: /b.ts
|
||||
////[|foo/**/;|]
|
||||
////[|foo;|]
|
||||
|
||||
// Uses "link" instead of "real" because `a` did.
|
||||
goTo.file("/b.ts");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user