Skip to content

Commit f04f1b5

Browse files
committed
Auto-imports of declaration files cannot use .ts extension
1 parent c4320a2 commit f04f1b5

File tree

5 files changed

+72
-9
lines changed

5 files changed

+72
-9
lines changed

src/compiler/moduleSpecifiers.ts

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
ModuleSpecifierResolutionHost, NodeFlags, NodeModulePathParts, normalizePath, Path, pathContainsNodeModules,
1717
pathIsBareSpecifier, pathIsRelative, PropertyAccessExpression, removeFileExtension, removeSuffix, resolvePath,
1818
ScriptKind, some, SourceFile, startsWith, startsWithDirectory, stringContains, StringLiteral, Symbol, SymbolFlags,
19-
toPath, tryGetExtensionFromPath, tryParsePatterns, TypeChecker, UserPreferences, shouldAllowImportingTsExtension, ResolutionMode, ModuleSpecifierEnding, getModuleSpecifierEndingPreference,
19+
toPath, tryGetExtensionFromPath, tryParsePatterns, TypeChecker, UserPreferences, shouldAllowImportingTsExtension, ResolutionMode, ModuleSpecifierEnding, getModuleSpecifierEndingPreference, isDeclarationFileName,
2020
} from "./_namespaces/ts";
2121

2222
// Used by importFixes, getEditsForFileRename, and declaration emit to synthesize import module specifiers.
@@ -74,10 +74,10 @@ function getPreferences(
7474
if (endsWith(oldImportSpecifier, "/index")) return ModuleSpecifierEnding.Index;
7575
}
7676
return getModuleSpecifierEndingPreference(
77-
importModuleSpecifierEnding,
78-
importingSourceFile.impliedNodeFormat,
79-
compilerOptions,
80-
importingSourceFile);
77+
importModuleSpecifierEnding,
78+
importingSourceFile.impliedNodeFormat,
79+
compilerOptions,
80+
importingSourceFile);
8181
}
8282
}
8383

@@ -937,10 +937,19 @@ function getPathsRelativeToRootDirs(path: string, rootDirs: readonly string[], g
937937
}
938938

939939
function processEnding(fileName: string, ending: ModuleSpecifierEnding, options: CompilerOptions, host?: ModuleSpecifierResolutionHost): string {
940-
if (fileExtensionIsOneOf(fileName, [Extension.Json, Extension.Mjs, Extension.Cjs])) return fileName;
940+
if (fileExtensionIsOneOf(fileName, [Extension.Json, Extension.Mjs, Extension.Cjs])) {
941+
return fileName;
942+
}
943+
941944
const noExtension = removeFileExtension(fileName);
942-
if (fileName === noExtension) return fileName;
943-
if (fileExtensionIsOneOf(fileName, [Extension.Dmts, Extension.Mts, Extension.Dcts, Extension.Cts])) return noExtension + getJSExtensionForFile(fileName, options);
945+
if (fileName === noExtension) {
946+
return fileName;
947+
}
948+
949+
if (fileExtensionIsOneOf(fileName, [Extension.Dmts, Extension.Mts, Extension.Dcts, Extension.Cts])) {
950+
return noExtension + getJSExtensionForFile(fileName, options);
951+
}
952+
944953
switch (ending) {
945954
case ModuleSpecifierEnding.Minimal:
946955
const withoutIndex = removeSuffix(noExtension, "/index");
@@ -955,7 +964,9 @@ function processEnding(fileName: string, ending: ModuleSpecifierEnding, options:
955964
case ModuleSpecifierEnding.JsExtension:
956965
return noExtension + getJSExtensionForFile(fileName, options);
957966
case ModuleSpecifierEnding.TsExtension:
958-
return fileName;
967+
// For now, we don't know if this import is going to be type-only, which means we don't
968+
// know if a .d.ts extension is valid, so use the .js extension.
969+
return isDeclarationFileName(fileName) ? noExtension + getJSExtensionForFile(fileName, options) : fileName;
959970
default:
960971
return Debug.assertNever(ending);
961972
}

tests/baselines/reference/autoImportAllowTsExtensions3.baseline.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,15 @@ import { Component } from "./Component.tsx";
66

77
## From completions
88

9+
- `fromDecl` from `"./decl.js"`
910
- `fromLocal` from `"./local.ts"`
1011

12+
```ts
13+
import { Component } from "./Component.tsx";
14+
import { fromDecl } from "./decl.js";
15+
fromDecl
16+
```
17+
1118
```ts
1219
import { Component } from "./Component.tsx";
1320
import { fromLocal } from "./local.ts";
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
```ts
2+
// @Filename: /main.ts
3+
import { Component } from "./local.js";
4+
/*|*/
5+
```
6+
7+
## From completions
8+
9+
- `fromDecl` from `"./decl.js"`
10+
- `fromLocal` from `"./local.js"`
11+
12+
```ts
13+
import { fromDecl } from "./decl.js";
14+
import { Component } from "./local.js";
15+
fromDecl
16+
```
17+
18+
```ts
19+
import { Component, fromLocal } from "./local.js";
20+
fromLocal
21+
```
22+

tests/cases/fourslash/autoImportAllowTsExtensions3.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
// @Filename: /local.ts
88
//// export const fromLocal: number;
99

10+
// @Filename: /decl.d.ts
11+
//// export const fromDecl: number;
12+
1013
// @Filename: /Component.tsx
1114
//// export function Component() { return null; }
1215

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @moduleResolution: hybrid
4+
// @allowImportingTsExtensions: true
5+
// @noEmit: true
6+
7+
// @Filename: /local.ts
8+
//// export const fromLocal: number;
9+
10+
// @Filename: /decl.d.ts
11+
//// export const fromDecl: number;
12+
13+
// @Filename: /Component.tsx
14+
//// export function Component() { return null; }
15+
16+
// @Filename: /main.ts
17+
//// import { Component } from "./local.js";
18+
//// /**/
19+
20+
verify.baselineAutoImports("");

0 commit comments

Comments
 (0)