Support incomplete identifier in JSX initializer completions (#21681) (#21692)

This commit is contained in:
Andy 2018-02-06 12:09:49 -08:00 committed by GitHub
parent 07c9505cd3
commit c46ab32070
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 6 deletions

View File

@ -3166,6 +3166,9 @@ Actual: ${stringify(fullActual)}`);
assert.equal(item.hasAction, hasAction, "hasAction");
assert.equal(item.isRecommended, options && options.isRecommended, "isRecommended");
assert.equal(item.insertText, options && options.insertText, "insertText");
if (options && options.replacementSpan) { // TODO: GH#21679
assert.deepEqual(item.replacementSpan, options && options.replacementSpan && textSpanFromRange(options.replacementSpan), "replacementSpan");
}
}
private findFile(indexOrName: string | number) {
@ -4622,6 +4625,7 @@ namespace FourSlashInterface {
sourceDisplay: string;
isRecommended?: true;
insertText?: string;
replacementSpan?: FourSlash.Range;
}
export interface NewContentOptions {

View File

@ -167,7 +167,7 @@ namespace ts.Completions {
origin: SymbolOriginInfo | undefined,
recommendedCompletion: Symbol | undefined,
propertyAccessToConvert: PropertyAccessExpression | undefined,
isJsxInitializer: boolean,
isJsxInitializer: IsJsxInitializer,
includeInsertTextCompletions: boolean,
): CompletionEntry | undefined {
const info = getCompletionEntryDisplayNameForSymbol(symbol, target, origin, kind);
@ -193,6 +193,9 @@ namespace ts.Completions {
if (isJsxInitializer) {
if (insertText === undefined) insertText = name;
insertText = `{${insertText}}`;
if (typeof isJsxInitializer !== "boolean") {
replacementSpan = createTextSpanFromNode(isJsxInitializer, sourceFile);
}
}
}
@ -250,7 +253,7 @@ namespace ts.Completions {
kind: CompletionKind,
includeInsertTextCompletions?: boolean,
propertyAccessToConvert?: PropertyAccessExpression | undefined,
isJsxInitializer?: boolean,
isJsxInitializer?: IsJsxInitializer,
recommendedCompletion?: Symbol,
symbolToOriginInfoMap?: SymbolOriginInfoMap,
): Map<true> {
@ -499,7 +502,7 @@ namespace ts.Completions {
location: Node;
symbolToOriginInfoMap: SymbolOriginInfoMap;
previousToken: Node;
readonly isJsxInitializer: boolean;
readonly isJsxInitializer: IsJsxInitializer;
}
function getSymbolCompletionFromEntryId(
typeChecker: TypeChecker,
@ -683,6 +686,8 @@ namespace ts.Completions {
}
const enum CompletionDataKind { Data, JsDocTagName, JsDocTag, JsDocParameterName }
/** true: after the `=` sign but no identifier has been typed yet. Else is the Identifier after the initializer. */
type IsJsxInitializer = boolean | Identifier;
interface CompletionData {
readonly kind: CompletionDataKind.Data;
readonly symbols: ReadonlyArray<Symbol>;
@ -695,7 +700,7 @@ namespace ts.Completions {
readonly symbolToOriginInfoMap: SymbolOriginInfoMap;
readonly recommendedCompletion: Symbol | undefined;
readonly previousToken: Node | undefined;
readonly isJsxInitializer: boolean;
readonly isJsxInitializer: IsJsxInitializer;
}
type Request = { readonly kind: CompletionDataKind.JsDocTagName | CompletionDataKind.JsDocTag } | { readonly kind: CompletionDataKind.JsDocParameterName, tag: JSDocParameterTag };
@ -877,7 +882,7 @@ namespace ts.Completions {
let isRightOfDot = false;
let isRightOfOpenTag = false;
let isStartingCloseTag = false;
let isJsxInitializer = false;
let isJsxInitializer: IsJsxInitializer = false;
let location = getTouchingPropertyName(sourceFile, position, insideJsDocTagTypeExpression); // TODO: GH#15853
if (contextToken) {
@ -938,7 +943,15 @@ namespace ts.Completions {
break;
case SyntaxKind.JsxAttribute:
isJsxInitializer = previousToken.kind === SyntaxKind.EqualsToken;
switch (previousToken.kind) {
case SyntaxKind.EqualsToken:
isJsxInitializer = true;
break;
case SyntaxKind.Identifier:
if (previousToken !== (parent as JsxAttribute).name) {
isJsxInitializer = previousToken as Identifier;
}
}
break;
}
}

View File

@ -0,0 +1,13 @@
/// <reference path="fourslash.ts" />
// @Filename: /a.tsx
////const foo = 0;
////<div x=[|f/**/|] />;
const [replacementSpan] = test.ranges();
goTo.marker();
verify.completionListContains("foo", "const foo: 0", undefined, "const", undefined, undefined, {
includeInsertTextCompletions: true,
insertText: "{foo}",
replacementSpan,
});

View File

@ -157,6 +157,7 @@ declare namespace FourSlashInterface {
sourceDisplay?: string,
isRecommended?: true,
insertText?: string,
replacementSpan?: Range,
},
): void;
completionListItemsCountIsGreaterThan(count: number): void;