mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-06 23:59:42 -05:00
Support completions for members with symbol names (#23091)
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
namespace ts.Completions {
|
||||
export type Log = (message: string) => void;
|
||||
|
||||
type SymbolOriginInfo = { type: "this-type" } | SymbolOriginInfoExport;
|
||||
type SymbolOriginInfo = { type: "this-type" } | { type: "symbol-member" } | SymbolOriginInfoExport;
|
||||
interface SymbolOriginInfoExport {
|
||||
type: "export";
|
||||
moduleSymbol: Symbol;
|
||||
@@ -208,9 +208,9 @@ namespace ts.Completions {
|
||||
}
|
||||
// We should only have needsConvertPropertyAccess if there's a property access to convert. But see #21790.
|
||||
// Somehow there was a global with a non-identifier name. Hopefully someone will complain about getting a "foo bar" global completion and provide a repro.
|
||||
else if (needsConvertPropertyAccess && propertyAccessToConvert) {
|
||||
insertText = `[${quote(name, preferences)}]`;
|
||||
const dot = findChildOfKind(propertyAccessToConvert, SyntaxKind.DotToken, sourceFile)!;
|
||||
else if ((origin && origin.type === "symbol-member" || needsConvertPropertyAccess) && propertyAccessToConvert) {
|
||||
insertText = needsConvertPropertyAccess ? `[${quote(name, preferences)}]` : `[${name}]`;
|
||||
const dot = findChildOfKind(propertyAccessToConvert!, SyntaxKind.DotToken, sourceFile)!;
|
||||
// If the text after the '.' starts with this name, write over it. Else, add new text.
|
||||
const end = startsWith(name, propertyAccessToConvert.name.text) ? propertyAccessToConvert.name.end : dot.end;
|
||||
replacementSpan = createTextSpanFromBounds(dot.getStart(sourceFile), end);
|
||||
@@ -1064,12 +1064,33 @@ namespace ts.Completions {
|
||||
else {
|
||||
for (const symbol of type.getApparentProperties()) {
|
||||
if (typeChecker.isValidPropertyAccessForCompletions(<PropertyAccessExpression>(node.parent), type, symbol)) {
|
||||
symbols.push(symbol);
|
||||
addPropertySymbol(symbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addPropertySymbol(symbol: Symbol) {
|
||||
// If this is e.g. [Symbol.iterator], add a completion for `Symbol`.
|
||||
const symbolSymbol = firstDefined(symbol.declarations, decl => {
|
||||
const name = getNameOfDeclaration(decl);
|
||||
const leftName = name.kind === SyntaxKind.ComputedPropertyName ? getLeftMostName(name.expression) : undefined;
|
||||
return leftName && typeChecker.getSymbolAtLocation(leftName);
|
||||
});
|
||||
if (symbolSymbol) {
|
||||
symbols.push(symbolSymbol);
|
||||
symbolToOriginInfoMap[getSymbolId(symbolSymbol)] = { type: "symbol-member" };
|
||||
}
|
||||
else {
|
||||
symbols.push(symbol);
|
||||
}
|
||||
}
|
||||
|
||||
/** Given 'a.b.c', returns 'a'. */
|
||||
function getLeftMostName(e: Expression): Identifier | undefined {
|
||||
return isIdentifier(e) ? e : isPropertyAccessExpression(e) ? getLeftMostName(e.expression) : undefined;
|
||||
}
|
||||
|
||||
function tryGetGlobalSymbols(): boolean {
|
||||
const result: GlobalsSearch = tryGetObjectLikeCompletionSymbols()
|
||||
|| tryGetImportOrExportClauseCompletionSymbols()
|
||||
|
||||
Reference in New Issue
Block a user