Skip to content

Commit 88d59e4

Browse files
authored
Fix path completions with sibling dts lookup in exports (#54869)
1 parent 5932420 commit 88d59e4

4 files changed

+91
-4
lines changed

src/services/stringCompletions.ts

+11-4
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import {
4747
getBaseFileName,
4848
getConditions,
4949
getContextualTypeFromParent,
50+
getDeclarationEmitExtensionForPath,
5051
getDirectoryPath,
5152
getEffectiveTypeRoots,
5253
getEmitModuleResolutionKind,
@@ -1023,6 +1024,8 @@ function getModulesForPathsPattern(
10231024
const expandedPrefixDirectory = fragmentHasPath ? combinePaths(normalizedPrefixDirectory, normalizedPrefixBase + fragmentDirectory) : normalizedPrefixDirectory;
10241025

10251026
const normalizedSuffix = normalizePath(parsed.suffix);
1027+
const declarationExtension = normalizedSuffix && getDeclarationEmitExtensionForPath("_" + normalizedSuffix);
1028+
const matchingSuffixes = declarationExtension ? [changeExtension(normalizedSuffix, declarationExtension), normalizedSuffix] : [normalizedSuffix];
10261029
// Need to normalize after combining: If we combinePaths("a", "../b"), we want "b" and not "a/../b".
10271030
const baseDirectory = normalizePath(combinePaths(packageDirectory, expandedPrefixDirectory));
10281031
const completePrefix = fragmentHasPath ? baseDirectory : ensureTrailingDirectorySeparator(baseDirectory) + normalizedPrefixBase;
@@ -1035,9 +1038,11 @@ function getModulesForPathsPattern(
10351038
// interpreted as "any character" can only return *too many* results as compared to the literal
10361039
// interpretation, so we can filter those superfluous results out via `trimPrefixAndSuffix` as we've always
10371040
// done.
1038-
const includeGlob = normalizedSuffix ? "**/*" + normalizedSuffix : "./*";
1041+
const includeGlobs = normalizedSuffix
1042+
? matchingSuffixes.map(suffix => "**/*" + suffix)
1043+
: ["./*"];
10391044

1040-
const matches = mapDefined(tryReadDirectory(host, baseDirectory, extensionOptions.extensionsToSearch, /*exclude*/ undefined, [includeGlob]), match => {
1045+
const matches = mapDefined(tryReadDirectory(host, baseDirectory, extensionOptions.extensionsToSearch, /*exclude*/ undefined, includeGlobs), match => {
10411046
const trimmedWithPattern = trimPrefixAndSuffix(match);
10421047
if (trimmedWithPattern) {
10431048
if (containsSlash(trimmedWithPattern)) {
@@ -1057,8 +1062,10 @@ function getModulesForPathsPattern(
10571062
return [...matches, ...directories];
10581063

10591064
function trimPrefixAndSuffix(path: string): string | undefined {
1060-
const inner = withoutStartAndEnd(normalizePath(path), completePrefix, normalizedSuffix);
1061-
return inner === undefined ? undefined : removeLeadingDirectorySeparator(inner);
1065+
return firstDefined(matchingSuffixes, suffix => {
1066+
const inner = withoutStartAndEnd(normalizePath(path), completePrefix, suffix);
1067+
return inner === undefined ? undefined : removeLeadingDirectorySeparator(inner);
1068+
});
10621069
}
10631070
}
10641071

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @module: nodenext
4+
5+
// @Filename: /node_modules/foo/package.json
6+
//// {
7+
//// "name": "foo",
8+
//// "exports": {
9+
//// "./*": "./dist/*.js"
10+
//// }
11+
//// }
12+
13+
// @Filename: /node_modules/foo/dist/blah.d.ts
14+
//// export const blah = 0;
15+
16+
// @Filename: /index.mts
17+
//// import { } from "foo//**/";
18+
19+
verify.completions({
20+
marker: "",
21+
isNewIdentifierLocation: true,
22+
exact: [
23+
{ name: "blah", kind: "script", kindModifiers: "" },
24+
]
25+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @module: nodenext
4+
5+
// @Filename: /node_modules/foo/package.json
6+
//// {
7+
//// "name": "foo",
8+
//// "exports": {
9+
//// "./*": "./dist/*.js"
10+
//// }
11+
//// }
12+
13+
// @Filename: /node_modules/foo/dist/blah.js
14+
//// export const blah = 0;
15+
16+
// @Filename: /node_modules/foo/dist/blah.d.ts
17+
//// export declare const blah: 0;
18+
19+
// @Filename: /index.mts
20+
//// import { } from "foo//**/";
21+
22+
verify.completions({
23+
marker: "",
24+
isNewIdentifierLocation: true,
25+
exact: [
26+
{ name: "blah", kind: "script", kindModifiers: "" },
27+
]
28+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @module: nodenext
4+
// @allowJs: true
5+
// @maxNodeModuleJsDepth: 1
6+
7+
// @Filename: /node_modules/foo/package.json
8+
//// {
9+
//// "name": "foo",
10+
//// "exports": {
11+
//// "./*": "./dist/*.js"
12+
//// }
13+
//// }
14+
15+
// @Filename: /node_modules/foo/dist/blah.js
16+
//// export const blah = 0;
17+
18+
// @Filename: /index.mts
19+
//// import { } from "foo//**/";
20+
21+
verify.completions({
22+
marker: "",
23+
isNewIdentifierLocation: true,
24+
exact: [
25+
{ name: "blah", kind: "script", kindModifiers: "" },
26+
]
27+
});

0 commit comments

Comments
 (0)