mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-09 02:30:15 -06:00
At <div x=/**/, completion insertText should be wrapped in braces (#21372)
This commit is contained in:
parent
b9bb7452f8
commit
dcd3b5e1f7
@ -78,7 +78,7 @@ namespace ts.Completions {
|
||||
}
|
||||
|
||||
function completionInfoFromData(sourceFile: SourceFile, typeChecker: TypeChecker, compilerOptions: CompilerOptions, log: Log, completionData: CompletionData, includeInsertTextCompletions: boolean): CompletionInfo {
|
||||
const { symbols, completionKind, isNewIdentifierLocation, location, propertyAccessToConvert, keywordFilters, symbolToOriginInfoMap, recommendedCompletion } = completionData;
|
||||
const { symbols, completionKind, isNewIdentifierLocation, location, propertyAccessToConvert, keywordFilters, symbolToOriginInfoMap, recommendedCompletion, isJsxInitializer } = completionData;
|
||||
|
||||
if (sourceFile.languageVariant === LanguageVariant.JSX && location && location.parent && isJsxClosingElement(location.parent)) {
|
||||
// In the TypeScript JSX element, if such element is not defined. When users query for completion at closing tag,
|
||||
@ -99,7 +99,7 @@ namespace ts.Completions {
|
||||
const entries: CompletionEntry[] = [];
|
||||
|
||||
if (isSourceFileJavaScript(sourceFile)) {
|
||||
const uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, includeInsertTextCompletions, propertyAccessToConvert, recommendedCompletion, symbolToOriginInfoMap);
|
||||
const uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, includeInsertTextCompletions, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap);
|
||||
getJavaScriptCompletionEntries(sourceFile, location.pos, uniqueNames, compilerOptions.target, entries);
|
||||
}
|
||||
else {
|
||||
@ -107,7 +107,7 @@ namespace ts.Completions {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, includeInsertTextCompletions, propertyAccessToConvert, recommendedCompletion, symbolToOriginInfoMap);
|
||||
getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, includeInsertTextCompletions, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap);
|
||||
}
|
||||
|
||||
// TODO add filter for keyword based on type/value/namespace and also location
|
||||
@ -167,6 +167,7 @@ namespace ts.Completions {
|
||||
origin: SymbolOriginInfo | undefined,
|
||||
recommendedCompletion: Symbol | undefined,
|
||||
propertyAccessToConvert: PropertyAccessExpression | undefined,
|
||||
isJsxInitializer: boolean,
|
||||
includeInsertTextCompletions: boolean,
|
||||
): CompletionEntry | undefined {
|
||||
const info = getCompletionEntryDisplayNameForSymbol(symbol, target, origin, kind);
|
||||
@ -174,19 +175,27 @@ namespace ts.Completions {
|
||||
return undefined;
|
||||
}
|
||||
const { name, needsConvertPropertyAccess } = info;
|
||||
if (needsConvertPropertyAccess && !includeInsertTextCompletions) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let insertText: string | undefined;
|
||||
let replacementSpan: TextSpan | undefined;
|
||||
if (origin && origin.type === "this-type") {
|
||||
insertText = needsConvertPropertyAccess ? `this["${name}"]` : `this.${name}`;
|
||||
if (includeInsertTextCompletions) {
|
||||
if (origin && origin.type === "this-type") {
|
||||
insertText = needsConvertPropertyAccess ? `this["${name}"]` : `this.${name}`;
|
||||
}
|
||||
else if (needsConvertPropertyAccess) {
|
||||
// TODO: GH#20619 Use configured quote style
|
||||
insertText = `["${name}"]`;
|
||||
replacementSpan = createTextSpanFromBounds(findChildOfKind(propertyAccessToConvert!, SyntaxKind.DotToken, sourceFile)!.getStart(sourceFile), propertyAccessToConvert!.name.end);
|
||||
}
|
||||
|
||||
if (isJsxInitializer) {
|
||||
if (insertText === undefined) insertText = name;
|
||||
insertText = `{${insertText}}`;
|
||||
}
|
||||
}
|
||||
else if (needsConvertPropertyAccess) {
|
||||
// TODO: GH#20619 Use configured quote style
|
||||
insertText = `["${name}"]`;
|
||||
replacementSpan = createTextSpanFromBounds(findChildOfKind(propertyAccessToConvert!, SyntaxKind.DotToken, sourceFile)!.getStart(sourceFile), propertyAccessToConvert!.name.end);
|
||||
|
||||
if (insertText !== undefined && !includeInsertTextCompletions) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// TODO(drosen): Right now we just permit *all* semantic meanings when calling
|
||||
@ -235,6 +244,7 @@ namespace ts.Completions {
|
||||
kind: CompletionKind,
|
||||
includeInsertTextCompletions?: boolean,
|
||||
propertyAccessToConvert?: PropertyAccessExpression | undefined,
|
||||
isJsxInitializer?: boolean,
|
||||
recommendedCompletion?: Symbol,
|
||||
symbolToOriginInfoMap?: SymbolOriginInfoMap,
|
||||
): Map<true> {
|
||||
@ -246,7 +256,7 @@ namespace ts.Completions {
|
||||
const uniques = createMap<true>();
|
||||
for (const symbol of symbols) {
|
||||
const origin = symbolToOriginInfoMap ? symbolToOriginInfoMap[getSymbolId(symbol)] : undefined;
|
||||
const entry = createCompletionEntry(symbol, location, sourceFile, typeChecker, target, kind, origin, recommendedCompletion, propertyAccessToConvert, includeInsertTextCompletions);
|
||||
const entry = createCompletionEntry(symbol, location, sourceFile, typeChecker, target, kind, origin, recommendedCompletion, propertyAccessToConvert, isJsxInitializer, includeInsertTextCompletions);
|
||||
if (!entry) {
|
||||
continue;
|
||||
}
|
||||
@ -483,6 +493,7 @@ namespace ts.Completions {
|
||||
location: Node;
|
||||
symbolToOriginInfoMap: SymbolOriginInfoMap;
|
||||
previousToken: Node;
|
||||
readonly isJsxInitializer: boolean;
|
||||
}
|
||||
function getSymbolCompletionFromEntryId(
|
||||
typeChecker: TypeChecker,
|
||||
@ -501,7 +512,7 @@ namespace ts.Completions {
|
||||
return { type: "request", request: completionData };
|
||||
}
|
||||
|
||||
const { symbols, location, completionKind, symbolToOriginInfoMap, previousToken } = completionData;
|
||||
const { symbols, location, completionKind, symbolToOriginInfoMap, previousToken, isJsxInitializer } = completionData;
|
||||
|
||||
// Find the symbol with the matching entry name.
|
||||
// We don't need to perform character checks here because we're only comparing the
|
||||
@ -510,7 +521,7 @@ namespace ts.Completions {
|
||||
return firstDefined<Symbol, SymbolCompletion>(symbols, (symbol): SymbolCompletion => { // TODO: Shouldn't need return type annotation (GH#12632)
|
||||
const origin = symbolToOriginInfoMap[getSymbolId(symbol)];
|
||||
const info = getCompletionEntryDisplayNameForSymbol(symbol, compilerOptions.target, origin, completionKind);
|
||||
return info && info.name === name && getSourceFromOrigin(origin) === source ? { type: "symbol" as "symbol", symbol, location, symbolToOriginInfoMap, previousToken } : undefined;
|
||||
return info && info.name === name && getSourceFromOrigin(origin) === source ? { type: "symbol" as "symbol", symbol, location, symbolToOriginInfoMap, previousToken, isJsxInitializer } : undefined;
|
||||
}) || { type: "none" };
|
||||
}
|
||||
|
||||
@ -678,6 +689,7 @@ namespace ts.Completions {
|
||||
readonly symbolToOriginInfoMap: SymbolOriginInfoMap;
|
||||
readonly recommendedCompletion: Symbol | undefined;
|
||||
readonly previousToken: Node | undefined;
|
||||
readonly isJsxInitializer: boolean;
|
||||
}
|
||||
type Request = { readonly kind: CompletionDataKind.JsDocTagName | CompletionDataKind.JsDocTag } | { readonly kind: CompletionDataKind.JsDocParameterName, tag: JSDocParameterTag };
|
||||
|
||||
@ -859,6 +871,7 @@ namespace ts.Completions {
|
||||
let isRightOfDot = false;
|
||||
let isRightOfOpenTag = false;
|
||||
let isStartingCloseTag = false;
|
||||
let isJsxInitializer = false;
|
||||
|
||||
let location = getTouchingPropertyName(sourceFile, position, insideJsDocTagTypeExpression); // TODO: GH#15853
|
||||
if (contextToken) {
|
||||
@ -917,6 +930,10 @@ namespace ts.Completions {
|
||||
location = contextToken;
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.JsxAttribute:
|
||||
isJsxInitializer = previousToken.kind === SyntaxKind.EqualsToken;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -962,7 +979,7 @@ namespace ts.Completions {
|
||||
log("getCompletionData: Semantic work: " + (timestamp() - semanticStart));
|
||||
|
||||
const recommendedCompletion = previousToken && getRecommendedCompletion(previousToken, typeChecker);
|
||||
return { kind: CompletionDataKind.Data, symbols, completionKind, propertyAccessToConvert, isNewIdentifierLocation, location, keywordFilters, symbolToOriginInfoMap, recommendedCompletion, previousToken };
|
||||
return { kind: CompletionDataKind.Data, symbols, completionKind, propertyAccessToConvert, isNewIdentifierLocation, location, keywordFilters, symbolToOriginInfoMap, recommendedCompletion, previousToken, isJsxInitializer };
|
||||
|
||||
type JSDocTagWithTypeExpression = JSDocParameterTag | JSDocPropertyTag | JSDocReturnTag | JSDocTypeTag | JSDocTypedefTag;
|
||||
|
||||
|
||||
23
tests/cases/fourslash/completionsJsxAttributeInitializer.ts
Normal file
23
tests/cases/fourslash/completionsJsxAttributeInitializer.ts
Normal file
@ -0,0 +1,23 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
// @Filename: /a.tsx
|
||||
////function f(this: { p: number; "a b": number }, x: number): void {
|
||||
//// <div foo=/**/ />;
|
||||
////}
|
||||
|
||||
goTo.marker();
|
||||
|
||||
verify.completionListContains("x", "(parameter) x: number", "", "parameter", undefined, undefined, {
|
||||
includeInsertTextCompletions: true,
|
||||
insertText: "{x}",
|
||||
});
|
||||
|
||||
verify.completionListContains("p", "(property) p: number", "", "property", undefined, undefined, {
|
||||
includeInsertTextCompletions: true,
|
||||
insertText: "{this.p}",
|
||||
});
|
||||
|
||||
verify.completionListContains("a b", '(property) "a b": number', "", "property", undefined, undefined, {
|
||||
includeInsertTextCompletions: true,
|
||||
insertText: '{this["a b"]}',
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user