From 9b29d2ea0184453bfbb87a4513691d0fc3cbc15c Mon Sep 17 00:00:00 2001 From: Vincent Boivin Date: Mon, 31 Aug 2020 11:25:53 -0400 Subject: [PATCH 1/7] Added fourslash tests to work on the bug --- ...ringLiteralTypeAsIndexedAccessTypeObject.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 tests/cases/fourslash/completionListsStringLiteralTypeAsIndexedAccessTypeObject.ts diff --git a/tests/cases/fourslash/completionListsStringLiteralTypeAsIndexedAccessTypeObject.ts b/tests/cases/fourslash/completionListsStringLiteralTypeAsIndexedAccessTypeObject.ts new file mode 100644 index 0000000000000..eaac523d7abd6 --- /dev/null +++ b/tests/cases/fourslash/completionListsStringLiteralTypeAsIndexedAccessTypeObject.ts @@ -0,0 +1,18 @@ +/// + +//// let firstCase: "/*case_1*/"["foo"] +//// let secondCase: "b/*case_2*/"["bar"] +//// let thirdCase: "c/*case_3*/"["baz"] +//// let fourthCase: "en/*case_4*/"["qux"] +//// interface Foo { +//// foo: string; +//// bar: string; +//// } +//// let fifthCase: Foo["b/*case_5*/"] +//// let sixthCase: Foo["f/*case_6*/"] + +// fourslash tests for issue 40322 +verify.completions({marker: ["case_1", "case_2", "case_3", "case_4"], exact: undefined, isNewIdentifierLocation: true}) + +// fourslash regression tests for previous implementation +verify.completions({marker: ["case_5", "case_6"], includes: ["bar", "foo"]}) \ No newline at end of file From 65a01bcdf381673b30a141801d082bf8863dd3c2 Mon Sep 17 00:00:00 2001 From: Vincent Boivin Date: Mon, 7 Sep 2020 22:51:55 -0400 Subject: [PATCH 2/7] fix(40322): bad completions for string literal type as indexed access type object --- src/services/stringCompletions.ts | 7 ++++++- ...tringLiteralTypeAsIndexedAccessTypeObject.ts | 17 ++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/services/stringCompletions.ts b/src/services/stringCompletions.ts index c3473b6251eae..3e68bddbdf53d 100644 --- a/src/services/stringCompletions.ts +++ b/src/services/stringCompletions.ts @@ -121,7 +121,12 @@ namespace ts.Completions.StringCompletions { // bar: string; // } // let x: Foo["/*completion position*/"] - return stringLiteralCompletionsFromProperties(typeChecker.getTypeFromTypeNode((parent.parent as IndexedAccessTypeNode).objectType)); + const { objectType } = parent.parent as IndexedAccessTypeNode; + const isNodeAnObjectTypeStringLiteral = node.text === (objectType as any).literal?.text; + if(!isNodeAnObjectTypeStringLiteral){ + return stringLiteralCompletionsFromProperties(typeChecker.getTypeFromTypeNode(objectType)); + } + return undefined; case SyntaxKind.ImportType: return { kind: StringLiteralCompletionKind.Paths, paths: getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker) }; case SyntaxKind.UnionType: { diff --git a/tests/cases/fourslash/completionListsStringLiteralTypeAsIndexedAccessTypeObject.ts b/tests/cases/fourslash/completionListsStringLiteralTypeAsIndexedAccessTypeObject.ts index eaac523d7abd6..f1e4e761fa52b 100644 --- a/tests/cases/fourslash/completionListsStringLiteralTypeAsIndexedAccessTypeObject.ts +++ b/tests/cases/fourslash/completionListsStringLiteralTypeAsIndexedAccessTypeObject.ts @@ -1,18 +1,13 @@ /// -//// let firstCase: "/*case_1*/"["foo"] +//// let firstCase: "a/*case_1*/"["foo"] //// let secondCase: "b/*case_2*/"["bar"] //// let thirdCase: "c/*case_3*/"["baz"] //// let fourthCase: "en/*case_4*/"["qux"] -//// interface Foo { -//// foo: string; -//// bar: string; -//// } -//// let fifthCase: Foo["b/*case_5*/"] -//// let sixthCase: Foo["f/*case_6*/"] // fourslash tests for issue 40322 -verify.completions({marker: ["case_1", "case_2", "case_3", "case_4"], exact: undefined, isNewIdentifierLocation: true}) - -// fourslash regression tests for previous implementation -verify.completions({marker: ["case_5", "case_6"], includes: ["bar", "foo"]}) \ No newline at end of file +verify.completions({ + marker: ["case_1", "case_2", "case_3", "case_4"], + exact: undefined, + isNewIdentifierLocation: true, +}); From edb8eb6f8897036ff87b2c7ab746f612e22474cc Mon Sep 17 00:00:00 2001 From: Vincent Boivin Date: Tue, 8 Sep 2020 09:38:29 -0400 Subject: [PATCH 3/7] Added regression tests --- src/services/stringCompletions.ts | 5 ++- ...ingLiteralTypeAsIndexedAccessTypeObject.ts | 40 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/services/stringCompletions.ts b/src/services/stringCompletions.ts index 88dc87169e1f8..705bd19f64918 100644 --- a/src/services/stringCompletions.ts +++ b/src/services/stringCompletions.ts @@ -131,7 +131,10 @@ namespace ts.Completions.StringCompletions { // } // let x: Foo["/*completion position*/"] const { objectType } = grandParent as IndexedAccessTypeNode; - const isNodeAnObjectTypeStringLiteral = node.text === (objectType as any).literal?.text; + let isNodeAnObjectTypeStringLiteral; + if((objectType as any).literal){ + isNodeAnObjectTypeStringLiteral = node.text === (objectType as any).literal.text; + } if(!isNodeAnObjectTypeStringLiteral){ return stringLiteralCompletionsFromProperties(typeChecker.getTypeFromTypeNode(objectType)); } diff --git a/tests/cases/fourslash/completionListsStringLiteralTypeAsIndexedAccessTypeObject.ts b/tests/cases/fourslash/completionListsStringLiteralTypeAsIndexedAccessTypeObject.ts index f1e4e761fa52b..371ca53f8827d 100644 --- a/tests/cases/fourslash/completionListsStringLiteralTypeAsIndexedAccessTypeObject.ts +++ b/tests/cases/fourslash/completionListsStringLiteralTypeAsIndexedAccessTypeObject.ts @@ -4,6 +4,12 @@ //// let secondCase: "b/*case_2*/"["bar"] //// let thirdCase: "c/*case_3*/"["baz"] //// let fourthCase: "en/*case_4*/"["qux"] +//// interface Foo { +//// bar: string; +//// qux: string; +//// } +//// let fifthCase: Foo["b/*case_5*/"] +//// let sixthCase: Foo["qu/*case_6*/"] // fourslash tests for issue 40322 verify.completions({ @@ -11,3 +17,37 @@ verify.completions({ exact: undefined, isNewIdentifierLocation: true, }); + +const [ + { fileName }, + _, + __, + ___, + fifthCaseMarker, + sixthCaseMarker, +] = test.markers(); + +// regression tests +verify.completions({ + marker: "case_5", + includes: { + name: "bar", + replacementSpan: { + fileName, + pos: fifthCaseMarker.position - 1, + end: fifthCaseMarker.position, + }, + }, +}); + +verify.completions({ + marker: "case_6", + includes: { + name: "qux", + replacementSpan: { + fileName, + pos: sixthCaseMarker.position - 2, + end: sixthCaseMarker.position, + }, + }, +}); From ee24fdf4683b831417b4928c085d405cba3a4656 Mon Sep 17 00:00:00 2001 From: Vincent Boivin Date: Tue, 8 Sep 2020 13:48:12 -0400 Subject: [PATCH 4/7] Using nodes instead of text --- src/services/stringCompletions.ts | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/services/stringCompletions.ts b/src/services/stringCompletions.ts index 705bd19f64918..c9fd7bfdd0e7f 100644 --- a/src/services/stringCompletions.ts +++ b/src/services/stringCompletions.ts @@ -130,15 +130,10 @@ namespace ts.Completions.StringCompletions { // bar: string; // } // let x: Foo["/*completion position*/"] - const { objectType } = grandParent as IndexedAccessTypeNode; - let isNodeAnObjectTypeStringLiteral; - if((objectType as any).literal){ - isNodeAnObjectTypeStringLiteral = node.text === (objectType as any).literal.text; - } - if(!isNodeAnObjectTypeStringLiteral){ - return stringLiteralCompletionsFromProperties(typeChecker.getTypeFromTypeNode(objectType)); + if (parent !== (grandParent as IndexedAccessTypeNode).indexType) { + return undefined; } - return undefined; + return stringLiteralCompletionsFromProperties(typeChecker.getTypeFromTypeNode((grandParent as IndexedAccessTypeNode).objectType)); case SyntaxKind.ImportType: return { kind: StringLiteralCompletionKind.Paths, paths: getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker) }; case SyntaxKind.UnionType: { From ad303f349490556262fee6623502a6ab812e90d4 Mon Sep 17 00:00:00 2001 From: Vincent Boivin Date: Tue, 8 Sep 2020 14:35:16 -0400 Subject: [PATCH 5/7] Add verification for parenthesized nodes --- src/services/stringCompletions.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/services/stringCompletions.ts b/src/services/stringCompletions.ts index c9fd7bfdd0e7f..893e90642d8ed 100644 --- a/src/services/stringCompletions.ts +++ b/src/services/stringCompletions.ts @@ -130,10 +130,11 @@ namespace ts.Completions.StringCompletions { // bar: string; // } // let x: Foo["/*completion position*/"] - if (parent !== (grandParent as IndexedAccessTypeNode).indexType) { + const { indexType, objectType } = grandParent as IndexedAccessTypeNode; + if (!isParenthesizedTypeNode(indexType) && parent !== indexType) { return undefined; } - return stringLiteralCompletionsFromProperties(typeChecker.getTypeFromTypeNode((grandParent as IndexedAccessTypeNode).objectType)); + return stringLiteralCompletionsFromProperties(typeChecker.getTypeFromTypeNode(objectType)); case SyntaxKind.ImportType: return { kind: StringLiteralCompletionKind.Paths, paths: getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker) }; case SyntaxKind.UnionType: { From 44f89d1d883093d5a6b9848ba1119a6579ba55d2 Mon Sep 17 00:00:00 2001 From: Vincent Boivin Date: Tue, 8 Sep 2020 15:42:04 -0400 Subject: [PATCH 6/7] Using range check --- src/services/stringCompletions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/stringCompletions.ts b/src/services/stringCompletions.ts index 893e90642d8ed..5c51f0c3b385e 100644 --- a/src/services/stringCompletions.ts +++ b/src/services/stringCompletions.ts @@ -131,7 +131,7 @@ namespace ts.Completions.StringCompletions { // } // let x: Foo["/*completion position*/"] const { indexType, objectType } = grandParent as IndexedAccessTypeNode; - if (!isParenthesizedTypeNode(indexType) && parent !== indexType) { + if (!rangeContainsPosition(indexType, position)) { return undefined; } return stringLiteralCompletionsFromProperties(typeChecker.getTypeFromTypeNode(objectType)); From 30a50a6ccd0176e37cdd892212bc5c2364ca7a1b Mon Sep 17 00:00:00 2001 From: Vincent Boivin Date: Tue, 8 Sep 2020 19:26:28 -0400 Subject: [PATCH 7/7] Change test markers --- ...ingLiteralTypeAsIndexedAccessTypeObject.ts | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/tests/cases/fourslash/completionListsStringLiteralTypeAsIndexedAccessTypeObject.ts b/tests/cases/fourslash/completionListsStringLiteralTypeAsIndexedAccessTypeObject.ts index 371ca53f8827d..b504720b989db 100644 --- a/tests/cases/fourslash/completionListsStringLiteralTypeAsIndexedAccessTypeObject.ts +++ b/tests/cases/fourslash/completionListsStringLiteralTypeAsIndexedAccessTypeObject.ts @@ -18,24 +18,18 @@ verify.completions({ isNewIdentifierLocation: true, }); -const [ - { fileName }, - _, - __, - ___, - fifthCaseMarker, - sixthCaseMarker, -] = test.markers(); - // regression tests +const test5 = test.marker("case_5"); +const test6 = test.marker("case_6"); + verify.completions({ marker: "case_5", includes: { name: "bar", replacementSpan: { - fileName, - pos: fifthCaseMarker.position - 1, - end: fifthCaseMarker.position, + fileName: test5.fileName, + pos: test5.position - 1, + end: test5.position, }, }, }); @@ -45,9 +39,9 @@ verify.completions({ includes: { name: "qux", replacementSpan: { - fileName, - pos: sixthCaseMarker.position - 2, - end: sixthCaseMarker.position, + fileName: test6.fileName, + pos: test6.position - 2, + end: test6.position, }, }, });