mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-25 22:01:51 -05:00
Support completion details for string literal completions (#22664)
This commit is contained in:
@@ -89,7 +89,7 @@ namespace ts.Completions {
|
||||
return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: true, entries };
|
||||
}
|
||||
case StringLiteralCompletionKind.Types: {
|
||||
const entries = completion.types.map(type => ({ name: type.value, kindModifiers: ScriptElementKindModifier.none, kind: ScriptElementKind.variableElement, sortText: "0" }));
|
||||
const entries = completion.types.map(type => ({ name: type.value, kindModifiers: ScriptElementKindModifier.none, kind: ScriptElementKind.typeElement, sortText: "0" }));
|
||||
return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: true, entries };
|
||||
}
|
||||
default:
|
||||
@@ -531,6 +531,15 @@ namespace ts.Completions {
|
||||
): CompletionEntryDetails {
|
||||
const typeChecker = program.getTypeChecker();
|
||||
const { name } = entryId;
|
||||
|
||||
const contextToken = findPrecedingToken(position, sourceFile);
|
||||
if (isInString(sourceFile, position, contextToken)) {
|
||||
const stringLiteralCompletions = !contextToken || !isStringLiteralLike(contextToken)
|
||||
? undefined
|
||||
: getStringLiteralCompletionEntries(sourceFile, contextToken, position, typeChecker, compilerOptions, host);
|
||||
return stringLiteralCompletions && stringLiteralCompletionDetails(name, contextToken, stringLiteralCompletions, sourceFile, typeChecker);
|
||||
}
|
||||
|
||||
// Compute all the completion symbols again.
|
||||
const symbolCompletion = getSymbolCompletionFromEntryId(typeChecker, log, compilerOptions, sourceFile, position, entryId, allSourceFiles);
|
||||
switch (symbolCompletion.type) {
|
||||
@@ -550,29 +559,40 @@ namespace ts.Completions {
|
||||
case "symbol": {
|
||||
const { symbol, location, symbolToOriginInfoMap, previousToken } = symbolCompletion;
|
||||
const { codeActions, sourceDisplay } = getCompletionEntryCodeActionsAndSourceDisplay(symbolToOriginInfoMap, symbol, program, typeChecker, host, compilerOptions, sourceFile, previousToken, formatContext, getCanonicalFileName, allSourceFiles, preferences);
|
||||
const kindModifiers = SymbolDisplay.getSymbolModifiers(symbol);
|
||||
const { displayParts, documentation, symbolKind, tags } = SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, sourceFile, location, location, SemanticMeaning.All);
|
||||
return { name, kindModifiers, kind: symbolKind, displayParts, documentation, tags, codeActions, source: sourceDisplay };
|
||||
return createCompletionDetailsForSymbol(symbol, typeChecker, sourceFile, location, codeActions, sourceDisplay);
|
||||
}
|
||||
case "none": {
|
||||
case "none":
|
||||
// Didn't find a symbol with this name. See if we can find a keyword instead.
|
||||
if (allKeywordsCompletions().some(c => c.name === name)) {
|
||||
return {
|
||||
name,
|
||||
kind: ScriptElementKind.keyword,
|
||||
kindModifiers: ScriptElementKindModifier.none,
|
||||
displayParts: [displayPart(name, SymbolDisplayPartKind.keyword)],
|
||||
documentation: undefined,
|
||||
tags: undefined,
|
||||
codeActions: undefined,
|
||||
source: undefined,
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
return allKeywordsCompletions().some(c => c.name === name) ? createCompletionDetails(name, ScriptElementKindModifier.none, ScriptElementKind.keyword, [displayPart(name, SymbolDisplayPartKind.keyword)]) : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function createCompletionDetailsForSymbol(symbol: Symbol, checker: TypeChecker, sourceFile: SourceFile, location: Node, codeActions?: CodeAction[], sourceDisplay?: SymbolDisplayPart[]): CompletionEntryDetails {
|
||||
const { displayParts, documentation, symbolKind, tags } = SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, sourceFile, location, location, SemanticMeaning.All);
|
||||
return createCompletionDetails(symbol.name, SymbolDisplay.getSymbolModifiers(symbol), symbolKind, displayParts, documentation, tags, codeActions, sourceDisplay);
|
||||
}
|
||||
|
||||
function stringLiteralCompletionDetails(name: string, location: Node, completion: StringLiteralCompletion, sourceFile: SourceFile, checker: TypeChecker): CompletionEntryDetails | undefined {
|
||||
switch (completion.kind) {
|
||||
case StringLiteralCompletionKind.Paths: {
|
||||
const match = find(completion.paths, p => p.name === name);
|
||||
return match && createCompletionDetails(name, ScriptElementKindModifier.none, match.kind, [textPart(name)]);
|
||||
}
|
||||
case StringLiteralCompletionKind.Properties: {
|
||||
const match = find(completion.symbols, s => s.name === name);
|
||||
return match && createCompletionDetailsForSymbol(match, checker, sourceFile, location);
|
||||
}
|
||||
case StringLiteralCompletionKind.Types:
|
||||
return find(completion.types, t => t.value === name) ? createCompletionDetails(name, ScriptElementKindModifier.none, ScriptElementKind.typeElement, [textPart(name)]) : undefined;
|
||||
default:
|
||||
return Debug.assertNever(completion);
|
||||
}
|
||||
}
|
||||
|
||||
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 };
|
||||
}
|
||||
|
||||
interface CodeActionsAndSourceDisplay {
|
||||
readonly codeActions: CodeAction[] | undefined;
|
||||
readonly sourceDisplay: SymbolDisplayPart[] | undefined;
|
||||
|
||||
28
tests/cases/fourslash/completionForStringLiteral_details.ts
Normal file
28
tests/cases/fourslash/completionForStringLiteral_details.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
// @Filename: /other.ts
|
||||
////export const x = 0;
|
||||
|
||||
// @Filename: /a.ts
|
||||
////import {} from ".//*path*/";
|
||||
////
|
||||
////const x: "a" = "/*type*/";
|
||||
////
|
||||
////interface I {
|
||||
//// /** Prop doc */
|
||||
//// x: number;
|
||||
//// /** Method doc */
|
||||
//// m(): void;
|
||||
////}
|
||||
////declare const o: I;
|
||||
////o["/*prop*/"];
|
||||
|
||||
goTo.marker("path");
|
||||
verify.completionListContains("other", "other", "", "script");
|
||||
|
||||
goTo.marker("type");
|
||||
verify.completionListContains("a", "a", "", "type");
|
||||
|
||||
goTo.marker("prop");
|
||||
verify.completionListContains("x", "(property) I.x: number", "Prop doc ", "property");
|
||||
verify.completionListContains("m", "(method) I.m(): void", "Method doc ", "method");
|
||||
Reference in New Issue
Block a user