Skip to content

Commit 54456cc

Browse files
committed
Adressing pr comments and adding test cases
1 parent 463a435 commit 54456cc

File tree

8 files changed

+118
-19
lines changed

8 files changed

+118
-19
lines changed

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7644,6 +7644,10 @@
76447644
"category": "Message",
76457645
"code": 95186
76467646
},
7647+
"Add missing comma for an object member completion '{0}'.": {
7648+
"category": "Message",
7649+
"code": 95187
7650+
},
76477651

76487652
"No value exists in scope for the shorthand property '{0}'. Either declare one or provide an initializer.": {
76497653
"category": "Error",

src/services/completions.ts

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ export enum CompletionSource {
446446
/** Case completions for switch statements */
447447
SwitchCases = "SwitchCases/",
448448
/** Completions for an Object literal expression */
449-
ObjectLiteralExpression = "ObjectLiteralExpression/",
449+
ObjectLiteralMemberWithComma = "ObjectLiteralMemberWithComma/",
450450
}
451451

452452
/** @internal */
@@ -1687,9 +1687,11 @@ function createCompletionEntry(
16871687
hasAction = true;
16881688
}
16891689

1690-
if ((contextToken && isPropertyAssignment(contextToken.parent) && findNextToken(contextToken, contextToken?.parent, sourceFile)?.kind !== SyntaxKind.CommaToken &&
1691-
completionKind === CompletionKind.ObjectPropertyDeclaration)) {
1692-
source = CompletionSource.ObjectLiteralExpression;
1690+
if (completionKind === CompletionKind.ObjectPropertyDeclaration && contextToken &&
1691+
findPrecedingToken(contextToken.pos, sourceFile, contextToken)?.kind !== SyntaxKind.CommaToken &&
1692+
findNextToken(contextToken, contextToken.parent, sourceFile)?.kind !== SyntaxKind.CommaToken &&
1693+
(findAncestor(contextToken.parent, (node: Node) => isPropertyAssignment(node))?.getLastToken() === contextToken || isMethodDeclaration(contextToken.parent.parent))) {
1694+
source = CompletionSource.ObjectLiteralMemberWithComma;
16931695
hasAction = true;
16941696
}
16951697

@@ -2675,7 +2677,7 @@ function getSymbolCompletionFromEntryId(
26752677
entryId.source === CompletionSource.ClassMemberSnippet && symbol.flags & SymbolFlags.ClassMember
26762678
|| entryId.source === CompletionSource.ObjectLiteralMethodSnippet && symbol.flags & (SymbolFlags.Property | SymbolFlags.Method)
26772679
|| getSourceFromOrigin(origin) === entryId.source
2678-
|| entryId.source === CompletionSource.ObjectLiteralExpression)
2680+
|| entryId.source === CompletionSource.ObjectLiteralMemberWithComma)
26792681
? { type: "symbol" as const, symbol, location, origin, contextToken, previousToken, isJsxInitializer, isTypeOnlyLocation }
26802682
: undefined;
26812683
}) || { type: "none" };
@@ -2871,10 +2873,10 @@ function getCompletionEntryCodeActionsAndSourceDisplay(
28712873
return { codeActions: [codeAction], sourceDisplay: undefined };
28722874
}
28732875

2874-
if (source === CompletionSource.ObjectLiteralExpression && contextToken) {
2876+
if (source === CompletionSource.ObjectLiteralMemberWithComma && contextToken) {
28752877
const changes = textChanges.ChangeTracker.with(
28762878
{ host, formatContext, preferences },
2877-
tracker=>tracker.insertText(sourceFile, contextToken.end,","));
2879+
tracker => tracker.insertText(sourceFile, contextToken.end,","));
28782880
if (changes) {
28792881
return {
28802882
sourceDisplay: undefined,
@@ -4920,6 +4922,11 @@ function tryGetObjectLikeCompletionContainer(contextToken: Node | undefined): Ob
49204922
return parent;
49214923
}
49224924
break;
4925+
case SyntaxKind.CloseBraceToken: // const x = { } |
4926+
if (parent.parent && parent.parent.parent && isMethodDeclaration(parent.parent) && isObjectLiteralExpression(parent.parent.parent)) {
4927+
return parent.parent.parent;
4928+
}
4929+
break;
49234930
case SyntaxKind.AsteriskToken:
49244931
return isMethodDeclaration(parent) ? tryCast(parent.parent, isObjectLiteralExpression) : undefined;
49254932
case SyntaxKind.AsyncKeyword:
@@ -4928,8 +4935,10 @@ function tryGetObjectLikeCompletionContainer(contextToken: Node | undefined): Ob
49284935
return (contextToken as Identifier).text === "async" && isShorthandPropertyAssignment(contextToken.parent)
49294936
? contextToken.parent.parent : undefined;
49304937
default:
4931-
if (parent.parent && isObjectLiteralExpression(parent.parent) && contextToken.kind !== SyntaxKind.ColonToken) {
4932-
return parent.parent;
4938+
const ancestorNode = findAncestor(parent, (node: Node) => isPropertyAssignment(node));
4939+
if (contextToken.kind !== SyntaxKind.ColonToken && ancestorNode && ancestorNode.getLastToken() === contextToken &&
4940+
isObjectLiteralExpression(ancestorNode.parent)) {
4941+
return ancestorNode.parent;
49334942
}
49344943
}
49354944
}

src/services/textChanges.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -601,11 +601,6 @@ export class ChangeTracker {
601601
this.replaceNode(sourceFile, oldNode, newNode, { suffix });
602602
}
603603

604-
public replacePropertyAssignmentOnSameLine(sourceFile: SourceFile, oldNode: PropertyAssignment, newNode: PropertyAssignment): void {
605-
const suffix = this.nextCommaToken(sourceFile, oldNode) ? "" : ",";
606-
this.replaceNode(sourceFile, oldNode, newNode, { suffix });
607-
}
608-
609604
public insertNodeAt(sourceFile: SourceFile, pos: number, newNode: Node, options: InsertNodeOptions = {}): void {
610605
this.replaceRange(sourceFile, createRange(pos), newNode, options);
611606
}

tests/cases/fourslash/completionsObjectLiteralExpressions1.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ verify.completions({
1515
name: "secondary",
1616
sortText: completion.SortText.OptionalMember,
1717
hasAction: true,
18-
source: completion.CompletionSource.ObjectLiteralExpression,
18+
source: completion.CompletionSource.ObjectLiteralMemberWithComma,
1919
}],
2020
preferences: {
2121
allowIncompleteCompletions: true,
@@ -26,7 +26,7 @@ verify.completions({
2626
verify.applyCodeActionFromCompletion("", {
2727
name: "secondary",
2828
description: `Add missing comma for an object member completion 'secondary'.`,
29-
source: completion.CompletionSource.ObjectLiteralExpression,
29+
source: completion.CompletionSource.ObjectLiteralMemberWithComma,
3030
newFileContent:
3131
`interface ColorPalette {
3232
primary?: string;

tests/cases/fourslash/completionsObjectLiteralExpressions2.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ verify.completions({
1818
name: "secondary",
1919
sortText: completion.SortText.OptionalMember,
2020
hasAction: true,
21-
source: completion.CompletionSource.ObjectLiteralExpression,
21+
source: completion.CompletionSource.ObjectLiteralMemberWithComma,
2222
}],
2323
preferences: {
2424
allowIncompleteCompletions: true,
@@ -29,7 +29,7 @@ verify.completions({
2929
verify.applyCodeActionFromCompletion("", {
3030
name: "secondary",
3131
description: `Add missing comma for an object member completion 'secondary'.`,
32-
source: completion.CompletionSource.ObjectLiteralExpression,
32+
source: completion.CompletionSource.ObjectLiteralMemberWithComma,
3333
newFileContent:
3434
`interface ColorPalette {
3535
primary?: string;
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/// <reference path="fourslash.ts" />
2+
////interface T {
3+
//// aaa?: string;
4+
//// foo(): void;
5+
//// }
6+
//// const obj: T = {
7+
//// foo() {
8+
//
9+
//// }
10+
//// /**/
11+
//// }
12+
13+
14+
15+
verify.completions({
16+
marker: "",
17+
includes: [{
18+
name: "aaa",
19+
sortText: completion.SortText.OptionalMember,
20+
hasAction: true,
21+
source: completion.CompletionSource.ObjectLiteralMemberWithComma,
22+
}],
23+
preferences: {
24+
allowIncompleteCompletions: true,
25+
includeInsertTextCompletions: true,
26+
},
27+
});
28+
29+
verify.applyCodeActionFromCompletion("", {
30+
name: "aaa",
31+
description: `Add missing comma for an object member completion 'aaa'.`,
32+
source: completion.CompletionSource.ObjectLiteralMemberWithComma,
33+
newFileContent:
34+
`interface T {
35+
aaa?: string;
36+
foo(): void;
37+
}
38+
const obj: T = {
39+
foo() {
40+
},
41+
42+
}`,
43+
preferences: {
44+
allowIncompleteCompletions: true,
45+
includeInsertTextCompletions: true,
46+
},
47+
});
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/// <reference path="fourslash.ts" />
2+
////interface T {
3+
//// aaa: number;
4+
//// bbb?: number;
5+
//// }
6+
//// const obj: T = {
7+
//// aaa: 1 * (2 + 3)
8+
//// /**/
9+
//// }
10+
11+
12+
13+
verify.completions({
14+
marker: "",
15+
includes: [{
16+
name: "bbb",
17+
sortText: completion.SortText.OptionalMember,
18+
hasAction: true,
19+
source: completion.CompletionSource.ObjectLiteralMemberWithComma,
20+
}],
21+
preferences: {
22+
allowIncompleteCompletions: true,
23+
includeInsertTextCompletions: true,
24+
},
25+
});
26+
27+
verify.applyCodeActionFromCompletion("", {
28+
name: "bbb",
29+
description: `Add missing comma for an object member completion 'bbb'.`,
30+
source: completion.CompletionSource.ObjectLiteralMemberWithComma,
31+
newFileContent:
32+
`interface T {
33+
aaa: number;
34+
bbb?: number;
35+
}
36+
const obj: T = {
37+
aaa: 1 * (2 + 3),
38+
39+
}`,
40+
preferences: {
41+
allowIncompleteCompletions: true,
42+
includeInsertTextCompletions: true,
43+
},
44+
});

tests/cases/fourslash/fourslash.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -914,7 +914,7 @@ declare namespace completion {
914914
TypeOnlyAlias = "TypeOnlyAlias/",
915915
ObjectLiteralMethodSnippet = "ObjectLiteralMethodSnippet/",
916916
SwitchCases = "SwitchCases/",
917-
ObjectLiteralExpression = "ObjectLiteralExpression/",
917+
ObjectLiteralMemberWithComma = "ObjectLiteralMemberWithComma/",
918918
}
919919
export const globalThisEntry: Entry;
920920
export const undefinedVarEntry: Entry;

0 commit comments

Comments
 (0)