Skip to content

Commit d68eba7

Browse files
author
Andy
authored
Fix ScriptElementKind for path mapping completions (#21695) (#21700)
* Fix ScriptElementKind for path mapping completions (#21695) * Fix lint
1 parent 4d04fa9 commit d68eba7

File tree

2 files changed

+48
-14
lines changed

2 files changed

+48
-14
lines changed

src/services/pathCompletions.ts

+19-14
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,10 @@ namespace ts.Completions.PathCompletions {
149149
for (const path in paths) {
150150
const patterns = paths[path];
151151
if (paths.hasOwnProperty(path) && patterns) {
152-
for (const pathCompletion of getCompletionsForPathMapping(path, patterns, fragment, baseUrl, fileExtensions, host)) {
152+
for (const { name, kind } of getCompletionsForPathMapping(path, patterns, fragment, baseUrl, fileExtensions, host)) {
153153
// Path mappings may provide a duplicate way to get to something we've already added, so don't add again.
154-
if (!result.some(entry => entry.name === pathCompletion)) {
155-
result.push(createCompletionEntryForModule(pathCompletion, ScriptElementKind.externalModuleName, span));
154+
if (!result.some(entry => entry.name === name)) {
155+
result.push(createCompletionEntryForModule(name, kind, span));
156156
}
157157
}
158158
}
@@ -177,24 +177,29 @@ namespace ts.Completions.PathCompletions {
177177
return result;
178178
}
179179

180+
interface NameAndKind {
181+
readonly name: string;
182+
readonly kind: ScriptElementKind.scriptElement | ScriptElementKind.directory;
183+
}
184+
180185
function getCompletionsForPathMapping(
181186
path: string, patterns: ReadonlyArray<string>, fragment: string, baseUrl: string, fileExtensions: ReadonlyArray<string>, host: LanguageServiceHost,
182-
): ReadonlyArray<string> {
187+
): ReadonlyArray<NameAndKind> {
183188
if (!endsWith(path, "*")) {
184189
// For a path mapping "foo": ["/x/y/z.ts"], add "foo" itself as a completion.
185-
return !stringContains(path, "*") && startsWith(path, fragment) ? [path] : emptyArray;
190+
return !stringContains(path, "*") && startsWith(path, fragment) ? [{ name: path, kind: ScriptElementKind.directory }] : emptyArray;
186191
}
187192

188193
const pathPrefix = path.slice(0, path.length - 1);
189194
if (!startsWith(fragment, pathPrefix)) {
190-
return [pathPrefix];
195+
return [{ name: pathPrefix, kind: ScriptElementKind.directory }];
191196
}
192197

193198
const remainingFragment = fragment.slice(pathPrefix.length);
194199
return flatMap(patterns, pattern => getModulesForPathsPattern(remainingFragment, baseUrl, pattern, fileExtensions, host));
195200
}
196201

197-
function getModulesForPathsPattern(fragment: string, baseUrl: string, pattern: string, fileExtensions: ReadonlyArray<string>, host: LanguageServiceHost): string[] | undefined {
202+
function getModulesForPathsPattern(fragment: string, baseUrl: string, pattern: string, fileExtensions: ReadonlyArray<string>, host: LanguageServiceHost): ReadonlyArray<NameAndKind> | undefined {
198203
if (!host.readDirectory) {
199204
return undefined;
200205
}
@@ -225,14 +230,14 @@ namespace ts.Completions.PathCompletions {
225230
// doesn't support. For now, this is safer but slower
226231
const includeGlob = normalizedSuffix ? "**/*" : "./*";
227232

228-
const matches = tryReadDirectory(host, baseDirectory, fileExtensions, /*exclude*/ undefined, [includeGlob]);
229-
const directories = tryGetDirectories(host, baseDirectory).map(d => combinePaths(baseDirectory, d));
233+
const matches = tryReadDirectory(host, baseDirectory, fileExtensions, /*exclude*/ undefined, [includeGlob]).map<NameAndKind>(name => ({ name, kind: ScriptElementKind.scriptElement }));
234+
const directories = tryGetDirectories(host, baseDirectory).map(d => combinePaths(baseDirectory, d)).map<NameAndKind>(name => ({ name, kind: ScriptElementKind.directory }));
230235

231236
// Trim away prefix and suffix
232-
return mapDefined(concatenate(matches, directories), match => {
233-
const normalizedMatch = normalizePath(match);
237+
return mapDefined<NameAndKind, NameAndKind>(concatenate(matches, directories), ({ name, kind }) => {
238+
const normalizedMatch = normalizePath(name);
234239
const inner = withoutStartAndEnd(normalizedMatch, completePrefix, normalizedSuffix);
235-
return inner !== undefined ? removeLeadingDirectorySeparator(removeFileExtension(inner)) : undefined;
240+
return inner !== undefined ? { name: removeLeadingDirectorySeparator(removeFileExtension(inner)), kind } : undefined;
236241
});
237242
}
238243

@@ -489,8 +494,8 @@ namespace ts.Completions.PathCompletions {
489494
return tryIOAndConsumeErrors(host, host.getDirectories, directoryName) || [];
490495
}
491496

492-
function tryReadDirectory(host: LanguageServiceHost, path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>): string[] | undefined | undefined {
493-
return tryIOAndConsumeErrors(host, host.readDirectory, path, extensions, exclude, include);
497+
function tryReadDirectory(host: LanguageServiceHost, path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>): ReadonlyArray<string> {
498+
return tryIOAndConsumeErrors(host, host.readDirectory, path, extensions, exclude, include) || emptyArray;
494499
}
495500

496501
function tryReadFile(host: LanguageServiceHost, path: string): string | undefined {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @Filename: /src/b.ts
4+
////not read
5+
6+
// @Filename: /src/dir/x.ts
7+
////not read
8+
9+
// @Filename: /src/a.ts
10+
////import {} from "./[|/*0*/|]";
11+
////import {} from "./[|/*1*/|]";
12+
13+
// @Filename: /tsconfig.json
14+
////{
15+
//// "compilerOptions": {
16+
//// "baseUrl": ".",
17+
//// "paths": {
18+
//// "foo/*": ["src/*"]
19+
//// }
20+
//// }
21+
////}
22+
23+
goTo.marker("0");
24+
verify.completionListContains("dir", undefined, undefined, "directory");
25+
verify.completionListContains("b", undefined, undefined, "script");
26+
27+
goTo.marker("1");
28+
verify.completionListContains("dir", undefined, undefined, "directory");
29+
verify.completionListContains("b", undefined, undefined, "script");

0 commit comments

Comments
 (0)