Skip to content

Commit 210d8b8

Browse files
author
Andy Hanson
committed
Support recommended completion for union
1 parent 7106a58 commit 210d8b8

File tree

4 files changed

+36
-8
lines changed

4 files changed

+36
-8
lines changed

src/harness/fourslash.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -908,8 +908,8 @@ namespace FourSlash {
908908
}
909909

910910
private verifyCompletionEntry(actual: ts.CompletionEntry, expected: FourSlashInterface.ExpectedCompletionEntry) {
911-
const { insertText, replacementSpan, hasAction, kind, text, documentation, sourceDisplay } = typeof expected === "string"
912-
? { insertText: undefined, replacementSpan: undefined, hasAction: undefined, kind: undefined, text: undefined, documentation: undefined, sourceDisplay: undefined }
911+
const { insertText, replacementSpan, hasAction, isRecommended, kind, text, documentation, sourceDisplay } = typeof expected === "string"
912+
? { insertText: undefined, replacementSpan: undefined, hasAction: undefined, isRecommended: undefined, kind: undefined, text: undefined, documentation: undefined, sourceDisplay: undefined }
913913
: expected;
914914

915915
if (actual.insertText !== insertText) {
@@ -926,6 +926,7 @@ namespace FourSlash {
926926
if (kind !== undefined) assert.equal(actual.kind, kind);
927927

928928
assert.equal(actual.hasAction, hasAction);
929+
assert.equal(actual.isRecommended, isRecommended);
929930

930931
if (text) {
931932
const actualDetails = this.getCompletionEntryDetails(actual.name, actual.source);
@@ -4747,6 +4748,7 @@ namespace FourSlashInterface {
47474748
readonly insertText?: string,
47484749
readonly replacementSpan?: FourSlash.Range,
47494750
readonly hasAction?: boolean, // If not specified, will assert that this is false.
4751+
readonly isRecommended?: boolean; // If not specified, will assert that this is false.
47504752
readonly kind?: string, // If not specified, won't assert about this
47514753
readonly text: string;
47524754
readonly documentation: string;

src/services/completions.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -681,12 +681,15 @@ namespace ts.Completions {
681681
}
682682

683683
function getRecommendedCompletion(currentToken: Node, position: number, sourceFile: SourceFile, checker: TypeChecker): Symbol | undefined {
684-
const ty = getContextualType(currentToken, position, sourceFile, checker);
685-
const symbol = ty && ty.symbol;
686-
// Don't include make a recommended completion for an abstract class
687-
return symbol && (symbol.flags & SymbolFlags.Enum || symbol.flags & SymbolFlags.Class && !isAbstractConstructorSymbol(symbol))
688-
? getFirstSymbolInChain(symbol, currentToken, checker)
689-
: undefined;
684+
const contextualType = getContextualType(currentToken, position, sourceFile, checker);
685+
// For a union `A | B`, just recommend the first one arbitrarily.
686+
return firstDefined(contextualType && (contextualType.isUnion() ? contextualType.types : [contextualType]), type => {
687+
const symbol = type && type.symbol;
688+
// Don't include make a recommended completion for an abstract class
689+
return symbol && (symbol.flags & SymbolFlags.EnumMember || symbol.flags & SymbolFlags.Class && !isAbstractConstructorSymbol(symbol))
690+
? getFirstSymbolInChain(symbol, currentToken, checker)
691+
: undefined;
692+
});
690693
}
691694

692695
function getContextualType(currentToken: Node, position: number, sourceFile: SourceFile, checker: TypeChecker): Type | undefined {
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @strictNullChecks: true
4+
5+
////const enum E { A = "A", B = "B" }
6+
////const enum E2 { X = "X", Y = "Y" }
7+
////const e: E | undefined = /*a*/
8+
////const e2: E | E2 = /*b*/
9+
10+
verify.completions(
11+
{
12+
marker: "a",
13+
includes: { name: "E", isRecommended: true },
14+
isNewIdentifierLocation: true,
15+
},
16+
{
17+
marker: "b",
18+
// Arbitrarily chooses one to be recommended
19+
includes: [{ name: "E", isRecommended: true, }, { name: "E2" }],
20+
isNewIdentifierLocation: true,
21+
},
22+
);

tests/cases/fourslash/fourslash.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,7 @@ declare namespace FourSlashInterface {
537537
readonly insertText?: string,
538538
readonly replacementSpan?: Range,
539539
readonly hasAction?: boolean,
540+
readonly isRecommended?: boolean,
540541
readonly kind?: string,
541542

542543
// details

0 commit comments

Comments
 (0)