Skip to content

Commit 179d1cb

Browse files
committed
Add kinds to tests
1 parent 426545c commit 179d1cb

5 files changed

+68
-27
lines changed

src/services/stringCompletions.ts

+39-18
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,30 @@
11
/* @internal */
22
namespace ts.Completions.StringCompletions {
3+
interface NameAndKindSet {
4+
add(value: NameAndKind): void;
5+
has(name: string): boolean;
6+
values(): Iterator<NameAndKind>;
7+
}
8+
const kindPrecedence = {
9+
[ScriptElementKind.directory]: 0,
10+
[ScriptElementKind.scriptElement]: 1,
11+
[ScriptElementKind.externalModuleName]: 2,
12+
};
13+
function createNameAndKindSet(): NameAndKindSet {
14+
const map = new Map<string, NameAndKind>();
15+
function add(value: NameAndKind) {
16+
const existing = map.get(value.name);
17+
if (!existing || kindPrecedence[existing.kind] < kindPrecedence[value.kind]) {
18+
map.set(value.name, value);
19+
}
20+
}
21+
return {
22+
add,
23+
has: map.has.bind(map),
24+
values: map.values.bind(map),
25+
};
26+
}
27+
328
export function getStringLiteralCompletions(
429
sourceFile: SourceFile,
530
position: number,
@@ -435,7 +460,7 @@ namespace ts.Completions.StringCompletions {
435460
host: LanguageServiceHost,
436461
exclude?: string,
437462
result = createNameAndKindSet()
438-
): Set<NameAndKind> {
463+
): NameAndKindSet {
439464
if (fragment === undefined) {
440465
fragment = "";
441466
}
@@ -526,7 +551,7 @@ namespace ts.Completions.StringCompletions {
526551

527552
/** @returns whether `fragment` was a match for any `paths` (which should indicate whether any other path completions should be offered) */
528553
function addCompletionEntriesFromPaths(
529-
result: Set<NameAndKind>,
554+
result: NameAndKindSet,
530555
fragment: string,
531556
baseDirectory: string,
532557
extensionOptions: ExtensionOptions,
@@ -546,7 +571,7 @@ namespace ts.Completions.StringCompletions {
546571

547572
/** @returns whether `fragment` was a match for any `paths` (which should indicate whether any other path completions should be offered) */
548573
function addCompletionEntriesFromPathsOrExports(
549-
result: Set<NameAndKind>,
574+
result: NameAndKindSet,
550575
fragment: string,
551576
baseDirectory: string,
552577
extensionOptions: ExtensionOptions,
@@ -595,10 +620,6 @@ namespace ts.Completions.StringCompletions {
595620
return matchedPath !== undefined;
596621
}
597622

598-
function createNameAndKindSet() {
599-
return createSet<NameAndKind>(element => +generateDjb2Hash(element.name), (a, b) => a.name === b.name);
600-
}
601-
602623
/**
603624
* Check all of the declared modules and those in node modules. Possible sources of modules:
604625
* Modules that are found by the type checker
@@ -642,7 +663,7 @@ namespace ts.Completions.StringCompletions {
642663
if (fragmentDirectory === undefined) {
643664
for (const moduleName of enumerateNodeModulesVisibleToScript(host, scriptPath)) {
644665
const moduleResult = nameAndKind(moduleName, ScriptElementKind.externalModuleName, /*extension*/ undefined);
645-
if (!result.has(moduleResult)) {
666+
if (!result.has(moduleResult.name)) {
646667
foundGlobal = true;
647668
result.add(moduleResult);
648669
}
@@ -733,20 +754,20 @@ namespace ts.Completions.StringCompletions {
733754
): readonly NameAndKind[] {
734755
if (!endsWith(path, "*")) {
735756
// For a path mapping "foo": ["/x/y/z.ts"], add "foo" itself as a completion.
736-
return !stringContains(path, "*") ? justPathMappingName(path) : emptyArray;
757+
return !stringContains(path, "*") ? justPathMappingName(path, ScriptElementKind.scriptElement) : emptyArray;
737758
}
738759

739760
const pathPrefix = path.slice(0, path.length - 1);
740761
const remainingFragment = tryRemovePrefix(fragment, pathPrefix);
741762
if (remainingFragment === undefined) {
742763
const starIsFullPathComponent = path[path.length - 2] === "/";
743-
return starIsFullPathComponent ? justPathMappingName(pathPrefix) : flatMap(patterns, pattern =>
764+
return starIsFullPathComponent ? justPathMappingName(pathPrefix, ScriptElementKind.directory) : flatMap(patterns, pattern =>
744765
getModulesForPathsPattern("", packageDirectory, pattern, extensionOptions, host)?.map(({ name, ...rest }) => ({ name: pathPrefix + name, ...rest })));
745766
}
746767
return flatMap(patterns, pattern => getModulesForPathsPattern(remainingFragment, packageDirectory, pattern, extensionOptions, host));
747768

748-
function justPathMappingName(name: string): readonly NameAndKind[] {
749-
return startsWith(name, fragment) ? [directoryResult(removeTrailingDirectorySeparator(name))] : emptyArray;
769+
function justPathMappingName(name: string, kind: ScriptElementKind.directory | ScriptElementKind.scriptElement): readonly NameAndKind[] {
770+
return startsWith(name, fragment) ? [{ name: removeTrailingDirectorySeparator(name), kind, extension: undefined }] : emptyArray;
750771
}
751772
}
752773

@@ -789,12 +810,12 @@ namespace ts.Completions.StringCompletions {
789810
const includeGlob = suffixHasFilename ? "**/*" : "./*";
790811

791812
const matches = mapDefined(tryReadDirectory(host, baseDirectory, extensionOptions.extensions, /*exclude*/ undefined, [includeGlob]), match => {
792-
const basename = trimPrefixAndSuffix(match);
793-
if (basename) {
794-
if (containsSlash(basename)) {
795-
return directoryResult(getPathComponents(basename)[0]);
813+
const trimmedWithPattern = trimPrefixAndSuffix(match);
814+
if (trimmedWithPattern) {
815+
if (containsSlash(trimmedWithPattern)) {
816+
return directoryResult(getPathComponents(trimmedWithPattern)[0]);
796817
}
797-
const { name, extension } = getFilenameWithExtensionOption(basename, host.getCompilationSettings(), extensionOptions.includeExtensionsOption);
818+
const { name, extension } = getFilenameWithExtensionOption(trimmedWithPattern, host.getCompilationSettings(), extensionOptions.includeExtensionsOption);
798819
return nameAndKind(name, ScriptElementKind.scriptElement, extension);
799820
}
800821
});
@@ -858,7 +879,7 @@ namespace ts.Completions.StringCompletions {
858879
return addReplacementSpans(toComplete, range.pos + prefix.length, arrayFrom(names.values()));
859880
}
860881

861-
function getCompletionEntriesFromTypings(host: LanguageServiceHost, options: CompilerOptions, scriptPath: string, fragmentDirectory: string | undefined, extensionOptions: ExtensionOptions, result = createNameAndKindSet()): Set<NameAndKind> {
882+
function getCompletionEntriesFromTypings(host: LanguageServiceHost, options: CompilerOptions, scriptPath: string, fragmentDirectory: string | undefined, extensionOptions: ExtensionOptions, result = createNameAndKindSet()): NameAndKindSet {
862883
// Check for typings specified in compiler options
863884
const seen = new Map<string, true>();
864885

tests/cases/fourslash/pathCompletionsPackageJsonExportsWildcard1.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,9 @@
4242
verify.completions({
4343
marker: "",
4444
isNewIdentifierLocation: true,
45-
exact: ["blah", "index", "arguments"]
45+
exact: [
46+
{ name: "blah", kind: "script", kindModifiers: "" },
47+
{ name: "index", kind: "script", kindModifiers: "" },
48+
{ name: "arguments", kind: "script", kindModifiers: "" },
49+
]
4650
});

tests/cases/fourslash/pathCompletionsPackageJsonExportsWildcard2.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,19 @@
2424
verify.completions({
2525
marker: "",
2626
isNewIdentifierLocation: true,
27-
exact: ["action"]
27+
exact: [{ name: "action", kind: "directory" }]
2828
});
2929

3030
edit.insert("action/");
3131

3232
verify.completions({
3333
isNewIdentifierLocation: true,
34-
exact: ["pageObjects"],
34+
exact: [{ name: "pageObjects", kind: "directory" }],
3535
});
3636

3737
edit.insert("pageObjects/");
3838

3939
verify.completions({
4040
isNewIdentifierLocation: true,
41-
exact: ["actionRenderer"],
41+
exact: [{ name: "actionRenderer", kind: "script" }],
4242
});

tests/cases/fourslash/pathCompletionsPackageJsonExportsWildcard3.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,16 @@
3030
verify.completions({
3131
marker: "",
3232
isNewIdentifierLocation: true,
33-
exact: ["component-blah", "component-index", "component-subfolder"],
33+
exact: [
34+
{ name: "component-blah", kind: "script" },
35+
{ name: "component-index", kind: "script" },
36+
{ name: "component-subfolder", kind: "directory" },
37+
],
3438
});
3539

3640
edit.insert("component-subfolder/");
3741

3842
verify.completions({
3943
isNewIdentifierLocation: true,
40-
exact: ["one"],
44+
exact: [{ name: "one", kind: "script" }],
4145
});

tests/cases/fourslash/pathCompletionsPackageJsonExportsWildcard4.ts

+15-3
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,31 @@
3434
verify.completions({
3535
marker: "",
3636
isNewIdentifierLocation: true,
37-
exact: ["blah.js", "index.js", "foo", "subfolder", "bar", "exact-match"],
37+
exact: [
38+
{ name: "blah.js", kind: "script", kindModifiers: ".js" },
39+
{ name: "index.js", kind: "script", kindModifiers: ".js" },
40+
{ name: "foo", kind: "directory" },
41+
{ name: "subfolder", kind: "directory" },
42+
{ name: "bar", kind: "directory" },
43+
{ name: "exact-match", kind: "script" },
44+
],
3845
});
3946

4047
edit.insert("foo/");
4148

4249
verify.completions({
4350
isNewIdentifierLocation: true,
44-
exact: ["blah.js", "index.js", "foo", "subfolder"],
51+
exact: [
52+
{ name: "blah.js", kind: "script", kindModifiers: ".js" },
53+
{ name: "index.js", kind: "script", kindModifiers: ".js" },
54+
{ name: "foo", kind: "directory" },
55+
{ name: "subfolder", kind: "directory" },
56+
],
4557
});
4658

4759
edit.insert("foo/");
4860

4961
verify.completions({
5062
isNewIdentifierLocation: true,
51-
exact: ["onlyInFooFolder.js"],
63+
exact: [{ name: "onlyInFooFolder.js", kind: "script", kindModifiers: ".js" }],
5264
});

0 commit comments

Comments
 (0)