Skip to content

Commit bd25c13

Browse files
authored
Port PR 9745 to master (microsoft#9881)
* Add completion for quote property name in object literal expression * Add fourslash tests for completion of quoted property in object literal expression * Handle object-literal expression as an argument Undo wip Undo wip Conflicts: src/services/services.ts * Add tests and baseline for object literal expression for arguments
1 parent f24341f commit bd25c13

5 files changed

+147
-6
lines changed

src/services/services.ts

+43-6
Original file line numberDiff line numberDiff line change
@@ -4296,6 +4296,7 @@ namespace ts {
42964296
kindModifiers: getSymbolModifiers(symbol),
42974297
sortText: "0",
42984298
};
4299+
42994300
}
43004301

43014302
function getCompletionEntriesFromSymbols(symbols: Symbol[], entries: CompletionEntry[], location: Node, performCharacterChecks: boolean): Map<string> {
@@ -4324,22 +4325,58 @@ namespace ts {
43244325
return undefined;
43254326
}
43264327

4327-
const argumentInfo = SignatureHelp.getContainingArgumentInfo(node, position, sourceFile);
4328-
if (argumentInfo) {
4329-
// Get string literal completions from specialized signatures of the target
4330-
return getStringLiteralCompletionEntriesFromCallExpression(argumentInfo);
4328+
if (node.parent.kind === SyntaxKind.PropertyAssignment && node.parent.parent.kind === SyntaxKind.ObjectLiteralExpression) {
4329+
// Get quoted name of properties of the object literal expression
4330+
// i.e. interface ConfigFiles {
4331+
// 'jspm:dev': string
4332+
// }
4333+
// let files: ConfigFiles = {
4334+
// '/*completion position*/'
4335+
// }
4336+
//
4337+
// function foo(c: ConfigFiles) {}
4338+
// foo({
4339+
// '/*completion position*/'
4340+
// });
4341+
return getStringLiteralCompletionEntriesFromPropertyAssignment(<ObjectLiteralElement>node.parent);
43314342
}
43324343
else if (isElementAccessExpression(node.parent) && node.parent.argumentExpression === node) {
43334344
// Get all names of properties on the expression
4345+
// i.e. interface A {
4346+
// 'prop1': string
4347+
// }
4348+
// let a: A;
4349+
// a['/*completion position*/']
43344350
return getStringLiteralCompletionEntriesFromElementAccess(node.parent);
43354351
}
43364352
else {
4337-
// Otherwise, get the completions from the contextual type if one exists
4353+
const argumentInfo = SignatureHelp.getContainingArgumentInfo(node, position, sourceFile);
4354+
if (argumentInfo) {
4355+
// Get string literal completions from specialized signatures of the target
4356+
// i.e. declare function f(a: 'A');
4357+
// f("/*completion position*/")
4358+
return getStringLiteralCompletionEntriesFromCallExpression(argumentInfo, node);
4359+
}
4360+
4361+
// Get completion for string literal from string literal type
4362+
// i.e. var x: "hi" | "hello" = "/*completion position*/"
43384363
return getStringLiteralCompletionEntriesFromContextualType(<StringLiteral>node);
43394364
}
43404365
}
43414366

4342-
function getStringLiteralCompletionEntriesFromCallExpression(argumentInfo: SignatureHelp.ArgumentListInfo) {
4367+
function getStringLiteralCompletionEntriesFromPropertyAssignment(element: ObjectLiteralElement) {
4368+
const typeChecker = program.getTypeChecker();
4369+
const type = typeChecker.getContextualType((<ObjectLiteralExpression>element.parent));
4370+
const entries: CompletionEntry[] = [];
4371+
if (type) {
4372+
getCompletionEntriesFromSymbols(type.getApparentProperties(), entries, element, /*performCharacterChecks*/false);
4373+
if (entries.length) {
4374+
return { isMemberCompletion: true, isNewIdentifierLocation: true, entries };
4375+
}
4376+
}
4377+
}
4378+
4379+
function getStringLiteralCompletionEntriesFromCallExpression(argumentInfo: SignatureHelp.ArgumentListInfo, location: Node) {
43434380
const typeChecker = program.getTypeChecker();
43444381
const candidates: Signature[] = [];
43454382
const entries: CompletionEntry[] = [];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
//// export interface Configfiles {
4+
//// jspm: string;
5+
//// 'jspm:browser': string;
6+
//// 'jspm:dev': string;
7+
//// 'jspm:node': string;
8+
//// }
9+
10+
//// let files: Configfiles;
11+
//// files = {
12+
//// /*0*/: '',
13+
//// '/*1*/': ''
14+
//// }
15+
16+
goTo.marker('0');
17+
verify.completionListContains("jspm");
18+
verify.completionListAllowsNewIdentifier();
19+
verify.memberListCount(1);
20+
21+
goTo.marker('1');
22+
verify.completionListContains("jspm:dev");
23+
verify.completionListAllowsNewIdentifier();
24+
verify.memberListCount(4);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
//// export interface Config {
4+
//// files: ConfigFiles
5+
//// }
6+
7+
//// export interface ConfigFiles {
8+
//// jspm: string;
9+
//// 'jspm:browser': string;
10+
//// 'jspm:dev': string;
11+
//// 'jspm:node': string;
12+
//// }
13+
14+
//// let config: Config;
15+
//// config = {
16+
//// files: {
17+
//// /*0*/: '',
18+
//// '/*1*/': ''
19+
//// }
20+
//// }
21+
22+
goTo.marker('0');
23+
verify.completionListContains("jspm");
24+
verify.completionListAllowsNewIdentifier();
25+
verify.memberListCount(1);
26+
27+
goTo.marker('1');
28+
verify.completionListContains("jspm:dev");
29+
verify.completionListAllowsNewIdentifier();
30+
verify.memberListCount(4);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
//// let configFiles1: {
4+
//// jspm: string;
5+
//// 'jspm:browser': string;
6+
//// } = {
7+
//// /*0*/: "",
8+
//// }
9+
10+
//// let configFiles2: {
11+
//// jspm: string;
12+
//// 'jspm:browser': string;
13+
//// } = {
14+
//// jspm: "",
15+
//// '/*1*/': ""
16+
//// }
17+
18+
goTo.marker('0');
19+
verify.completionListContains("jspm");
20+
verify.completionListAllowsNewIdentifier();
21+
verify.memberListCount(1);
22+
23+
goTo.marker('1');
24+
verify.completionListContains("jspm:browser");
25+
verify.completionListAllowsNewIdentifier();
26+
verify.memberListCount(2);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
//// export interface ConfigFiles {
4+
//// jspm: string;
5+
//// 'jspm:browser': string;
6+
//// 'jspm:dev': string;
7+
//// 'jspm:node': string;
8+
//// }
9+
10+
//// function foo(c: ConfigFiles) {}
11+
//// foo({
12+
//// j/*0*/: "",
13+
//// "/*1*/": "",
14+
//// })
15+
16+
goTo.marker('0');
17+
verify.completionListContains("jspm");
18+
verify.completionListAllowsNewIdentifier();
19+
verify.memberListCount(1);
20+
21+
goTo.marker('1');
22+
verify.completionListContains("jspm:dev");
23+
verify.completionListAllowsNewIdentifier();
24+
verify.memberListCount(4);

0 commit comments

Comments
 (0)