From 41b5986dcdeed31ea0b1a8931d1349a3d443ce9b Mon Sep 17 00:00:00 2001 From: Ben Lichtman Date: Mon, 6 Jan 2020 15:37:33 -0800 Subject: [PATCH] Make sortText on completions be enum-typed --- src/harness/client.ts | 2 +- src/server/protocol.ts | 2 +- src/services/completions.ts | 19 ++++++++++++++++++- src/services/jsDoc.ts | 6 +++--- src/services/stringCompletions.ts | 2 +- src/services/types.ts | 2 +- .../unittests/tsserver/metadataInResponse.ts | 4 ++-- .../reference/api/tsserverlibrary.d.ts | 16 ++++++++++++++-- tests/baselines/reference/api/typescript.d.ts | 14 +++++++++++++- 9 files changed, 54 insertions(+), 13 deletions(-) diff --git a/src/harness/client.ts b/src/harness/client.ts index 63ad8b90da83c..e6ae251b86dfb 100644 --- a/src/harness/client.ts +++ b/src/harness/client.ts @@ -204,7 +204,7 @@ namespace ts.server { return res; } - return entry as { name: string, kind: ScriptElementKind, kindModifiers: string, sortText: string }; // TODO: GH#18217 + return entry as { name: string, kind: ScriptElementKind, kindModifiers: string, sortText: Completions.SortText }; // TODO: GH#18217 }) }; } diff --git a/src/server/protocol.ts b/src/server/protocol.ts index cabe7dcd55dd1..483f15d54e037 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -2058,7 +2058,7 @@ namespace ts.server.protocol { * A string that is used for comparing completion items so that they can be ordered. This * is often the same as the name but may be different in certain circumstances. */ - sortText: string; + sortText: Completions.SortText; /** * Text to insert instead of `name`. * This is used to support bracketed completions; If `name` might be "a-b" but `insertText` would be `["a-b"]`, diff --git a/src/services/completions.ts b/src/services/completions.ts index bdf97266cf959..0bf6ad50758f4 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1,4 +1,3 @@ -/* @internal */ namespace ts.Completions { export enum SortText { LocationPriority = "0", @@ -9,8 +8,10 @@ namespace ts.Completions { AutoImportSuggestions = "5", JavascriptIdentifiers = "6" } + /* @internal */ export type Log = (message: string) => void; + /* @internal */ const enum SymbolOriginInfoKind { ThisType = 1 << 0, SymbolMember = 1 << 1, @@ -22,10 +23,12 @@ namespace ts.Completions { SymbolMemberExport = SymbolMember | Export, } + /* @internal */ interface SymbolOriginInfo { kind: SymbolOriginInfoKind; } + /* @internal */ interface SymbolOriginInfoExport extends SymbolOriginInfo { kind: SymbolOriginInfoKind; moduleSymbol: Symbol; @@ -56,8 +59,10 @@ namespace ts.Completions { * Map from symbol id -> SymbolOriginInfo. * Only populated for symbols that come from other modules. */ + /* @internal */ type SymbolOriginInfoMap = (SymbolOriginInfo | SymbolOriginInfoExport | undefined)[]; + /* @internal */ type SymbolSortTextMap = (SortText | undefined)[]; const enum KeywordCompletionFilters { @@ -74,18 +79,21 @@ namespace ts.Completions { const enum GlobalsSearch { Continue, Success, Fail } + /* @internal */ export interface AutoImportSuggestion { symbol: Symbol; symbolName: string; skipFilter: boolean; origin: SymbolOriginInfoExport; } + /* @internal */ export interface ImportSuggestionsForFileCache { clear(): void; get(fileName: string, checker: TypeChecker, projectVersion?: string): readonly AutoImportSuggestion[] | undefined; set(fileName: string, suggestions: readonly AutoImportSuggestion[], projectVersion?: string): void; isEmpty(): boolean; } + /* @internal */ export function createImportSuggestionsForFileCache(): ImportSuggestionsForFileCache { let cache: readonly AutoImportSuggestion[] | undefined; let projectVersion: string | undefined; @@ -131,6 +139,7 @@ namespace ts.Completions { }; } + /* @internal */ export function getCompletionsAtPosition( host: LanguageServiceHost, program: Program, @@ -422,6 +431,7 @@ namespace ts.Completions { return origin && originIsExport(origin) ? stripQuotes(origin.moduleSymbol.name) : undefined; } + /* @internal */ export function getCompletionEntriesFromSymbols( symbols: readonly Symbol[], entries: Push, @@ -571,11 +581,13 @@ namespace ts.Completions { : symbol.name; } + /* @internal */ export interface CompletionEntryIdentifier { name: string; source?: string; } + /* @internal */ export function getCompletionEntryDetails( program: Program, log: Log, @@ -633,6 +645,7 @@ namespace ts.Completions { return createCompletionDetails(name, ScriptElementKindModifier.none, kind, [displayPart(name, kind2)]); } + /* @internal */ export function createCompletionDetailsForSymbol(symbol: Symbol, checker: TypeChecker, sourceFile: SourceFile, location: Node, cancellationToken: CancellationToken, codeActions?: CodeAction[], sourceDisplay?: SymbolDisplayPart[]): CompletionEntryDetails { const { displayParts, documentation, symbolKind, tags } = checker.runWithCancellationToken(cancellationToken, checker => @@ -641,6 +654,7 @@ namespace ts.Completions { return createCompletionDetails(symbol.name, SymbolDisplay.getSymbolModifiers(symbol), symbolKind, displayParts, documentation, tags, codeActions, sourceDisplay); } + /* @internal */ export function createCompletionDetails(name: string, kindModifiers: string, kind: ScriptElementKind, displayParts: SymbolDisplayPart[], documentation?: SymbolDisplayPart[], tags?: JSDocTagInfo[], codeActions?: CodeAction[], source?: SymbolDisplayPart[]): CompletionEntryDetails { return { name, kindModifiers, kind, displayParts, documentation, tags, codeActions, source }; } @@ -682,6 +696,7 @@ namespace ts.Completions { return { sourceDisplay: [textPart(moduleSpecifier)], codeActions: [codeAction] }; } + /* @internal */ export function getCompletionEntrySymbol( program: Program, log: Log, @@ -695,6 +710,7 @@ namespace ts.Completions { } const enum CompletionDataKind { Data, JsDocTagName, JsDocTag, JsDocParameterName } + /* @internal */ /** true: after the `=` sign but no identifier has been typed yet. Else is the Identifier after the initializer. */ type IsJsxInitializer = boolean | Identifier; interface CompletionData { @@ -717,6 +733,7 @@ namespace ts.Completions { } type Request = { readonly kind: CompletionDataKind.JsDocTagName | CompletionDataKind.JsDocTag } | { readonly kind: CompletionDataKind.JsDocParameterName, tag: JSDocParameterTag }; + /* @internal */ export const enum CompletionKind { ObjectPropertyDeclaration, Global, diff --git a/src/services/jsDoc.ts b/src/services/jsDoc.ts index 56e0a0ae50ed6..d4f5d2a6da74a 100644 --- a/src/services/jsDoc.ts +++ b/src/services/jsDoc.ts @@ -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 }; }); } diff --git a/src/services/stringCompletions.ts b/src/services/stringCompletions.ts index b474f391049a9..b6d97525f6229 100644 --- a/src/services/stringCompletions.ts +++ b/src/services/stringCompletions.ts @@ -35,7 +35,7 @@ namespace ts.Completions.StringCompletions { return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: completion.hasIndexSignature, entries }; } case StringLiteralCompletionKind.Types: { - const entries = completion.types.map(type => ({ name: type.value, kindModifiers: ScriptElementKindModifier.none, kind: ScriptElementKind.string, sortText: "0" })); + const entries = completion.types.map(type => ({ name: type.value, kindModifiers: ScriptElementKindModifier.none, kind: ScriptElementKind.string, sortText: SortText.LocationPriority })); return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: completion.isNewIdentifier, entries }; } default: diff --git a/src/services/types.ts b/src/services/types.ts index 3a1627c247fe2..e60484805263b 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -977,7 +977,7 @@ namespace ts { name: string; kind: ScriptElementKind; kindModifiers?: string; // see ScriptElementKindModifier, comma separated - sortText: string; + sortText: Completions.SortText; insertText?: string; /** * An optional span that indicates the text to be replaced by this completion item. diff --git a/src/testRunner/unittests/tsserver/metadataInResponse.ts b/src/testRunner/unittests/tsserver/metadataInResponse.ts index 10b1c58d737a9..b798b6d67e0c0 100644 --- a/src/testRunner/unittests/tsserver/metadataInResponse.ts +++ b/src/testRunner/unittests/tsserver/metadataInResponse.ts @@ -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", () => { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 5ca50db806704..04f8e7ebc0c52 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -5641,7 +5641,7 @@ declare namespace ts { name: string; kind: ScriptElementKind; kindModifiers?: string; - sortText: string; + sortText: Completions.SortText; insertText?: string; /** * An optional span that indicates the text to be replaced by this completion item. @@ -5892,6 +5892,18 @@ declare namespace ts { /** The classifier is used for syntactic highlighting in editors via the TSServer */ function createClassifier(): Classifier; } +declare namespace ts.Completions { + export enum SortText { + LocationPriority = "0", + OptionalMember = "1", + MemberDeclaredBySpreadAssignment = "2", + SuggestedClassMembers = "3", + GlobalsOrKeywords = "4", + AutoImportSuggestions = "5", + JavascriptIdentifiers = "6" + } + export {}; +} declare namespace ts { interface DocumentHighlights { fileName: string; @@ -7616,7 +7628,7 @@ declare namespace ts.server.protocol { * A string that is used for comparing completion items so that they can be ordered. This * is often the same as the name but may be different in certain circumstances. */ - sortText: string; + sortText: Completions.SortText; /** * Text to insert instead of `name`. * This is used to support bracketed completions; If `name` might be "a-b" but `insertText` would be `["a-b"]`, diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 1143d4c6ebceb..735aa3fee7795 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -5641,7 +5641,7 @@ declare namespace ts { name: string; kind: ScriptElementKind; kindModifiers?: string; - sortText: string; + sortText: Completions.SortText; insertText?: string; /** * An optional span that indicates the text to be replaced by this completion item. @@ -5892,6 +5892,18 @@ declare namespace ts { /** The classifier is used for syntactic highlighting in editors via the TSServer */ function createClassifier(): Classifier; } +declare namespace ts.Completions { + export enum SortText { + LocationPriority = "0", + OptionalMember = "1", + MemberDeclaredBySpreadAssignment = "2", + SuggestedClassMembers = "3", + GlobalsOrKeywords = "4", + AutoImportSuggestions = "5", + JavascriptIdentifiers = "6" + } + export {}; +} declare namespace ts { interface DocumentHighlights { fileName: string;