Skip to content

Commit d7cd405

Browse files
authored
feat(14751): show static members at the top of the list for a class like completion (microsoft#40428)
1 parent 3d235b4 commit d7cd405

24 files changed

+214
-82
lines changed

src/services/completions.ts

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
/* @internal */
22
namespace ts.Completions {
33
export enum SortText {
4-
LocationPriority = "0",
5-
OptionalMember = "1",
6-
MemberDeclaredBySpreadAssignment = "2",
7-
SuggestedClassMembers = "3",
8-
GlobalsOrKeywords = "4",
9-
AutoImportSuggestions = "5",
10-
JavascriptIdentifiers = "6"
4+
LocalDeclarationPriority = "0",
5+
LocationPriority = "1",
6+
OptionalMember = "2",
7+
MemberDeclaredBySpreadAssignment = "3",
8+
SuggestedClassMembers = "4",
9+
GlobalsOrKeywords = "5",
10+
AutoImportSuggestions = "6",
11+
JavascriptIdentifiers = "7"
1112
}
1213
export type Log = (message: string) => void;
1314

@@ -1270,7 +1271,7 @@ namespace ts.Completions {
12701271
else {
12711272
for (const symbol of type.getApparentProperties()) {
12721273
if (typeChecker.isValidPropertyAccessForCompletions(propertyAccess, type, symbol)) {
1273-
addPropertySymbol(symbol, /*insertAwait*/ false, insertQuestionDot);
1274+
addPropertySymbol(symbol, /* insertAwait */ false, insertQuestionDot);
12741275
}
12751276
}
12761277
}
@@ -1307,14 +1308,22 @@ namespace ts.Completions {
13071308
}
13081309
else if (preferences.includeCompletionsWithInsertText) {
13091310
addSymbolOriginInfo(symbol);
1311+
addSymbolSortInfo(symbol);
13101312
symbols.push(symbol);
13111313
}
13121314
}
13131315
else {
13141316
addSymbolOriginInfo(symbol);
1317+
addSymbolSortInfo(symbol);
13151318
symbols.push(symbol);
13161319
}
13171320

1321+
function addSymbolSortInfo(symbol: Symbol) {
1322+
if (isStaticProperty(symbol)) {
1323+
symbolToSortTextMap[getSymbolId(symbol)] = SortText.LocalDeclarationPriority;
1324+
}
1325+
}
1326+
13181327
function addSymbolOriginInfo(symbol: Symbol) {
13191328
if (preferences.includeCompletionsWithInsertText) {
13201329
if (insertAwait && !symbolToOriginInfoMap[getSymbolId(symbol)]) {
@@ -2817,4 +2826,8 @@ namespace ts.Completions {
28172826
}
28182827
return false;
28192828
}
2829+
2830+
function isStaticProperty(symbol: Symbol) {
2831+
return !!(symbol.valueDeclaration && getEffectiveModifierFlags(symbol.valueDeclaration) & ModifierFlags.Static && isClassLike(symbol.valueDeclaration.parent));
2832+
}
28202833
}

src/services/jsDoc.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ namespace ts.JsDoc {
164164
name: tagName,
165165
kind: ScriptElementKind.keyword,
166166
kindModifiers: "",
167-
sortText: "0",
167+
sortText: Completions.SortText.LocationPriority,
168168
};
169169
}));
170170
}
@@ -177,7 +177,7 @@ namespace ts.JsDoc {
177177
name: `@${tagName}`,
178178
kind: ScriptElementKind.keyword,
179179
kindModifiers: "",
180-
sortText: "0"
180+
sortText: Completions.SortText.LocationPriority
181181
};
182182
}));
183183
}
@@ -212,7 +212,7 @@ namespace ts.JsDoc {
212212
return undefined;
213213
}
214214

215-
return { name, kind: ScriptElementKind.parameterElement, kindModifiers: "", sortText: "0" };
215+
return { name, kind: ScriptElementKind.parameterElement, kindModifiers: "", sortText: Completions.SortText.LocationPriority };
216216
});
217217
}
218218

src/services/stringCompletions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ namespace ts.Completions.StringCompletions {
4242
name: type.value,
4343
kindModifiers: ScriptElementKindModifier.none,
4444
kind: ScriptElementKind.string,
45-
sortText: "0",
45+
sortText: SortText.LocationPriority,
4646
replacementSpan: getReplacementSpanForContextToken(contextToken)
4747
}));
4848
return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: completion.isNewIdentifier, optionalReplacementSpan, entries };

src/testRunner/unittests/tsserver/metadataInResponse.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ namespace ts.projectSystem {
5555
offset: aTs.content.indexOf("this.") + 1 + "this.".length
5656
};
5757
const expectedCompletionEntries: readonly protocol.CompletionEntry[] = [
58-
{ name: "foo", kind: ScriptElementKind.memberFunctionElement, kindModifiers: "", sortText: "0" },
59-
{ name: "prop", kind: ScriptElementKind.memberVariableElement, kindModifiers: "", sortText: "0" }
58+
{ name: "foo", kind: ScriptElementKind.memberFunctionElement, kindModifiers: "", sortText: Completions.SortText.LocationPriority },
59+
{ name: "prop", kind: ScriptElementKind.memberVariableElement, kindModifiers: "", sortText: Completions.SortText.LocationPriority }
6060
];
6161

6262
it("can pass through metadata when the command returns array", () => {

tests/cases/fourslash/cloduleAsBaseClass.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@
2525

2626
verify.completions({ marker: "1", exact: ["foo2", "foo"] });
2727
edit.insert('foo()');
28-
verify.completions({ marker: "2", exact: ["prototype", "bar2", "bar", "baz", "x", ...completion.functionMembers] });
28+
verify.completions({
29+
marker: "2",
30+
exact: [
31+
{ name: "prototype", sortText: completion.SortText.LocationPriority },
32+
{ name: "bar2", sortText: completion.SortText.LocalDeclarationPriority },
33+
{ name: "bar", sortText: completion.SortText.LocalDeclarationPriority },
34+
{ name: "baz", sortText: completion.SortText.LocationPriority },
35+
{ name: "x", sortText: completion.SortText.LocationPriority },
36+
...completion.functionMembers
37+
]
38+
});
2939
edit.insert('bar()');
3040
verify.noErrors();

tests/cases/fourslash/cloduleAsBaseClass2.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,16 @@
3131
verify.completions({ marker: "1", exact: ["foo2", "foo"] });
3232
edit.insert('foo()');
3333

34-
verify.completions({ marker: "2", includes: ["bar", "bar2", "baz", "x"], excludes: ["foo", "foo2"] });
34+
verify.completions({
35+
marker: "2",
36+
includes: [
37+
{ name: "bar", sortText: completion.SortText.LocalDeclarationPriority },
38+
{ name: "bar2", sortText: completion.SortText.LocalDeclarationPriority },
39+
{ name: "baz", sortText: completion.SortText.LocationPriority },
40+
{ name: "x", sortText: completion.SortText.LocationPriority }
41+
],
42+
excludes: ["foo", "foo2"]
43+
});
3544
edit.insert('bar()');
3645

3746
verify.noErrors();

tests/cases/fourslash/cloduleTypeOf1.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@
1414
//// }
1515
////}
1616

17-
verify.completions({ marker: "1", includes: ["f", "foo"] });
17+
verify.completions({
18+
marker: "1",
19+
includes: [
20+
{ name: "f", sortText: completion.SortText.LocationPriority },
21+
{ name: "foo", sortText: completion.SortText.LocalDeclarationPriority }
22+
]
23+
});
1824
edit.insert('foo(1);');
1925

2026
verify.completions({ marker: "2", includes: "x" });

tests/cases/fourslash/commentsClassMembers.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -190,13 +190,13 @@ verify.completions(
190190
{
191191
marker: ["30", "34", "36", "39", "41", "88"],
192192
exact: [
193-
"prototype",
194-
{ name: "s1", text: "(property) c1.s1: number", documentation: "s1 is static property of c1" },
195-
{ name: "s2", text: "(method) c1.s2(b: number): number", documentation: "static sum with property" },
196-
{ name: "s3", text: "(property) c1.s3: number", documentation: "static getter property\nsetter property 3" },
197-
{ name: "nc_s1", text: "(property) c1.nc_s1: number" },
198-
{ name: "nc_s2", text: "(method) c1.nc_s2(b: number): number" },
199-
{ name: "nc_s3", text: "(property) c1.nc_s3: number" },
193+
{ name: "prototype", sortText: completion.SortText.LocationPriority },
194+
{ name: "s1", text: "(property) c1.s1: number", documentation: "s1 is static property of c1", sortText: completion.SortText.LocalDeclarationPriority },
195+
{ name: "s2", text: "(method) c1.s2(b: number): number", documentation: "static sum with property", sortText: completion.SortText.LocalDeclarationPriority },
196+
{ name: "s3", text: "(property) c1.s3: number", documentation: "static getter property\nsetter property 3", sortText: completion.SortText.LocalDeclarationPriority },
197+
{ name: "nc_s1", text: "(property) c1.nc_s1: number", sortText: completion.SortText.LocalDeclarationPriority },
198+
{ name: "nc_s2", text: "(method) c1.nc_s2(b: number): number", sortText: completion.SortText.LocalDeclarationPriority },
199+
{ name: "nc_s3", text: "(property) c1.nc_s3: number", sortText: completion.SortText.LocalDeclarationPriority },
200200
...completion.functionMembers,
201201
],
202202
},

tests/cases/fourslash/completionListCladule.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@
1414

1515
goTo.marker("c1");
1616
edit.insert(".");
17-
verify.completions({ includes: ["x", "prototype", "staticMethod"] });
17+
verify.completions({
18+
includes: [
19+
{ name: "x", sortText: completion.SortText.LocationPriority },
20+
{ name: "prototype", sortText: completion.SortText.LocationPriority },
21+
{ name: "staticMethod", sortText: completion.SortText.LocalDeclarationPriority }
22+
]
23+
});
1824

1925
goTo.marker("c2");
2026
edit.insert(".");

tests/cases/fourslash/completionListClassMembers.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,27 @@
2626
verify.completions(
2727
{
2828
marker: "staticsInsideClassScope",
29-
exact: ["prototype", "privateStaticProperty", "publicStaticProperty", "privateStaticMethod", "publicStaticMethod", ...completion.functionMembers],
29+
exact: [
30+
{ name: "prototype", sortText: completion.SortText.LocationPriority },
31+
{ name: "privateStaticProperty", sortText: completion.SortText.LocalDeclarationPriority },
32+
{ name: "publicStaticProperty", sortText: completion.SortText.LocalDeclarationPriority },
33+
{ name: "privateStaticMethod", sortText: completion.SortText.LocalDeclarationPriority },
34+
{ name: "publicStaticMethod", sortText: completion.SortText.LocalDeclarationPriority },
35+
...completion.functionMembers
36+
],
3037
},
3138
{
3239
marker: "instanceMembersInsideClassScope",
3340
exact: ["privateInstanceMethod", "publicInstanceMethod", "privateProperty", "publicProperty"],
3441
},
3542
{
3643
marker: "staticsOutsideClassScope",
37-
exact: ["prototype", "publicStaticProperty", "publicStaticMethod", ...completion.functionMembers],
44+
exact: [
45+
{ name: "prototype", sortText: completion.SortText.LocationPriority },
46+
{ name: "publicStaticProperty", sortText: completion.SortText.LocalDeclarationPriority },
47+
{ name: "publicStaticMethod", sortText: completion.SortText.LocalDeclarationPriority },
48+
...completion.functionMembers
49+
],
3850
},
3951
{
4052
marker: "instanceMembersOutsideClassScope",

0 commit comments

Comments
 (0)