Skip to content

Commit 12d5063

Browse files
mjbvzmhegazy
authored andcommitted
Add kindModifier to mark if a completion item is for an optional field (#20839)
* Add kindModifier to mark if a completion item is for an optional field For #12458 Adds a new KindModifier for completion items to mark when a property is optional. This can be used by editors to either change the item icon or add a `?` to the item text * Add method test * Baseline-accept
1 parent b36d614 commit 12d5063

File tree

7 files changed

+38
-8
lines changed

7 files changed

+38
-8
lines changed

src/harness/fourslash.ts

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -872,7 +872,7 @@ namespace FourSlash {
872872
});
873873
}
874874

875-
public verifyCompletionListContains(entryId: ts.Completions.CompletionEntryIdentifier, text?: string, documentation?: string, kind?: string, spanIndex?: number, hasAction?: boolean, options?: FourSlashInterface.VerifyCompletionListContainsOptions) {
875+
public verifyCompletionListContains(entryId: ts.Completions.CompletionEntryIdentifier, text?: string, documentation?: string, kind?: string | { kind?: string, kindModifiers?: string }, spanIndex?: number, hasAction?: boolean, options?: FourSlashInterface.VerifyCompletionListContainsOptions) {
876876
const completions = this.getCompletionListAtCaret(options);
877877
if (completions) {
878878
this.assertItemInCompletionList(completions.entries, entryId, text, documentation, kind, spanIndex, hasAction, options);
@@ -893,7 +893,7 @@ namespace FourSlash {
893893
* @param expectedKind the kind of symbol (see ScriptElementKind)
894894
* @param spanIndex the index of the range that the completion item's replacement text span should match
895895
*/
896-
public verifyCompletionListDoesNotContain(entryId: ts.Completions.CompletionEntryIdentifier, expectedText?: string, expectedDocumentation?: string, expectedKind?: string, spanIndex?: number, options?: FourSlashInterface.CompletionsAtOptions) {
896+
public verifyCompletionListDoesNotContain(entryId: ts.Completions.CompletionEntryIdentifier, expectedText?: string, expectedDocumentation?: string, expectedKind?: string | { kind?: string, kindModifiers?: string }, spanIndex?: number, options?: FourSlashInterface.CompletionsAtOptions) {
897897
let replacementSpan: ts.TextSpan;
898898
if (spanIndex !== undefined) {
899899
replacementSpan = this.getTextSpanForRangeAtIndex(spanIndex);
@@ -902,7 +902,7 @@ namespace FourSlash {
902902
const completions = this.getCompletionListAtCaret(options);
903903
if (completions) {
904904
let filterCompletions = completions.entries.filter(e => e.name === entryId.name && e.source === entryId.source);
905-
filterCompletions = expectedKind ? filterCompletions.filter(e => e.kind === expectedKind) : filterCompletions;
905+
filterCompletions = expectedKind ? filterCompletions.filter(e => e.kind === expectedKind || (typeof expectedKind === "object" && e.kind === expectedKind.kind)) : filterCompletions;
906906
filterCompletions = filterCompletions.filter(entry => {
907907
const details = this.getCompletionEntryDetails(entry.name);
908908
const documentation = details && ts.displayPartsToString(details.documentation);
@@ -3089,7 +3089,7 @@ Actual: ${stringify(fullActual)}`);
30893089
entryId: ts.Completions.CompletionEntryIdentifier,
30903090
text: string | undefined,
30913091
documentation: string | undefined,
3092-
kind: string | undefined,
3092+
kind: string | undefined | { kind?: string, kindModifiers?: string },
30933093
spanIndex: number | undefined,
30943094
hasAction: boolean | undefined,
30953095
options: FourSlashInterface.VerifyCompletionListContainsOptions | undefined,
@@ -3123,9 +3123,21 @@ Actual: ${stringify(fullActual)}`);
31233123
}
31243124

31253125
if (kind !== undefined) {
3126-
assert.equal(item.kind, kind, this.assertionMessageAtLastKnownMarker("completion item kind for " + entryId));
3126+
if (typeof kind === "string") {
3127+
assert.equal(item.kind, kind, this.assertionMessageAtLastKnownMarker("completion item kind for " + entryId));
3128+
}
3129+
else {
3130+
if (kind.kind) {
3131+
assert.equal(item.kind, kind.kind, this.assertionMessageAtLastKnownMarker("completion item kind for " + entryId));
3132+
}
3133+
if (kind.kindModifiers !== undefined) {
3134+
assert.equal(item.kindModifiers, kind.kindModifiers, this.assertionMessageAtLastKnownMarker("completion item kindModifiers for " + entryId));
3135+
}
3136+
}
31273137
}
31283138

3139+
3140+
31293141
if (spanIndex !== undefined) {
31303142
const span = this.getTextSpanForRangeAtIndex(spanIndex);
31313143
assert.isTrue(TestState.textSpansEqual(span, item.replacementSpan), this.assertionMessageAtLastKnownMarker(stringify(span) + " does not equal " + stringify(item.replacementSpan) + " replacement span for " + entryId));
@@ -3842,7 +3854,7 @@ namespace FourSlashInterface {
38423854

38433855
// Verifies the completion list contains the specified symbol. The
38443856
// completion list is brought up if necessary
3845-
public completionListContains(entryId: string | ts.Completions.CompletionEntryIdentifier, text?: string, documentation?: string, kind?: string, spanIndex?: number, hasAction?: boolean, options?: VerifyCompletionListContainsOptions) {
3857+
public completionListContains(entryId: string | ts.Completions.CompletionEntryIdentifier, text?: string, documentation?: string, kind?: string | { kind?: string, kindModifiers?: string }, spanIndex?: number, hasAction?: boolean, options?: VerifyCompletionListContainsOptions) {
38463858
if (typeof entryId === "string") {
38473859
entryId = { name: entryId, source: undefined };
38483860
}

src/services/symbolDisplay.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,14 @@ namespace ts.SymbolDisplay {
9191
}
9292

9393
export function getSymbolModifiers(symbol: Symbol): string {
94-
return symbol && symbol.declarations && symbol.declarations.length > 0
94+
const nodeModifiers = symbol && symbol.declarations && symbol.declarations.length > 0
9595
? getNodeModifiers(symbol.declarations[0])
9696
: ScriptElementKindModifier.none;
97+
98+
const symbolModifiers = symbol && symbol.flags & SymbolFlags.Optional ?
99+
ScriptElementKindModifier.optionalModifier
100+
: ScriptElementKindModifier.none;
101+
return nodeModifiers && symbolModifiers ? nodeModifiers + "," + symbolModifiers : nodeModifiers || symbolModifiers;
97102
}
98103

99104
interface SymbolDisplayPartsDocumentationAndSymbolKind {

src/services/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,7 @@ namespace ts {
954954
ambientModifier = "declare",
955955
staticModifier = "static",
956956
abstractModifier = "abstract",
957+
optionalModifier = "optional"
957958
}
958959

959960
export const enum ClassificationTypeNames {

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4505,6 +4505,7 @@ declare namespace ts {
45054505
ambientModifier = "declare",
45064506
staticModifier = "static",
45074507
abstractModifier = "abstract",
4508+
optionalModifier = "optional",
45084509
}
45094510
enum ClassificationTypeNames {
45104511
comment = "comment",

tests/baselines/reference/api/typescript.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4505,6 +4505,7 @@ declare namespace ts {
45054505
ambientModifier = "declare",
45064506
staticModifier = "static",
45074507
abstractModifier = "abstract",
4508+
optionalModifier = "optional",
45084509
}
45094510
enum ClassificationTypeNames {
45104511
comment = "comment",
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
////interface A { a?: number; method?(): number; };
4+
////function f(x: A) {
5+
////x./*a*/;
6+
////}
7+
8+
goTo.marker("a");
9+
verify.completionListContains("a", /* text */ undefined, /* documentation */ undefined, { kindModifiers: "optional" });
10+
verify.completionListContains("method", /* text */ undefined, /* documentation */ undefined, { kindModifiers: "optional" });

tests/cases/fourslash/fourslash.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ declare namespace FourSlashInterface {
146146
entryId: string | { name: string, source?: string },
147147
text?: string,
148148
documentation?: string,
149-
kind?: string,
149+
kind?: string | { kind?: string, kindModifiers?: string },
150150
spanIndex?: number,
151151
hasAction?: boolean,
152152
options?: { includeExternalModuleExports?: boolean, sourceDisplay?: string, isRecommended?: true },

0 commit comments

Comments
 (0)