Add API option to getCompletionsAtPosition to expose completion symbol information (#52560)

Co-authored-by: Andrew Branch <andrewbranch@users.noreply.github.com>
This commit is contained in:
Vitaly 2023-02-16 22:09:29 +03:00 committed by GitHub
parent 151364902b
commit 2f43308dc4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 66 additions and 6 deletions

View File

@ -643,6 +643,7 @@ export function getCompletionsAtPosition(
completionKind: CompletionTriggerKind | undefined,
cancellationToken: CancellationToken,
formatContext?: formatting.FormatContext,
includeSymbol = false
): CompletionInfo | undefined {
const { previousToken } = getRelevantTokens(position, sourceFile);
if (triggerCharacter && !isInString(sourceFile, position, previousToken) && !isValidTrigger(sourceFile, triggerCharacter, previousToken, position)) {
@ -672,7 +673,7 @@ export function getCompletionsAtPosition(
incompleteCompletionsCache?.clear();
}
const stringCompletions = StringCompletions.getStringLiteralCompletions(sourceFile, position, previousToken, compilerOptions, host, program, log, preferences);
const stringCompletions = StringCompletions.getStringLiteralCompletions(sourceFile, position, previousToken, compilerOptions, host, program, log, preferences, includeSymbol);
if (stringCompletions) {
return stringCompletions;
}
@ -689,7 +690,7 @@ export function getCompletionsAtPosition(
switch (completionData.kind) {
case CompletionDataKind.Data:
const response = completionInfoFromData(sourceFile, host, program, compilerOptions, log, completionData, preferences, formatContext, position);
const response = completionInfoFromData(sourceFile, host, program, compilerOptions, log, completionData, preferences, formatContext, position, includeSymbol);
if (response?.isIncomplete) {
incompleteCompletionsCache?.set(response);
}
@ -863,7 +864,8 @@ function completionInfoFromData(
completionData: CompletionData,
preferences: UserPreferences,
formatContext: formatting.FormatContext | undefined,
position: number
position: number,
includeSymbol: boolean | undefined,
): CompletionInfo | undefined {
const {
symbols,
@ -948,6 +950,7 @@ function completionInfoFromData(
symbolToSortTextMap,
isJsxIdentifierExpected,
isRightOfOpenTag,
includeSymbol
);
if (keywordFilters !== KeywordCompletionFilters.None) {
@ -1267,6 +1270,7 @@ function createCompletionEntry(
formatContext: formatting.FormatContext | undefined,
isJsxIdentifierExpected: boolean | undefined,
isRightOfOpenTag: boolean | undefined,
includeSymbol: boolean
): CompletionEntry | undefined {
let insertText: string | undefined;
let replacementSpan = getReplacementSpanForContextToken(replacementToken);
@ -1422,6 +1426,7 @@ function createCompletionEntry(
isPackageJsonImport: originIsPackageJsonImport(origin) || undefined,
isImportStatementCompletion: !!importStatementCompletion || undefined,
data,
...includeSymbol ? { symbol } : undefined
};
}
@ -2051,6 +2056,7 @@ export function getCompletionEntriesFromSymbols(
symbolToSortTextMap?: SymbolSortTextMap,
isJsxIdentifierExpected?: boolean,
isRightOfOpenTag?: boolean,
includeSymbol = false
): UniqueNameSet {
const start = timestamp();
const variableDeclaration = getVariableDeclaration(location);
@ -2096,6 +2102,7 @@ export function getCompletionEntriesFromSymbols(
formatContext,
isJsxIdentifierExpected,
isRightOfOpenTag,
includeSymbol
);
if (!entry) {
continue;

View File

@ -1990,7 +1990,8 @@ export function createLanguageService(
options.triggerCharacter,
options.triggerKind,
cancellationToken,
formattingSettings && formatting.getFormatContext(formattingSettings, host));
formattingSettings && formatting.getFormatContext(formattingSettings, host),
options.includeSymbol);
}
function getCompletionEntryDetails(fileName: string, position: number, name: string, formattingOptions: FormatCodeSettings | undefined, source: string | undefined, preferences: UserPreferences = emptyOptions, data?: CompletionEntryData): CompletionEntryDetails | undefined {

View File

@ -192,7 +192,8 @@ export function getStringLiteralCompletions(
host: LanguageServiceHost,
program: Program,
log: Log,
preferences: UserPreferences): CompletionInfo | undefined {
preferences: UserPreferences,
includeSymbol: boolean): CompletionInfo | undefined {
if (isInReferenceComment(sourceFile, position)) {
const entries = getTripleSlashReferenceCompletion(sourceFile, position, options, host);
return entries && convertPathCompletions(entries);
@ -200,7 +201,7 @@ export function getStringLiteralCompletions(
if (isInString(sourceFile, position, contextToken)) {
if (!contextToken || !isStringLiteralLike(contextToken)) return undefined;
const entries = getStringLiteralCompletionEntries(sourceFile, contextToken, position, program.getTypeChecker(), options, host, preferences);
return convertStringLiteralCompletions(entries, contextToken, sourceFile, host, program, log, options, preferences, position);
return convertStringLiteralCompletions(entries, contextToken, sourceFile, host, program, log, options, preferences, position, includeSymbol);
}
}
@ -214,6 +215,7 @@ function convertStringLiteralCompletions(
options: CompilerOptions,
preferences: UserPreferences,
position: number,
includeSymbol: boolean,
): CompletionInfo | undefined {
if (completion === undefined) {
return undefined;
@ -241,6 +243,17 @@ function convertStringLiteralCompletions(
preferences,
options,
/*formatContext*/ undefined,
/*isTypeOnlyLocation */ undefined,
/*propertyAccessToConvert*/ undefined,
/*jsxIdentifierExpected*/ undefined,
/*isJsxInitializer*/ undefined,
/*importStatementCompletion*/ undefined,
/*recommendedCompletion*/ undefined,
/*symbolToOriginInfoMap*/ undefined,
/*symbolToSortTextMap*/ undefined,
/*isJsxIdentifierExpected*/ undefined,
/*isRightOfOpenTag*/ undefined,
includeSymbol
); // Target will not be used, so arbitrary
return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: completion.hasIndexSignature, optionalReplacementSpan, entries };
}

View File

@ -700,6 +700,13 @@ export interface GetCompletionsAtPositionOptions extends UserPreferences {
*/
triggerCharacter?: CompletionsTriggerCharacter;
triggerKind?: CompletionTriggerKind;
/**
* Include a `symbol` property on each completion entry object.
* Symbols reference cyclic data structures and sometimes an entire TypeChecker instance,
* so use caution when serializing or retaining completion entries retrieved with this option.
* @default false
*/
includeSymbol?: boolean
/** @deprecated Use includeCompletionsForModuleExports */
includeExternalModuleExports?: boolean;
/** @deprecated Use includeCompletionsWithInsertText */
@ -1379,6 +1386,12 @@ export interface CompletionEntry {
isFromUncheckedFile?: true;
isPackageJsonImport?: true;
isImportStatementCompletion?: true;
/**
* For API purposes.
* Included for non-string completions only when `includeSymbol: true` option is passed to `getCompletionsAtPosition`.
* @example Get declaration of completion: `symbol.valueDeclaration`
*/
symbol?: Symbol
/**
* A property to be sent back to TS Server in the CompletionDetailsRequest, along with `name`,
* that allows TS Server to look up the symbol represented by the completion item, disambiguating

View File

@ -10073,6 +10073,13 @@ declare namespace ts {
*/
triggerCharacter?: CompletionsTriggerCharacter;
triggerKind?: CompletionTriggerKind;
/**
* Include a `symbol` property on each completion entry object.
* Symbols reference cyclic data structures and sometimes an entire TypeChecker instance,
* so use caution when serializing or retaining completion entries retrieved with this option.
* @default false
*/
includeSymbol?: boolean;
/** @deprecated Use includeCompletionsForModuleExports */
includeExternalModuleExports?: boolean;
/** @deprecated Use includeCompletionsWithInsertText */
@ -10630,6 +10637,12 @@ declare namespace ts {
isFromUncheckedFile?: true;
isPackageJsonImport?: true;
isImportStatementCompletion?: true;
/**
* For API purposes.
* Included for non-string completions only when `includeSymbol: true` option is passed to `getCompletionsAtPosition`.
* @example Get declaration of completion: `symbol.valueDeclaration`
*/
symbol?: Symbol;
/**
* A property to be sent back to TS Server in the CompletionDetailsRequest, along with `name`,
* that allows TS Server to look up the symbol represented by the completion item, disambiguating

View File

@ -6171,6 +6171,13 @@ declare namespace ts {
*/
triggerCharacter?: CompletionsTriggerCharacter;
triggerKind?: CompletionTriggerKind;
/**
* Include a `symbol` property on each completion entry object.
* Symbols reference cyclic data structures and sometimes an entire TypeChecker instance,
* so use caution when serializing or retaining completion entries retrieved with this option.
* @default false
*/
includeSymbol?: boolean;
/** @deprecated Use includeCompletionsForModuleExports */
includeExternalModuleExports?: boolean;
/** @deprecated Use includeCompletionsWithInsertText */
@ -6728,6 +6735,12 @@ declare namespace ts {
isFromUncheckedFile?: true;
isPackageJsonImport?: true;
isImportStatementCompletion?: true;
/**
* For API purposes.
* Included for non-string completions only when `includeSymbol: true` option is passed to `getCompletionsAtPosition`.
* @example Get declaration of completion: `symbol.valueDeclaration`
*/
symbol?: Symbol;
/**
* A property to be sent back to TS Server in the CompletionDetailsRequest, along with `name`,
* that allows TS Server to look up the symbol represented by the completion item, disambiguating