diff --git a/src/services/completions.ts b/src/services/completions.ts index 4193e651a037f..2553465616bcf 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -646,6 +646,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)) { @@ -675,7 +676,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; } @@ -692,7 +693,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); } @@ -866,7 +867,8 @@ function completionInfoFromData( completionData: CompletionData, preferences: UserPreferences, formatContext: formatting.FormatContext | undefined, - position: number + position: number, + includeSymbol: boolean | undefined, ): CompletionInfo | undefined { const { symbols, @@ -951,6 +953,7 @@ function completionInfoFromData( symbolToSortTextMap, isJsxIdentifierExpected, isRightOfOpenTag, + includeSymbol ); if (keywordFilters !== KeywordCompletionFilters.None) { @@ -1339,6 +1342,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); @@ -1492,6 +1496,7 @@ function createCompletionEntry( isPackageJsonImport: originIsPackageJsonImport(origin) || undefined, isImportStatementCompletion: !!importStatementCompletion || undefined, data, + ...includeSymbol ? { symbol } : undefined }; } @@ -2119,6 +2124,7 @@ export function getCompletionEntriesFromSymbols( symbolToSortTextMap?: SymbolSortTextMap, isJsxIdentifierExpected?: boolean, isRightOfOpenTag?: boolean, + includeSymbol = false ): UniqueNameSet { const start = timestamp(); const variableDeclaration = getVariableDeclaration(location); @@ -2164,6 +2170,7 @@ export function getCompletionEntriesFromSymbols( formatContext, isJsxIdentifierExpected, isRightOfOpenTag, + includeSymbol ); if (!entry) { continue; diff --git a/src/services/services.ts b/src/services/services.ts index f6e5fccfe06c6..fb665bdf61c3a 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -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 { diff --git a/src/services/stringCompletions.ts b/src/services/stringCompletions.ts index 205bbfc5d66d3..af460d88ee690 100644 --- a/src/services/stringCompletions.ts +++ b/src/services/stringCompletions.ts @@ -190,7 +190,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); @@ -198,7 +199,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); } } @@ -212,6 +213,7 @@ function convertStringLiteralCompletions( options: CompilerOptions, preferences: UserPreferences, position: number, + includeSymbol: boolean, ): CompletionInfo | undefined { if (completion === undefined) { return undefined; @@ -239,6 +241,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 }; } diff --git a/src/services/types.ts b/src/services/types.ts index 11f22f4fc9472..983aa7bbbb5f0 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -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 diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 035abc4d7ff10..dd488ea21b4c1 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -10072,6 +10072,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 */ @@ -10629,6 +10636,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 diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index a8a5c3bb97f1b..a355db267c1ba 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -6170,6 +6170,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 */ @@ -6727,6 +6734,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