feat(14751): show static members at the top of the list for a class like completion (#40428)

This commit is contained in:
Alex T
2020-09-12 00:48:24 +03:00
committed by GitHub
parent 3d235b42a0
commit d7cd405bb2
24 changed files with 214 additions and 82 deletions
+21 -8
View File
@@ -1,13 +1,14 @@
/* @internal */
namespace ts.Completions {
export enum SortText {
LocationPriority = "0",
OptionalMember = "1",
MemberDeclaredBySpreadAssignment = "2",
SuggestedClassMembers = "3",
GlobalsOrKeywords = "4",
AutoImportSuggestions = "5",
JavascriptIdentifiers = "6"
LocalDeclarationPriority = "0",
LocationPriority = "1",
OptionalMember = "2",
MemberDeclaredBySpreadAssignment = "3",
SuggestedClassMembers = "4",
GlobalsOrKeywords = "5",
AutoImportSuggestions = "6",
JavascriptIdentifiers = "7"
}
export type Log = (message: string) => void;
@@ -1270,7 +1271,7 @@ namespace ts.Completions {
else {
for (const symbol of type.getApparentProperties()) {
if (typeChecker.isValidPropertyAccessForCompletions(propertyAccess, type, symbol)) {
addPropertySymbol(symbol, /*insertAwait*/ false, insertQuestionDot);
addPropertySymbol(symbol, /* insertAwait */ false, insertQuestionDot);
}
}
}
@@ -1307,14 +1308,22 @@ namespace ts.Completions {
}
else if (preferences.includeCompletionsWithInsertText) {
addSymbolOriginInfo(symbol);
addSymbolSortInfo(symbol);
symbols.push(symbol);
}
}
else {
addSymbolOriginInfo(symbol);
addSymbolSortInfo(symbol);
symbols.push(symbol);
}
function addSymbolSortInfo(symbol: Symbol) {
if (isStaticProperty(symbol)) {
symbolToSortTextMap[getSymbolId(symbol)] = SortText.LocalDeclarationPriority;
}
}
function addSymbolOriginInfo(symbol: Symbol) {
if (preferences.includeCompletionsWithInsertText) {
if (insertAwait && !symbolToOriginInfoMap[getSymbolId(symbol)]) {
@@ -2817,4 +2826,8 @@ namespace ts.Completions {
}
return false;
}
function isStaticProperty(symbol: Symbol) {
return !!(symbol.valueDeclaration && getEffectiveModifierFlags(symbol.valueDeclaration) & ModifierFlags.Static && isClassLike(symbol.valueDeclaration.parent));
}
}
+3 -3
View File
@@ -164,7 +164,7 @@ namespace ts.JsDoc {
name: tagName,
kind: ScriptElementKind.keyword,
kindModifiers: "",
sortText: "0",
sortText: Completions.SortText.LocationPriority,
};
}));
}
@@ -177,7 +177,7 @@ namespace ts.JsDoc {
name: `@${tagName}`,
kind: ScriptElementKind.keyword,
kindModifiers: "",
sortText: "0"
sortText: Completions.SortText.LocationPriority
};
}));
}
@@ -212,7 +212,7 @@ namespace ts.JsDoc {
return undefined;
}
return { name, kind: ScriptElementKind.parameterElement, kindModifiers: "", sortText: "0" };
return { name, kind: ScriptElementKind.parameterElement, kindModifiers: "", sortText: Completions.SortText.LocationPriority };
});
}
+1 -1
View File
@@ -42,7 +42,7 @@ namespace ts.Completions.StringCompletions {
name: type.value,
kindModifiers: ScriptElementKindModifier.none,
kind: ScriptElementKind.string,
sortText: "0",
sortText: SortText.LocationPriority,
replacementSpan: getReplacementSpanForContextToken(contextToken)
}));
return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: completion.isNewIdentifier, optionalReplacementSpan, entries };
@@ -55,8 +55,8 @@ namespace ts.projectSystem {
offset: aTs.content.indexOf("this.") + 1 + "this.".length
};
const expectedCompletionEntries: readonly protocol.CompletionEntry[] = [
{ name: "foo", kind: ScriptElementKind.memberFunctionElement, kindModifiers: "", sortText: "0" },
{ name: "prop", kind: ScriptElementKind.memberVariableElement, kindModifiers: "", sortText: "0" }
{ name: "foo", kind: ScriptElementKind.memberFunctionElement, kindModifiers: "", sortText: Completions.SortText.LocationPriority },
{ name: "prop", kind: ScriptElementKind.memberVariableElement, kindModifiers: "", sortText: Completions.SortText.LocationPriority }
];
it("can pass through metadata when the command returns array", () => {
+11 -1
View File
@@ -25,6 +25,16 @@
verify.completions({ marker: "1", exact: ["foo2", "foo"] });
edit.insert('foo()');
verify.completions({ marker: "2", exact: ["prototype", "bar2", "bar", "baz", "x", ...completion.functionMembers] });
verify.completions({
marker: "2",
exact: [
{ name: "prototype", sortText: completion.SortText.LocationPriority },
{ name: "bar2", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "bar", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "baz", sortText: completion.SortText.LocationPriority },
{ name: "x", sortText: completion.SortText.LocationPriority },
...completion.functionMembers
]
});
edit.insert('bar()');
verify.noErrors();
+10 -1
View File
@@ -31,7 +31,16 @@
verify.completions({ marker: "1", exact: ["foo2", "foo"] });
edit.insert('foo()');
verify.completions({ marker: "2", includes: ["bar", "bar2", "baz", "x"], excludes: ["foo", "foo2"] });
verify.completions({
marker: "2",
includes: [
{ name: "bar", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "bar2", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "baz", sortText: completion.SortText.LocationPriority },
{ name: "x", sortText: completion.SortText.LocationPriority }
],
excludes: ["foo", "foo2"]
});
edit.insert('bar()');
verify.noErrors();
+7 -1
View File
@@ -14,7 +14,13 @@
//// }
////}
verify.completions({ marker: "1", includes: ["f", "foo"] });
verify.completions({
marker: "1",
includes: [
{ name: "f", sortText: completion.SortText.LocationPriority },
{ name: "foo", sortText: completion.SortText.LocalDeclarationPriority }
]
});
edit.insert('foo(1);');
verify.completions({ marker: "2", includes: "x" });
@@ -190,13 +190,13 @@ verify.completions(
{
marker: ["30", "34", "36", "39", "41", "88"],
exact: [
"prototype",
{ name: "s1", text: "(property) c1.s1: number", documentation: "s1 is static property of c1" },
{ name: "s2", text: "(method) c1.s2(b: number): number", documentation: "static sum with property" },
{ name: "s3", text: "(property) c1.s3: number", documentation: "static getter property\nsetter property 3" },
{ name: "nc_s1", text: "(property) c1.nc_s1: number" },
{ name: "nc_s2", text: "(method) c1.nc_s2(b: number): number" },
{ name: "nc_s3", text: "(property) c1.nc_s3: number" },
{ name: "prototype", sortText: completion.SortText.LocationPriority },
{ name: "s1", text: "(property) c1.s1: number", documentation: "s1 is static property of c1", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "s2", text: "(method) c1.s2(b: number): number", documentation: "static sum with property", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "s3", text: "(property) c1.s3: number", documentation: "static getter property\nsetter property 3", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "nc_s1", text: "(property) c1.nc_s1: number", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "nc_s2", text: "(method) c1.nc_s2(b: number): number", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "nc_s3", text: "(property) c1.nc_s3: number", sortText: completion.SortText.LocalDeclarationPriority },
...completion.functionMembers,
],
},
@@ -14,7 +14,13 @@
goTo.marker("c1");
edit.insert(".");
verify.completions({ includes: ["x", "prototype", "staticMethod"] });
verify.completions({
includes: [
{ name: "x", sortText: completion.SortText.LocationPriority },
{ name: "prototype", sortText: completion.SortText.LocationPriority },
{ name: "staticMethod", sortText: completion.SortText.LocalDeclarationPriority }
]
});
goTo.marker("c2");
edit.insert(".");
@@ -26,7 +26,14 @@
verify.completions(
{
marker: "staticsInsideClassScope",
exact: ["prototype", "privateStaticProperty", "publicStaticProperty", "privateStaticMethod", "publicStaticMethod", ...completion.functionMembers],
exact: [
{ name: "prototype", sortText: completion.SortText.LocationPriority },
{ name: "privateStaticProperty", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "publicStaticProperty", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "privateStaticMethod", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "publicStaticMethod", sortText: completion.SortText.LocalDeclarationPriority },
...completion.functionMembers
],
},
{
marker: "instanceMembersInsideClassScope",
@@ -34,7 +41,12 @@ verify.completions(
},
{
marker: "staticsOutsideClassScope",
exact: ["prototype", "publicStaticProperty", "publicStaticMethod", ...completion.functionMembers],
exact: [
{ name: "prototype", sortText: completion.SortText.LocationPriority },
{ name: "publicStaticProperty", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "publicStaticMethod", sortText: completion.SortText.LocalDeclarationPriority },
...completion.functionMembers
],
},
{
marker: "instanceMembersOutsideClassScope",
@@ -5,5 +5,8 @@
////Foo./**/;
/////*1*/var bar;
verify.completions({ marker: "", includes: "fun" });
verify.completions({
marker: "",
includes: [{ name: "fun", sortText: completion.SortText.LocalDeclarationPriority }]
});
verify.not.errorExistsAfterMarker("1");
@@ -9,16 +9,19 @@
//// method() { }
//// static staticMethod() { }
////}
////class test1 extends Foo./*1*/ {}
////class test2 implements IFoo./*2*/ {}
////interface test3 extends IFoo./*3*/ {}
////interface test4 implements Foo./*4*/ {}
verify.completions(
{ marker: "1", exact: ["prototype", "staticMethod", ...completion.functionMembers] },
{
marker: "1",
exact: [
{ name: "prototype", sortText: completion.SortText.LocationPriority },
{ name: "staticMethod", sortText: completion.SortText.LocalDeclarationPriority },
...completion.functionMembers
]
},
{ marker: ["2", "3", "4"], exact: undefined },
);
@@ -39,7 +39,14 @@ verify.completions(
{ marker: ["1", "7"], exact: ["F", "C", "E", "N", "V", "A"] },
{ marker: ["1Type", "7Type"], exact: ["I", "C", "E", "A"] },
// Class C
{ marker: "2", exact: ["prototype", "property", ...completion.functionMembers] },
{
marker: "2",
exact: [
{ name: "prototype", sortText: completion.SortText.LocationPriority },
{ name: "property", sortText: completion.SortText.LocalDeclarationPriority },
...completion.functionMembers
]
},
// Enum E
{ marker: "3", exact: "value" },
// Module N
@@ -0,0 +1,17 @@
/// <reference path='fourslash.ts'/>
////class Foo {
//// static a() {}
//// static b() {}
////}
////Foo./**/
verify.completions({
marker: "",
exact: [
{ name: "prototype", sortText: completion.SortText.LocationPriority },
{ name: "a", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "b", sortText: completion.SortText.LocalDeclarationPriority },
...completion.functionMembers
]
});
@@ -29,11 +29,27 @@ verify.completions(
{
marker: ["1", "2"],
// Same class, everything is visible
includes: ["privateMethod", "privateProperty", "protectedMethod", "protectedProperty", "publicMethod", "publicProperty", "protectedOverriddenMethod", "protectedOverriddenProperty"],
includes: [
{ name: "privateMethod", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "privateProperty", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "protectedMethod", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "protectedProperty", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "publicMethod", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "publicProperty", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "protectedOverriddenMethod", sortText: completion.SortText.LocalDeclarationPriority},
{ name: "protectedOverriddenProperty", sortText: completion.SortText.LocalDeclarationPriority }
],
},
{
marker: "3",
includes: ["privateMethod", "privateProperty", "protectedMethod", "protectedProperty", "publicMethod", "publicProperty"],
includes: [
{ name: "privateMethod", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "privateProperty", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "protectedMethod", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "protectedProperty", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "publicMethod", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "publicProperty", sortText: completion.SortText.LocalDeclarationPriority }
],
// Can not access protected properties overridden in subclass
excludes: ["protectedOverriddenMethod", "protectedOverriddenProperty"],
},
@@ -31,27 +31,27 @@ verify.completions(
// Same class, everything is visible
marker: ["1"],
exact: [
"prototype",
"protectedMethod",
"protectedProperty",
"publicMethod",
"publicProperty",
"protectedOverriddenMethod",
"protectedOverriddenProperty",
{ name: "prototype", sortText: completion.SortText.LocationPriority },
{ name: "protectedMethod", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "protectedProperty", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "publicMethod", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "publicProperty", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "protectedOverriddenMethod", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "protectedOverriddenProperty", sortText: completion.SortText.LocalDeclarationPriority},
...completion.functionMembers,
],
},
{
marker: ["2", "3"],
exact: [
"prototype",
"protectedOverriddenMethod",
"protectedOverriddenProperty",
"test",
"protectedMethod",
"protectedProperty",
"publicMethod",
"publicProperty",
{ name: "prototype", sortText: completion.SortText.LocationPriority },
{ name: "protectedOverriddenMethod", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "protectedOverriddenProperty", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "test", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "protectedMethod", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "protectedProperty", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "publicMethod", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "publicProperty", sortText: completion.SortText.LocalDeclarationPriority },
...completion.functionMembers,
],
},
@@ -59,13 +59,13 @@ verify.completions(
// only public and protected methods of the base class are accessible through super
marker: "4",
exact: [
"protectedMethod",
"publicMethod",
"protectedOverriddenMethod",
"apply",
"call",
"bind",
"toString",
{ name: "protectedMethod", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "publicMethod", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "protectedOverriddenMethod", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "apply", sortText: completion.SortText.LocationPriority },
{ name: "call", sortText: completion.SortText.LocationPriority },
{ name: "bind", sortText: completion.SortText.LocationPriority },
{ name: "toString", sortText: completion.SortText.LocationPriority },
],
},
);
@@ -25,5 +25,10 @@
// Only public properties are visible outside the class
verify.completions({
marker: ["1", "2"],
exact: ["prototype", "publicMethod", "publicProperty", ...completion.functionMembers],
exact: [
{ name: "prototype", sortText: completion.SortText.LocationPriority },
{ name: "publicMethod", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "publicProperty", sortText: completion.SortText.LocalDeclarationPriority },
...completion.functionMembers
],
});
@@ -26,18 +26,22 @@
////}
//// Derived./*2*/
const publicCompletions: ReadonlyArray<FourSlashInterface.ExpectedCompletionEntry> = ["publicMethod", "publicProperty", ...completion.functionMembers];
const publicCompletions: ReadonlyArray<FourSlashInterface.ExpectedCompletionEntry> = [
{ name: "publicMethod", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "publicProperty", sortText: completion.SortText.LocalDeclarationPriority },
...completion.functionMembers
];
verify.completions(
{
// Sub class, everything but private is visible
marker: "1",
exact: [
"prototype",
"protectedOverriddenMethod",
"protectedOverriddenProperty",
"protectedMethod",
"protectedProperty",
{ name: "prototype", sortText: completion.SortText.LocationPriority },
{ name: "protectedOverriddenMethod", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "protectedOverriddenProperty", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "protectedMethod", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "protectedProperty", sortText: completion.SortText.LocalDeclarationPriority },
...publicCompletions
],
},
@@ -45,9 +49,9 @@ verify.completions(
// Can see protected methods elevated to public
marker: "2",
exact: [
"prototype",
"protectedOverriddenMethod",
"protectedOverriddenProperty",
{ name: "prototype", sortText: completion.SortText.LocationPriority },
{ name: "protectedOverriddenMethod", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "protectedOverriddenProperty", sortText: completion.SortText.LocalDeclarationPriority },
...publicCompletions,
],
},
@@ -15,8 +15,12 @@
////A./*3*/
goTo.eachMarker((_, i) => {
const all = ["foo", "bar", "baz"];
verify.completions({ includes: all.slice(0, 3 - i), excludes: all.slice(3 - i) });
const all = [
{ name: "foo", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "bar", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "baz", sortText: completion.SortText.LocalDeclarationPriority }
];
verify.completions({ includes: all.slice(0, 3 - i), excludes: all.slice(3 - i).map(e => e.name) });
edit.insert("foo;");
});
@@ -14,5 +14,12 @@
verify.completions(
{ marker: "type", exact: "T" },
{ marker: "value", exact: ["prototype", "m", ...completion.functionMembers] },
{
marker: "value",
exact: [
{ name: "prototype", sortText: completion.SortText.LocationPriority },
{ name: "m", sortText: completion.SortText.LocalDeclarationPriority },
...completion.functionMembers
]
},
);
+8 -7
View File
@@ -769,13 +769,14 @@ declare function classification(format: "2020"): FourSlashInterface.ModernClassi
declare namespace completion {
type Entry = FourSlashInterface.ExpectedCompletionEntryObject;
export const enum SortText {
LocationPriority = "0",
OptionalMember = "1",
MemberDeclaredBySpreadAssignment = "2",
SuggestedClassMembers = "3",
GlobalsOrKeywords = "4",
AutoImportSuggestions = "5",
JavascriptIdentifiers = "6"
LocalDeclarationPriority = "0",
LocationPriority = "1",
OptionalMember = "2",
MemberDeclaredBySpreadAssignment = "3",
SuggestedClassMembers = "4",
GlobalsOrKeywords = "5",
AutoImportSuggestions = "6",
JavascriptIdentifiers = "7"
}
export const enum CompletionSource {
ThisProperty = "ThisProperty/"
@@ -70,8 +70,8 @@ verify.completions(
{
marker: "valueMemberOfFoo",
exact: [
"prototype",
{ name: "method1", kind: "method", kindModifiers: "static" },
{ name: "prototype", sortText: completion.SortText.LocationPriority },
{ name: "method1", kind: "method", kindModifiers: "static", sortText: completion.SortText.LocalDeclarationPriority },
...completion.functionMembers,
],
},
@@ -5,4 +5,4 @@
////Foo./**/;
/////*1*/var bar;
verify.completions({ marker: "", includes: "fun" });
verify.completions({ marker: "", includes: [{ name: "fun", sortText: completion.SortText.LocalDeclarationPriority }] });
+10 -1
View File
@@ -21,7 +21,16 @@
verify.completions(
{ marker: "1", includes: "C" },
{ marker: ["2", "4"], exact: ["prototype", "boo", "x", "foo", ...completion.functionMembers] },
{
marker: ["2", "4"],
exact: [
{ name: "prototype", sortText: completion.SortText.LocationPriority },
{ name: "boo", sortText: completion.SortText.LocalDeclarationPriority },
{ name: "x", sortText: completion.SortText.LocationPriority },
{ name: "foo", sortText: completion.SortText.LocationPriority },
...completion.functionMembers
]
},
{ marker: "3", exact: ["foo", "bar"] },
);
verify.noErrors();