Support recommended completion for union (#24326)

* Support recommended completion for union

* Fix for empty enum, which is not a union
This commit is contained in:
Andy 2018-05-22 13:38:28 -07:00 committed by GitHub
parent 694a985b49
commit 9cda2bdba0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 37 additions and 9 deletions

View File

@ -908,8 +908,8 @@ namespace FourSlash {
}
private verifyCompletionEntry(actual: ts.CompletionEntry, expected: FourSlashInterface.ExpectedCompletionEntry) {
const { insertText, replacementSpan, hasAction, kind, text, documentation, sourceDisplay } = typeof expected === "string"
? { insertText: undefined, replacementSpan: undefined, hasAction: undefined, kind: undefined, text: undefined, documentation: undefined, sourceDisplay: undefined }
const { insertText, replacementSpan, hasAction, isRecommended, kind, text, documentation, sourceDisplay } = typeof expected === "string"
? { insertText: undefined, replacementSpan: undefined, hasAction: undefined, isRecommended: undefined, kind: undefined, text: undefined, documentation: undefined, sourceDisplay: undefined }
: expected;
if (actual.insertText !== insertText) {
@ -926,6 +926,7 @@ namespace FourSlash {
if (kind !== undefined) assert.equal(actual.kind, kind);
assert.equal(actual.hasAction, hasAction);
assert.equal(actual.isRecommended, isRecommended);
if (text) {
const actualDetails = this.getCompletionEntryDetails(actual.name, actual.source);
@ -4747,6 +4748,7 @@ namespace FourSlashInterface {
readonly insertText?: string,
readonly replacementSpan?: FourSlash.Range,
readonly hasAction?: boolean, // If not specified, will assert that this is false.
readonly isRecommended?: boolean; // If not specified, will assert that this is false.
readonly kind?: string, // If not specified, won't assert about this
readonly text: string;
readonly documentation: string;

View File

@ -686,12 +686,15 @@ namespace ts.Completions {
}
function getRecommendedCompletion(currentToken: Node, position: number, sourceFile: SourceFile, checker: TypeChecker): Symbol | undefined {
const ty = getContextualType(currentToken, position, sourceFile, checker);
const symbol = ty && ty.symbol;
// Don't include make a recommended completion for an abstract class
return symbol && (symbol.flags & SymbolFlags.Enum || symbol.flags & SymbolFlags.Class && !isAbstractConstructorSymbol(symbol))
? getFirstSymbolInChain(symbol, currentToken, checker)
: undefined;
const contextualType = getContextualType(currentToken, position, sourceFile, checker);
// For a union, return the first one with a recommended completion.
return firstDefined(contextualType && (contextualType.isUnion() ? contextualType.types : [contextualType]), type => {
const symbol = type && type.symbol;
// Don't include make a recommended completion for an abstract class
return symbol && (symbol.flags & (SymbolFlags.EnumMember | SymbolFlags.Enum | SymbolFlags.Class) && !isAbstractConstructorSymbol(symbol))
? getFirstSymbolInChain(symbol, currentToken, checker)
: undefined;
});
}
function getContextualType(currentToken: Node, position: number, sourceFile: SourceFile, checker: TypeChecker): Type | undefined {

View File

@ -15,7 +15,7 @@
////enu = E/*let0*/;
////enu = E/*let1*/;
goTo.eachMarker(["e0"], () => {//, "e1", "let0", "let1"
goTo.eachMarker(["e0", "e1", "let0", "let1"], () => {
verify.completionListContains("Enu", "enum Enu", "", "enum", undefined, undefined, { isRecommended: true });
});

View File

@ -0,0 +1,22 @@
/// <reference path="fourslash.ts" />
// @strictNullChecks: true
////const enum E { A = "A", B = "B" }
////const enum E2 { X = "X", Y = "Y" }
////const e: E | undefined = /*a*/
////const e2: E | E2 = /*b*/
verify.completions(
{
marker: "a",
includes: { name: "E", isRecommended: true },
isNewIdentifierLocation: true,
},
{
marker: "b",
// Arbitrarily chooses one to be recommended
includes: [{ name: "E", isRecommended: true, }, { name: "E2" }],
isNewIdentifierLocation: true,
},
);

View File

@ -537,6 +537,7 @@ declare namespace FourSlashInterface {
readonly insertText?: string,
readonly replacementSpan?: Range,
readonly hasAction?: boolean,
readonly isRecommended?: boolean,
readonly kind?: string,
// details