Skip to content

Commit

Permalink
Support recommended completion for union (#24326)
Browse files Browse the repository at this point in the history
* Support recommended completion for union

* Fix for empty enum, which is not a union
  • Loading branch information
Andy authored May 22, 2018
1 parent 694a985 commit 9cda2bd
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 9 deletions.
6 changes: 4 additions & 2 deletions src/harness/fourslash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
15 changes: 9 additions & 6 deletions src/services/completions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion tests/cases/fourslash/completionsRecommended_local.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
});

Expand Down
22 changes: 22 additions & 0 deletions tests/cases/fourslash/completionsRecommended_union.ts
Original file line number Diff line number Diff line change
@@ -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,
},
);
1 change: 1 addition & 0 deletions tests/cases/fourslash/fourslash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,7 @@ declare namespace FourSlashInterface {
readonly insertText?: string,
readonly replacementSpan?: Range,
readonly hasAction?: boolean,
readonly isRecommended?: boolean,
readonly kind?: string,

// details
Expand Down

0 comments on commit 9cda2bd

Please sign in to comment.