Skip to content

Commit 8aa39d6

Browse files
committed
Set sort text while adding sysmbols
1 parent e3b812a commit 8aa39d6

File tree

5 files changed

+49
-53
lines changed

5 files changed

+49
-53
lines changed

src/harness/fourslash.ts

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -841,16 +841,7 @@ namespace FourSlash {
841841
assert.equal(actual.hasAction, hasAction);
842842
assert.equal(actual.isRecommended, isRecommended);
843843
assert.equal(actual.source, source);
844-
845-
let isSortTextEqual: boolean;
846-
if (!sortText) {
847-
isSortTextEqual = [ts.Completions.SortText.LocationPriorityFulfilled, ts.Completions.SortText.LocationPriority].indexOf(actual.sortText as ts.Completions.SortText) !== -1
848-
|| (actual.kindModifiers === "optional" && actual.sortText === ts.Completions.SortText.LocationPriorityOptional);
849-
}
850-
else {
851-
isSortTextEqual = actual.sortText === sortText;
852-
}
853-
assert.equal(isSortTextEqual, true, this.messageAtLastKnownMarker(`Actual entry: ${JSON.stringify(actual)}`));
844+
assert.equal(actual.sortText, sortText || ts.Completions.SortText.LocationPriority, this.messageAtLastKnownMarker(`Actual entry: ${JSON.stringify(actual)}`));
854845

855846
if (text !== undefined) {
856847
const actualDetails = this.getCompletionEntryDetails(actual.name, actual.source)!;

src/services/completions.ts

Lines changed: 40 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
namespace ts.Completions {
33
export enum SortText {
44
LocationPriority = "0",
5-
LocationPriorityOptional = "1",
6-
LocationPriorityFulfilled = "2",
5+
OptionalMember = "1",
6+
MemberDeclaredBySpreadAssignment = "2",
77
SuggestedClassMembers = "3",
88
GlobalsOrKeywords = "4",
99
AutoImportSuggestions = "5",
@@ -105,7 +105,6 @@ namespace ts.Completions {
105105
isJsxInitializer,
106106
insideJsDocTagTypeExpression,
107107
symbolToSortTextMap,
108-
fulfilledSymbols,
109108
} = completionData;
110109

111110
if (location && location.parent && isJsxClosingElement(location.parent)) {
@@ -167,7 +166,6 @@ namespace ts.Completions {
167166
recommendedCompletion,
168167
symbolToOriginInfoMap,
169168
symbolToSortTextMap,
170-
fulfilledSymbols
171169
);
172170
}
173171

@@ -321,7 +319,6 @@ namespace ts.Completions {
321319
recommendedCompletion?: Symbol,
322320
symbolToOriginInfoMap?: SymbolOriginInfoMap,
323321
symbolToSortTextMap?: SymbolSortTextMap,
324-
fulfilledSymbols?: ReadonlyArray<Symbol>,
325322
): Map<true> {
326323
const start = timestamp();
327324
// Tracks unique names.
@@ -340,23 +337,9 @@ namespace ts.Completions {
340337
continue;
341338
}
342339

343-
let sortText = symbolToSortTextMap && symbolToSortTextMap[getSymbolId(symbol)];
344-
if (!sortText) {
345-
if (fulfilledSymbols && fulfilledSymbols.length > 0) {
346-
fulfilledSymbols.forEach(fulfilledSymbol => {
347-
if (fulfilledSymbol.name === symbol.name) {
348-
sortText = SortText.LocationPriorityFulfilled;
349-
}
350-
});
351-
}
352-
}
353-
if (!sortText) {
354-
sortText = SymbolDisplay.getSymbolModifiers(symbol) === "optional" ? SortText.LocationPriorityOptional : SortText.LocationPriority;
355-
}
356-
357340
const entry = createCompletionEntry(
358341
symbol,
359-
sortText,
342+
symbolToSortTextMap && symbolToSortTextMap[getSymbolId(symbol)] || SortText.LocationPriority,
360343
location,
361344
sourceFile,
362345
typeChecker,
@@ -366,7 +349,7 @@ namespace ts.Completions {
366349
recommendedCompletion,
367350
propertyAccessToConvert,
368351
isJsxInitializer,
369-
preferences,
352+
preferences
370353
);
371354
if (!entry) {
372355
continue;
@@ -600,7 +583,6 @@ namespace ts.Completions {
600583
readonly isJsxInitializer: IsJsxInitializer;
601584
readonly insideJsDocTagTypeExpression: boolean;
602585
readonly symbolToSortTextMap: SymbolSortTextMap;
603-
readonly fulfilledSymbols?: ReadonlyArray<Symbol>;
604586
}
605587
type Request = { readonly kind: CompletionDataKind.JsDocTagName | CompletionDataKind.JsDocTag } | { readonly kind: CompletionDataKind.JsDocParameterName, tag: JSDocParameterTag };
606588

@@ -892,7 +874,6 @@ namespace ts.Completions {
892874
let isNewIdentifierLocation = false;
893875
let keywordFilters = KeywordCompletionFilters.None;
894876
let symbols: Symbol[] = [];
895-
let fulfilledSymbols: Symbol[] | undefined = [];
896877
const symbolToOriginInfoMap: SymbolOriginInfoMap = [];
897878
const symbolToSortTextMap: SymbolSortTextMap = [];
898879

@@ -946,7 +927,6 @@ namespace ts.Completions {
946927
isJsxInitializer,
947928
insideJsDocTagTypeExpression,
948929
symbolToSortTextMap,
949-
fulfilledSymbols
950930
};
951931

952932
type JSDocTagWithTypeExpression = JSDocParameterTag | JSDocPropertyTag | JSDocReturnTag | JSDocTypeTag | JSDocTypedefTag;
@@ -1516,20 +1496,21 @@ namespace ts.Completions {
15161496
if (typeMembers && typeMembers.length > 0) {
15171497
// Add filtered items to the completion list
15181498
symbols = filterObjectMembersList(typeMembers, Debug.assertDefined(existingMembers));
1519-
if (existingMembers && existingMembers.length > 0) {
1520-
existingMembers.forEach(member => {
1521-
if (member.kind === SyntaxKind.SpreadAssignment) {
1522-
const expression = (<SpreadAssignment>member).expression;
1523-
const symbol = typeChecker.getSymbolAtLocation(expression);
1524-
const type = symbol && typeChecker.getTypeOfSymbolAtLocation(symbol, expression);
1525-
fulfilledSymbols = type && (<ObjectType>type).properties;
1526-
}
1527-
});
1528-
}
15291499
}
1500+
setSortTextToOptionalMember();
1501+
15301502
return GlobalsSearch.Success;
15311503
}
15321504

1505+
// Set SortText to OptionalMember if it is an optinoal member
1506+
function setSortTextToOptionalMember() {
1507+
symbols.forEach(m => {
1508+
if (SymbolDisplay.getSymbolModifiers(m) === "optional") {
1509+
symbolToSortTextMap[getSymbolId(m)] = symbolToSortTextMap[getSymbolId(m)] || SortText.OptionalMember;
1510+
}
1511+
});
1512+
}
1513+
15331514
/**
15341515
* Aggregates relevant symbols for completion in import clauses and export clauses
15351516
* whose declarations have a module specifier; for instance, symbols will be aggregated for
@@ -1898,6 +1879,7 @@ namespace ts.Completions {
18981879
return contextualMemberSymbols;
18991880
}
19001881

1882+
const fulfilledSymbols: Symbol[] = [];
19011883
const existingMemberNames = createUnderscoreEscapedMap<boolean>();
19021884
for (const m of existingMembers) {
19031885
// Ignore omitted expressions for missing members
@@ -1906,7 +1888,8 @@ namespace ts.Completions {
19061888
m.kind !== SyntaxKind.BindingElement &&
19071889
m.kind !== SyntaxKind.MethodDeclaration &&
19081890
m.kind !== SyntaxKind.GetAccessor &&
1909-
m.kind !== SyntaxKind.SetAccessor) {
1891+
m.kind !== SyntaxKind.SetAccessor &&
1892+
m.kind !== SyntaxKind.SpreadAssignment) {
19101893
continue;
19111894
}
19121895

@@ -1917,7 +1900,16 @@ namespace ts.Completions {
19171900

19181901
let existingName: __String | undefined;
19191902

1920-
if (isBindingElement(m) && m.propertyName) {
1903+
if (isSpreadAssignment(m)) {
1904+
const expression = m.expression;
1905+
const symbol = typeChecker.getSymbolAtLocation(expression);
1906+
const type = symbol && typeChecker.getTypeOfSymbolAtLocation(symbol, expression);
1907+
const properties = type && (<ObjectType>type).properties;
1908+
if (properties) {
1909+
fulfilledSymbols.push(...properties);
1910+
}
1911+
}
1912+
else if (isBindingElement(m) && m.propertyName) {
19211913
// include only identifiers in completion list
19221914
if (m.propertyName.kind === SyntaxKind.Identifier) {
19231915
existingName = m.propertyName.escapedText;
@@ -1934,7 +1926,18 @@ namespace ts.Completions {
19341926
existingMemberNames.set(existingName!, true); // TODO: GH#18217
19351927
}
19361928

1937-
return contextualMemberSymbols.filter(m => !existingMemberNames.get(m.escapedName));
1929+
const filteredSymbols = contextualMemberSymbols.filter(m => !existingMemberNames.get(m.escapedName));
1930+
1931+
// Set SortText to MemberDeclaredBySpreadAssignment if it is fulfilled by spread assignment
1932+
for (const fulfilledSymbol of fulfilledSymbols) {
1933+
for (const contextualMemberSymbol of filteredSymbols) {
1934+
if (contextualMemberSymbol.name === fulfilledSymbol.name) {
1935+
symbolToSortTextMap[getSymbolId(contextualMemberSymbol)] = SortText.MemberDeclaredBySpreadAssignment;
1936+
}
1937+
}
1938+
}
1939+
1940+
return filteredSymbols;
19381941
}
19391942

19401943
/**

tests/cases/fourslash/completionsPropertiesPriorities.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121
verify.completions({
2222
marker: ['a'],
2323
exact: [
24-
{ name: 'B', kindModifiers: 'optional', sortText: completion.SortText.LocationPriorityFulfilled, kind: 'property' },
25-
{ name: 'a', sortText: completion.SortText.LocationPriorityFulfilled, kind: 'property' },
26-
{ name: 'c', kindModifiers: 'optional', sortText: completion.SortText.LocationPriorityOptional, kind: 'property' },
24+
{ name: 'B', kindModifiers: 'optional', sortText: completion.SortText.MemberDeclaredBySpreadAssignment, kind: 'property' },
25+
{ name: 'a', sortText: completion.SortText.MemberDeclaredBySpreadAssignment, kind: 'property' },
26+
{ name: 'c', kindModifiers: 'optional', sortText: completion.SortText.OptionalMember, kind: 'property' },
2727
{ name: 'd', sortText: completion.SortText.LocationPriority, kind: 'property' }
2828
]
2929
});

tests/cases/fourslash/completionsWithOptionalProperties.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
verify.completions({
1515
marker: "",
16-
includes: ['world']
16+
exact: [
17+
{ name: "world", kind: "property", kindModifiers: "optional", sortText: completion.SortText.OptionalMember }
18+
]
1719
});
1820

tests/cases/fourslash/fourslash.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -672,8 +672,8 @@ declare namespace completion {
672672
type Entry = FourSlashInterface.ExpectedCompletionEntryObject;
673673
export const enum SortText {
674674
LocationPriority = "0",
675-
LocationPriorityOptional = "1",
676-
LocationPriorityFulfilled = "2",
675+
OptionalMember = "1",
676+
MemberDeclaredBySpreadAssignment = "2",
677677
SuggestedClassMembers = "3",
678678
GlobalsOrKeywords = "4",
679679
AutoImportSuggestions = "5",

0 commit comments

Comments
 (0)