From 1c3259d29b9244ce43b1b4e7e45e37a614b29d7c Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 20 Jun 2018 09:13:04 -0700 Subject: [PATCH] Add CompletionInfo command to protocol (#25080) * Add CompletionInfo command to protocol * Add comments to protocol --- src/server/protocol.ts | 14 ++++++ src/server/session.ts | 44 ++++++++++++------- .../reference/api/tsserverlibrary.d.ts | 10 +++++ 3 files changed, 51 insertions(+), 17 deletions(-) diff --git a/src/server/protocol.ts b/src/server/protocol.ts index 2f128aa1663..49fb54a6b10 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -14,7 +14,9 @@ namespace ts.server.protocol { GetSpanOfEnclosingComment = "getSpanOfEnclosingComment", Change = "change", Close = "close", + /** @deprecated Prefer CompletionInfo -- see comment on CompletionsResponse */ Completions = "completions", + CompletionInfo = "completionInfo", /* @internal */ CompletionsFull = "completions-full", CompletionDetails = "completionEntryDetails", @@ -1943,10 +1945,22 @@ namespace ts.server.protocol { source?: SymbolDisplayPart[]; } + /** @deprecated Prefer CompletionInfoResponse, which supports several top-level fields in addition to the array of entries. */ export interface CompletionsResponse extends Response { body?: CompletionEntry[]; } + export interface CompletionInfoResponse extends Response { + body?: CompletionInfo; + } + + export interface CompletionInfo { + readonly isGlobalCompletion: boolean; + readonly isMemberCompletion: boolean; + readonly isNewIdentifierLocation: boolean; + readonly entries: ReadonlyArray; + } + export interface CompletionDetailsResponse extends Response { body?: CompletionEntryDetails[]; } diff --git a/src/server/session.ts b/src/server/session.ts index 74629d97e48..c6934bb8d82 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -1343,8 +1343,7 @@ namespace ts.server { }); } - private getCompletions(args: protocol.CompletionsRequestArgs, simplifiedResult: boolean): ReadonlyArray | CompletionInfo | undefined { - const prefix = args.prefix || ""; + private getCompletions(args: protocol.CompletionsRequestArgs, kind: protocol.CommandTypes.CompletionInfo | protocol.CommandTypes.Completions | protocol.CommandTypes.CompletionsFull): ReadonlyArray | protocol.CompletionInfo | CompletionInfo | undefined { const { file, project } = this.getFileAndProject(args); const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!; const position = this.getPosition(args, scriptInfo); @@ -1355,19 +1354,27 @@ namespace ts.server { includeExternalModuleExports: args.includeExternalModuleExports, includeInsertTextCompletions: args.includeInsertTextCompletions }); - if (simplifiedResult) { - return mapDefined(completions && completions.entries, entry => { - if (completions!.isMemberCompletion || startsWith(entry.name.toLowerCase(), prefix.toLowerCase())) { - const { name, kind, kindModifiers, sortText, insertText, replacementSpan, hasAction, source, isRecommended } = entry; - const convertedSpan = replacementSpan ? this.toLocationTextSpan(replacementSpan, scriptInfo) : undefined; - // Use `hasAction || undefined` to avoid serializing `false`. - return { name, kind, kindModifiers, sortText, insertText, replacementSpan: convertedSpan, hasAction: hasAction || undefined, source, isRecommended }; - } - }).sort((a, b) => compareStringsCaseSensitiveUI(a.name, b.name)); - } - else { - return completions; - } + if (completions === undefined) return undefined; + + if (kind === protocol.CommandTypes.CompletionsFull) return completions; + + const prefix = args.prefix || ""; + const entries = mapDefined(completions.entries, entry => { + if (completions.isMemberCompletion || startsWith(entry.name.toLowerCase(), prefix.toLowerCase())) { + const { name, kind, kindModifiers, sortText, insertText, replacementSpan, hasAction, source, isRecommended } = entry; + const convertedSpan = replacementSpan ? this.toLocationTextSpan(replacementSpan, scriptInfo) : undefined; + // Use `hasAction || undefined` to avoid serializing `false`. + return { name, kind, kindModifiers, sortText, insertText, replacementSpan: convertedSpan, hasAction: hasAction || undefined, source, isRecommended }; + } + }).sort((a, b) => compareStringsCaseSensitiveUI(a.name, b.name)); + + if (kind === protocol.CommandTypes.Completions) return entries; + + const res: protocol.CompletionInfo = { + ...completions, + entries, + }; + return res; } private getCompletionEntryDetails(args: protocol.CompletionDetailsRequestArgs, simplifiedResult: boolean): ReadonlyArray | ReadonlyArray { @@ -2035,11 +2042,14 @@ namespace ts.server { [CommandNames.FormatRangeFull]: (request: protocol.FormatRequest) => { return this.requiredResponse(this.getFormattingEditsForRangeFull(request.arguments)); }, + [CommandNames.CompletionInfo]: (request: protocol.CompletionsRequest) => { + return this.requiredResponse(this.getCompletions(request.arguments, CommandNames.CompletionInfo)); + }, [CommandNames.Completions]: (request: protocol.CompletionsRequest) => { - return this.requiredResponse(this.getCompletions(request.arguments, /*simplifiedResult*/ true)); + return this.requiredResponse(this.getCompletions(request.arguments, CommandNames.Completions)); }, [CommandNames.CompletionsFull]: (request: protocol.CompletionsRequest) => { - return this.requiredResponse(this.getCompletions(request.arguments, /*simplifiedResult*/ false)); + return this.requiredResponse(this.getCompletions(request.arguments, CommandNames.CompletionsFull)); }, [CommandNames.CompletionDetails]: (request: protocol.CompletionDetailsRequest) => { return this.requiredResponse(this.getCompletionEntryDetails(request.arguments, /*simplifiedResult*/ true)); diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 74045ba417d..114b2341fa9 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -12175,6 +12175,7 @@ declare namespace ts.server.protocol { Change = "change", Close = "close", Completions = "completions", + CompletionInfo = "completionInfo", CompletionsFull = "completions-full", CompletionDetails = "completionEntryDetails", CompletionDetailsFull = "completionEntryDetails-full", @@ -12876,6 +12877,15 @@ declare namespace ts.server.protocol { interface CompletionsResponse extends Response { body?: CompletionEntry[]; } + interface CompletionInfoResponse extends Response { + body?: CompletionInfo; + } + interface CompletionInfo { + readonly isGlobalCompletion: boolean; + readonly isMemberCompletion: boolean; + readonly isNewIdentifierLocation: boolean; + readonly entries: ReadonlyArray; + } interface CompletionDetailsResponse extends Response { body?: CompletionEntryDetails[]; }