Skip to content

Commit 7c9cbdb

Browse files
committed
WIP: modify sort text system
1 parent b9cb703 commit 7c9cbdb

File tree

3 files changed

+63
-58
lines changed

3 files changed

+63
-58
lines changed

src/harness/fourslashInterfaceImpl.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -963,7 +963,7 @@ namespace FourSlashInterface {
963963
name,
964964
kind: "function",
965965
kindModifiers: "deprecated,declare",
966-
sortText: SortText.DeprecatedGlobalsOrKeywords
966+
sortText: "z15" as SortText,
967967
});
968968
const varEntry = (name: string): ExpectedCompletionEntryObject => ({
969969
name,
@@ -992,7 +992,7 @@ namespace FourSlashInterface {
992992
name,
993993
kind: "method",
994994
kindModifiers: "deprecated,declare",
995-
sortText: SortText.DeprecatedLocationPriority
995+
sortText: "z11" as SortText,
996996
});
997997
const propertyEntry = (name: string): ExpectedCompletionEntryObject => ({
998998
name,

src/services/completions.ts

Lines changed: 50 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,6 @@ namespace ts.Completions {
1818
GlobalsOrKeywords = "15",
1919
AutoImportSuggestions = "16",
2020
JavascriptIdentifiers = "17",
21-
DeprecatedLocalDeclarationPriority = "18",
22-
DeprecatedLocationPriority = "19",
23-
DeprecatedOptionalMember = "20",
24-
DeprecatedMemberDeclaredBySpreadAssignment = "21",
25-
DeprecatedSuggestedClassMembers = "22",
26-
DeprecatedGlobalsOrKeywords = "23",
27-
DeprecatedAutoImportSuggestions = "24"
28-
}
29-
30-
const enum SortTextId {
31-
LocalDeclarationPriority = 10,
32-
LocationPriority = 11,
33-
OptionalMember = 12,
34-
MemberDeclaredBySpreadAssignment = 13,
35-
SuggestedClassMembers = 14,
36-
GlobalsOrKeywords = 15,
37-
AutoImportSuggestions = 16,
38-
39-
// Don't use these directly.
40-
_JavaScriptIdentifiers = 17,
41-
_DeprecatedStart = 18,
42-
_First = LocalDeclarationPriority,
43-
44-
DeprecatedOffset = _DeprecatedStart - _First,
4521
}
4622

4723
/**
@@ -157,8 +133,8 @@ namespace ts.Completions {
157133
*/
158134
type SymbolOriginInfoMap = Record<number, SymbolOriginInfo>;
159135

160-
/** Map from symbol id -> SortTextId. */
161-
type SymbolSortTextIdMap = (SortTextId | undefined)[];
136+
/** Map from symbol id -> SortText. */
137+
type SymbolSortTextIdMap = (SortText | undefined)[];
162138

163139
const enum KeywordCompletionFilters {
164140
None, // No keywords
@@ -288,7 +264,7 @@ namespace ts.Completions {
288264
return getLabelCompletionAtPosition(previousToken.parent);
289265
}
290266

291-
const completionData = getCompletionData(program, log, sourceFile, isUncheckedFile(sourceFile, compilerOptions), position, preferences, /*detailsEntryId*/ undefined, host, cancellationToken);
267+
const completionData = getCompletionData(program, log, sourceFile, compilerOptions, position, preferences, /*detailsEntryId*/ undefined, host, cancellationToken);
292268
if (!completionData) {
293269
return undefined;
294270
}
@@ -791,7 +767,7 @@ namespace ts.Completions {
791767
}
792768
({ insertText, isSnippet, importAdder, sourceDisplay } = entry);
793769
source = CompletionSource.ObjectLiteralMethodSnippet;
794-
sortText = SortText.OptionalMember;
770+
sortText = sortText + "1" as SortText;
795771
if (importAdder.hasFixes()) {
796772
hasAction = true;
797773
}
@@ -1396,8 +1372,8 @@ namespace ts.Completions {
13961372
}
13971373

13981374
const { name, needsConvertPropertyAccess } = info;
1399-
const sortTextId = symbolToSortTextIdMap?.[getSymbolId(symbol)] ?? SortTextId.LocationPriority;
1400-
const sortText = (isDeprecated(symbol, typeChecker) ? SortTextId.DeprecatedOffset + sortTextId : sortTextId).toString() as SortText;
1375+
const originalSortText = symbolToSortTextIdMap?.[getSymbolId(symbol)] ?? SortText.LocationPriority;
1376+
const sortText = (isDeprecated(symbol, typeChecker) ? "z" + originalSortText : originalSortText) as SortText;
14011377
const entry = createCompletionEntry(
14021378
symbol,
14031379
sortText,
@@ -1465,9 +1441,9 @@ namespace ts.Completions {
14651441
// Auto Imports are not available for scripts so this conditional is always false
14661442
if (!!sourceFile.externalModuleIndicator
14671443
&& !compilerOptions.allowUmdGlobalAccess
1468-
&& symbolToSortTextIdMap[getSymbolId(symbol)] === SortTextId.GlobalsOrKeywords
1469-
&& (symbolToSortTextIdMap[getSymbolId(symbolOrigin)] === SortTextId.AutoImportSuggestions
1470-
|| symbolToSortTextIdMap[getSymbolId(symbolOrigin)] === SortTextId.LocationPriority)) {
1444+
&& symbolToSortTextIdMap[getSymbolId(symbol)] === SortText.GlobalsOrKeywords
1445+
&& (symbolToSortTextIdMap[getSymbolId(symbolOrigin)] === SortText.AutoImportSuggestions
1446+
|| symbolToSortTextIdMap[getSymbolId(symbolOrigin)] === SortText.LocationPriority)) {
14711447
return false;
14721448
}
14731449

@@ -1559,7 +1535,7 @@ namespace ts.Completions {
15591535
}
15601536

15611537
const compilerOptions = program.getCompilerOptions();
1562-
const completionData = getCompletionData(program, log, sourceFile, isUncheckedFile(sourceFile, compilerOptions), position, { includeCompletionsForModuleExports: true, includeCompletionsWithInsertText: true }, entryId, host);
1538+
const completionData = getCompletionData(program, log, sourceFile, compilerOptions, position, { includeCompletionsForModuleExports: true, includeCompletionsWithInsertText: true }, entryId, host);
15631539
if (!completionData) {
15641540
return { type: "none" };
15651541
}
@@ -1892,15 +1868,15 @@ namespace ts.Completions {
18921868
program: Program,
18931869
log: (message: string) => void,
18941870
sourceFile: SourceFile,
1895-
isUncheckedFile: boolean,
1871+
compilerOptions: CompilerOptions,
18961872
position: number,
18971873
preferences: UserPreferences,
18981874
detailsEntryId: CompletionEntryIdentifier | undefined,
18991875
host: LanguageServiceHost,
19001876
cancellationToken?: CancellationToken,
19011877
): CompletionData | Request | undefined {
19021878
const typeChecker = program.getTypeChecker();
1903-
1879+
const inUncheckedFile = isUncheckedFile(sourceFile, compilerOptions);
19041880
let start = timestamp();
19051881
let currentToken = getTokenAtPosition(sourceFile, position); // TODO: GH#15853
19061882
// We will check for jsdoc comments with insideComment and getJsDocTagAtPosition. (TODO: that seems rather inefficient to check the same thing so many times.)
@@ -2350,7 +2326,7 @@ namespace ts.Completions {
23502326
}
23512327

23522328
const propertyAccess = node.kind === SyntaxKind.ImportType ? node as ImportTypeNode : node.parent as PropertyAccessExpression | QualifiedName;
2353-
if (isUncheckedFile) {
2329+
if (inUncheckedFile) {
23542330
// In javascript files, for union types, we don't just get the members that
23552331
// the individual types have in common, we also include all the members that
23562332
// each individual type has. This is because we're going to add all identifiers
@@ -2437,7 +2413,7 @@ namespace ts.Completions {
24372413

24382414
function addSymbolSortInfo(symbol: Symbol) {
24392415
if (isStaticProperty(symbol)) {
2440-
symbolToSortTextIdMap[getSymbolId(symbol)] = SortTextId.LocalDeclarationPriority;
2416+
symbolToSortTextIdMap[getSymbolId(symbol)] = SortText.LocalDeclarationPriority;
24412417
}
24422418
}
24432419

@@ -2557,7 +2533,7 @@ namespace ts.Completions {
25572533
const symbol = symbols[i];
25582534
if (!typeChecker.isArgumentsSymbol(symbol) &&
25592535
!some(symbol.declarations, d => d.getSourceFile() === sourceFile)) {
2560-
symbolToSortTextIdMap[getSymbolId(symbol)] = SortTextId.GlobalsOrKeywords;
2536+
symbolToSortTextIdMap[getSymbolId(symbol)] = SortText.GlobalsOrKeywords;
25612537
}
25622538
if (typeOnlyAliasNeedsPromotion && !(symbol.flags & SymbolFlags.Value)) {
25632539
const typeOnlyAliasDeclaration = symbol.declarations && find(symbol.declarations, isTypeOnlyImportOrExportDeclaration);
@@ -2575,7 +2551,7 @@ namespace ts.Completions {
25752551
for (const symbol of getPropertiesForCompletion(thisType, typeChecker)) {
25762552
symbolToOriginInfoMap[symbols.length] = { kind: SymbolOriginInfoKind.ThisType };
25772553
symbols.push(symbol);
2578-
symbolToSortTextIdMap[getSymbolId(symbol)] = SortTextId.SuggestedClassMembers;
2554+
symbolToSortTextIdMap[getSymbolId(symbol)] = SortText.SuggestedClassMembers;
25792555
}
25802556
}
25812557
}
@@ -2762,12 +2738,12 @@ namespace ts.Completions {
27622738

27632739
function pushAutoImportSymbol(symbol: Symbol, origin: SymbolOriginInfoResolvedExport | SymbolOriginInfoExport) {
27642740
const symbolId = getSymbolId(symbol);
2765-
if (symbolToSortTextIdMap[symbolId] === SortTextId.GlobalsOrKeywords) {
2741+
if (symbolToSortTextIdMap[symbolId] === SortText.GlobalsOrKeywords) {
27662742
// If an auto-importable symbol is available as a global, don't add the auto import
27672743
return;
27682744
}
27692745
symbolToOriginInfoMap[symbols.length] = origin;
2770-
symbolToSortTextIdMap[symbolId] = importCompletionNode ? SortTextId.LocationPriority : SortTextId.AutoImportSuggestions;
2746+
symbolToSortTextIdMap[symbolId] = importCompletionNode ? SortText.LocationPriority : SortText.AutoImportSuggestions;
27712747
symbols.push(symbol);
27722748
}
27732749

@@ -3050,6 +3026,10 @@ namespace ts.Completions {
30503026
}
30513027
}
30523028
setSortTextToOptionalMember();
3029+
if (objectLikeContainer.kind === SyntaxKind.ObjectLiteralExpression && preferences.includeCompletionsWithInsertText) {
3030+
// >> TODO: specify `symbols` range?
3031+
transformObjectLiteralMembersSortText();
3032+
}
30533033

30543034
return GlobalsSearch.Success;
30553035
}
@@ -3131,7 +3111,7 @@ namespace ts.Completions {
31313111
localsContainer.locals?.forEach((symbol, name) => {
31323112
symbols.push(symbol);
31333113
if (localsContainer.symbol?.exports?.has(name)) {
3134-
symbolToSortTextIdMap[getSymbolId(symbol)] = SortTextId.OptionalMember;
3114+
symbolToSortTextIdMap[getSymbolId(symbol)] = SortText.OptionalMember;
31353115
}
31363116
});
31373117
return GlobalsSearch.Success;
@@ -3571,7 +3551,7 @@ namespace ts.Completions {
35713551
symbols.forEach(m => {
35723552
if (m.flags & SymbolFlags.Optional) {
35733553
const symbolId = getSymbolId(m);
3574-
symbolToSortTextIdMap[symbolId] = symbolToSortTextIdMap[symbolId] ?? SortTextId.OptionalMember;
3554+
symbolToSortTextIdMap[symbolId] = symbolToSortTextIdMap[symbolId] ?? SortText.OptionalMember;
35753555
}
35763556
});
35773557
}
@@ -3583,7 +3563,32 @@ namespace ts.Completions {
35833563
}
35843564
for (const contextualMemberSymbol of contextualMemberSymbols) {
35853565
if (membersDeclaredBySpreadAssignment.has(contextualMemberSymbol.name)) {
3586-
symbolToSortTextIdMap[getSymbolId(contextualMemberSymbol)] = SortTextId.MemberDeclaredBySpreadAssignment;
3566+
symbolToSortTextIdMap[getSymbolId(contextualMemberSymbol)] = SortText.MemberDeclaredBySpreadAssignment;
3567+
}
3568+
}
3569+
}
3570+
3571+
function transformObjectLiteralMembersSortText(): void {
3572+
const pastSymbolIds: Set<number> = new Set();
3573+
for (let i = 0; i < symbols.length; i++) {
3574+
const symbol = symbols[i];
3575+
const symbolId = getSymbolId(symbol);
3576+
if (pastSymbolIds.has(symbolId)) {
3577+
continue;
3578+
}
3579+
pastSymbolIds.add(symbolId);
3580+
const origin = symbolToOriginInfoMap?.[i];
3581+
const target = getEmitScriptTarget(compilerOptions);
3582+
const displayName = getCompletionEntryDisplayNameForSymbol(
3583+
symbol,
3584+
target,
3585+
origin,
3586+
CompletionKind.ObjectPropertyDeclaration,
3587+
/*jsxIdentifierExpected*/ false);
3588+
if (displayName) {
3589+
const originalSortText = symbolToSortTextIdMap[symbolId] ?? SortText.LocationPriority;
3590+
const { name } = displayName;
3591+
symbolToSortTextIdMap[symbolId] = `${originalSortText}\0${name}\0` as SortText;
35873592
}
35883593
}
35893594
}

tests/cases/fourslash/completionsObjectLiteralMethod1.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,12 @@ verify.completions({
4141
includes: [
4242
{
4343
name: "bar",
44-
sortText: completion.SortText.LocationPriority,
44+
sortText: `${completion.SortText.LocationPriority}\0bar\0` as completion.SortText,
4545
insertText: undefined,
4646
},
4747
{
4848
name: "bar",
49-
sortText: completion.SortText.OptionalMember,
49+
sortText: `${completion.SortText.LocationPriority}\0bar\0${1}` as completion.SortText,
5050
source: completion.CompletionSource.ObjectLiteralMethodSnippet,
5151
insertText: "bar(x: number): void {\n},",
5252
},
@@ -61,23 +61,23 @@ verify.completions({
6161
includes: [
6262
{
6363
name: "bar",
64-
sortText: completion.SortText.LocationPriority,
64+
sortText: `${completion.SortText.LocationPriority}\0bar\0` as completion.SortText,
6565
insertText: undefined,
6666
},
6767
{
6868
name: "bar",
69-
sortText: completion.SortText.OptionalMember,
69+
sortText: `${completion.SortText.LocationPriority}\0bar\0${1}` as completion.SortText,
7070
source: completion.CompletionSource.ObjectLiteralMethodSnippet,
7171
insertText: "bar(x: number): void {\n},",
7272
},
7373
{
7474
name: "foo",
75-
sortText: completion.SortText.LocationPriority,
75+
sortText: `${completion.SortText.LocationPriority}\0foo\0` as completion.SortText,
7676
insertText: undefined,
7777
},
7878
{
7979
name: "foo",
80-
sortText: completion.SortText.OptionalMember,
80+
sortText: `${completion.SortText.LocationPriority}\0foo\0${1}` as completion.SortText,
8181
source: completion.CompletionSource.ObjectLiteralMethodSnippet,
8282
insertText: "foo(x: string): string {\n},",
8383
},
@@ -92,7 +92,7 @@ verify.completions({
9292
exact: [
9393
{
9494
name: "buzz",
95-
sortText: completion.SortText.LocationPriority,
95+
sortText: `${completion.SortText.LocationPriority}\0buzz\0` as completion.SortText,
9696
// no declaration insert text, because this property has overloads
9797
insertText: undefined,
9898
},
@@ -107,12 +107,12 @@ verify.completions({
107107
includes: [
108108
{
109109
name: "\"space bar\"",
110-
sortText: completion.SortText.LocationPriority,
110+
sortText: `${completion.SortText.LocationPriority}\0${"\"space bar\""}\0` as completion.SortText,
111111
insertText: undefined,
112112
},
113113
{
114114
name: "\"space bar\"",
115-
sortText: completion.SortText.OptionalMember,
115+
sortText: `${completion.SortText.LocationPriority}\0${"\"space bar\""}\0${1}` as completion.SortText,
116116
source: completion.CompletionSource.ObjectLiteralMethodSnippet,
117117
insertText: "\"space bar\"(): string {\n},",
118118
},
@@ -127,12 +127,12 @@ verify.completions({
127127
includes: [
128128
{
129129
name: "bar",
130-
sortText: completion.SortText.LocationPriority,
130+
sortText: `${completion.SortText.LocationPriority}\0bar\0` as completion.SortText,
131131
insertText: undefined,
132132
},
133133
{
134134
name: "bar",
135-
sortText: completion.SortText.OptionalMember,
135+
sortText: `${completion.SortText.LocationPriority}\0bar\0${1}` as completion.SortText,
136136
source: completion.CompletionSource.ObjectLiteralMethodSnippet,
137137
isSnippet: true,
138138
insertText: "bar(x: number): void {\n $0\n},",

0 commit comments

Comments
 (0)