From 8255f75d3f22726e8f8e8a2e7423648847160fc8 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Fri, 16 Dec 2022 10:28:55 +0800 Subject: [PATCH 01/19] Add test --- .../__snapshots__/jsfmt.spec.js.snap | 74 +++++++++++++++++++ .../js/indentifier/parentheses/jsfmt.spec.js | 14 ++++ .../format/js/indentifier/parentheses/let.js | 12 +++ 3 files changed, 100 insertions(+) create mode 100644 tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap create mode 100644 tests/format/js/indentifier/parentheses/jsfmt.spec.js create mode 100644 tests/format/js/indentifier/parentheses/let.js diff --git a/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap new file mode 100644 index 000000000000..fd2c1a81ddba --- /dev/null +++ b/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap @@ -0,0 +1,74 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`let.js - {"semi":false} format 1`] = ` +====================================options===================================== +parsers: ["babel", "typescript"] +printWidth: 80 +semi: false + | printWidth +=====================================input====================================== +let.a = 1; + +foo = []; +(let[a] = 1); + +foo = []; +(let[a].b.c.e = 1); + +foo[let[a]] = 1; +(let)[let[a]] = 1; + +foo = let[a]; + +=====================================output===================================== +let.a = 1 + +foo = [] +let[a] = 1 + +foo = [] +let[a].b.c.e = 1 + +foo[let[a]] = 1 +let[let[a]] = 1 + +foo = let[a] + +================================================================================ +`; + +exports[`let.js format 1`] = ` +====================================options===================================== +parsers: ["babel", "typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +let.a = 1; + +foo = []; +(let[a] = 1); + +foo = []; +(let[a].b.c.e = 1); + +foo[let[a]] = 1; +(let)[let[a]] = 1; + +foo = let[a]; + +=====================================output===================================== +let.a = 1; + +foo = []; +let[a] = 1; + +foo = []; +let[a].b.c.e = 1; + +foo[let[a]] = 1; +let[let[a]] = 1; + +foo = let[a]; + +================================================================================ +`; diff --git a/tests/format/js/indentifier/parentheses/jsfmt.spec.js b/tests/format/js/indentifier/parentheses/jsfmt.spec.js new file mode 100644 index 000000000000..9556557681db --- /dev/null +++ b/tests/format/js/indentifier/parentheses/jsfmt.spec.js @@ -0,0 +1,14 @@ +run_spec(__dirname, [ + "babel", + // "flow", + "typescript", +]); +run_spec( + __dirname, + [ + "babel", + // "flow", + "typescript", + ], + { semi: false } +); diff --git a/tests/format/js/indentifier/parentheses/let.js b/tests/format/js/indentifier/parentheses/let.js new file mode 100644 index 000000000000..6b1fe0abcf97 --- /dev/null +++ b/tests/format/js/indentifier/parentheses/let.js @@ -0,0 +1,12 @@ +let.a = 1; + +foo = []; +(let[a] = 1); + +foo = []; +(let[a].b.c.e = 1); + +foo[let[a]] = 1; +(let)[let[a]] = 1; + +foo = let[a]; From 93cc3b3b029b5377ff06eb3a5181784d44aa2028 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Fri, 16 Dec 2022 10:43:17 +0800 Subject: [PATCH 02/19] Fix --- src/language-js/needs-parens.js | 22 +++++++++++++++++++ .../__snapshots__/jsfmt.spec.js.snap | 12 +++++----- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/language-js/needs-parens.js b/src/language-js/needs-parens.js index 94d95febc44a..9a806e5cc067 100644 --- a/src/language-js/needs-parens.js +++ b/src/language-js/needs-parens.js @@ -77,6 +77,17 @@ function needsParens(path, options) { return true; } + // `let[a] = 1` + if ( + name === "object" && + node.name === "let" && + parent.type === "MemberExpression" && + parent.computed && + !parent.optional + ) { + return path.callParent(isAssignmentExpressionLeft); + } + return false; } @@ -963,4 +974,15 @@ function shouldWrapFunctionForExportDefault(path, options) { ); } +function isAssignmentExpressionLeft(path) { + const name = path.getName(); + const parent = path.getParentNode(); + + if (name === "object" && parent.type === "MemberExpression") { + return path.callParent(isAssignmentExpressionLeft); + } + + return name === "left" && parent.type === "AssignmentExpression"; +} + module.exports = needsParens; diff --git a/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap index fd2c1a81ddba..be79604f7cfe 100644 --- a/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap @@ -24,13 +24,13 @@ foo = let[a]; let.a = 1 foo = [] -let[a] = 1 +;(let)[a] = 1 foo = [] -let[a].b.c.e = 1 +;(let)[a].b.c.e = 1 foo[let[a]] = 1 -let[let[a]] = 1 +;(let)[let[a]] = 1 foo = let[a] @@ -60,13 +60,13 @@ foo = let[a]; let.a = 1; foo = []; -let[a] = 1; +(let)[a] = 1; foo = []; -let[a].b.c.e = 1; +(let)[a].b.c.e = 1; foo[let[a]] = 1; -let[let[a]] = 1; +(let)[let[a]] = 1; foo = let[a]; From 2eeacbaa8b0eb008a0df6e4b75b578d846803630 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Fri, 16 Dec 2022 10:45:01 +0800 Subject: [PATCH 03/19] More test --- src/language-js/needs-parens.js | 1 + .../__snapshots__/jsfmt.spec.js.snap | 24 +++++++++++++++++++ .../format/js/indentifier/parentheses/let.js | 6 +++++ 3 files changed, 31 insertions(+) diff --git a/src/language-js/needs-parens.js b/src/language-js/needs-parens.js index 9a806e5cc067..1a7a5ef46647 100644 --- a/src/language-js/needs-parens.js +++ b/src/language-js/needs-parens.js @@ -978,6 +978,7 @@ function isAssignmentExpressionLeft(path) { const name = path.getName(); const parent = path.getParentNode(); + // "OptionalMemberExpression" can't be here if (name === "object" && parent.type === "MemberExpression") { return path.callParent(isAssignmentExpressionLeft); } diff --git a/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap index be79604f7cfe..4b1de2a9d9fe 100644 --- a/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap @@ -15,9 +15,15 @@ foo = []; foo = []; (let[a].b.c.e = 1); +foo = []; foo[let[a]] = 1; + +foo = []; (let)[let[a]] = 1; +foo = []; +(let[a] ??= 1); + foo = let[a]; =====================================output===================================== @@ -29,9 +35,15 @@ foo = [] foo = [] ;(let)[a].b.c.e = 1 +foo = [] foo[let[a]] = 1 + +foo = [] ;(let)[let[a]] = 1 +foo = [] +;(let)[a] ??= 1 + foo = let[a] ================================================================================ @@ -51,9 +63,15 @@ foo = []; foo = []; (let[a].b.c.e = 1); +foo = []; foo[let[a]] = 1; + +foo = []; (let)[let[a]] = 1; +foo = []; +(let[a] ??= 1); + foo = let[a]; =====================================output===================================== @@ -65,9 +83,15 @@ foo = []; foo = []; (let)[a].b.c.e = 1; +foo = []; foo[let[a]] = 1; + +foo = []; (let)[let[a]] = 1; +foo = []; +(let)[a] ??= 1; + foo = let[a]; ================================================================================ diff --git a/tests/format/js/indentifier/parentheses/let.js b/tests/format/js/indentifier/parentheses/let.js index 6b1fe0abcf97..e17bf02d8703 100644 --- a/tests/format/js/indentifier/parentheses/let.js +++ b/tests/format/js/indentifier/parentheses/let.js @@ -6,7 +6,13 @@ foo = []; foo = []; (let[a].b.c.e = 1); +foo = []; foo[let[a]] = 1; + +foo = []; (let)[let[a]] = 1; +foo = []; +(let[a] ??= 1); + foo = let[a]; From aa4f3ac964de8b6972ed57ca06ca57cf37fb17cd Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Fri, 16 Dec 2022 10:49:28 +0800 Subject: [PATCH 04/19] More test --- .../__snapshots__/jsfmt.spec.js.snap | 36 +++++++++++++++++++ .../format/js/indentifier/parentheses/let.js | 9 +++++ 2 files changed, 45 insertions(+) diff --git a/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap index 4b1de2a9d9fe..758cdde6f78c 100644 --- a/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap @@ -26,6 +26,15 @@ foo = []; foo = let[a]; +foo = []; +let()[a] = 1; + +foo = []; +foo(let)[a] = 1; + +foo = []; +foo(let[a])[a] = 1; + =====================================output===================================== let.a = 1 @@ -46,6 +55,15 @@ foo = [] foo = let[a] +foo = [] +let()[a] = 1 + +foo = [] +foo(let)[a] = 1 + +foo = [] +foo(let[a])[a] = 1 + ================================================================================ `; @@ -74,6 +92,15 @@ foo = []; foo = let[a]; +foo = []; +let()[a] = 1; + +foo = []; +foo(let)[a] = 1; + +foo = []; +foo(let[a])[a] = 1; + =====================================output===================================== let.a = 1; @@ -94,5 +121,14 @@ foo = []; foo = let[a]; +foo = []; +let()[a] = 1; + +foo = []; +foo(let)[a] = 1; + +foo = []; +foo(let[a])[a] = 1; + ================================================================================ `; diff --git a/tests/format/js/indentifier/parentheses/let.js b/tests/format/js/indentifier/parentheses/let.js index e17bf02d8703..978534b8ac86 100644 --- a/tests/format/js/indentifier/parentheses/let.js +++ b/tests/format/js/indentifier/parentheses/let.js @@ -16,3 +16,12 @@ foo = []; (let[a] ??= 1); foo = let[a]; + +foo = []; +let()[a] = 1; + +foo = []; +foo(let)[a] = 1; + +foo = []; +foo(let[a])[a] = 1; From 7e053d42fed1bf2d92b797366566dca3375cbd6b Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Fri, 16 Dec 2022 10:51:07 +0800 Subject: [PATCH 05/19] Fix comment --- src/language-js/needs-parens.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/language-js/needs-parens.js b/src/language-js/needs-parens.js index 1a7a5ef46647..213bef347089 100644 --- a/src/language-js/needs-parens.js +++ b/src/language-js/needs-parens.js @@ -77,7 +77,7 @@ function needsParens(path, options) { return true; } - // `let[a] = 1` + // `(let)[a] = 1` if ( name === "object" && node.name === "let" && From 0b14faaac8a75d64c0b0e6b320d126107190d86c Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Fri, 16 Dec 2022 10:52:27 +0800 Subject: [PATCH 06/19] Rename file --- .../indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap | 4 ++-- .../indentifier/parentheses/{let.js => let-in-assignment.js} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename tests/format/js/indentifier/parentheses/{let.js => let-in-assignment.js} (100%) diff --git a/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap index 758cdde6f78c..376f62de9c7e 100644 --- a/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`let.js - {"semi":false} format 1`] = ` +exports[`let-in-assignment.js - {"semi":false} format 1`] = ` ====================================options===================================== parsers: ["babel", "typescript"] printWidth: 80 @@ -67,7 +67,7 @@ foo(let[a])[a] = 1 ================================================================================ `; -exports[`let.js format 1`] = ` +exports[`let-in-assignment.js format 1`] = ` ====================================options===================================== parsers: ["babel", "typescript"] printWidth: 80 diff --git a/tests/format/js/indentifier/parentheses/let.js b/tests/format/js/indentifier/parentheses/let-in-assignment.js similarity index 100% rename from tests/format/js/indentifier/parentheses/let.js rename to tests/format/js/indentifier/parentheses/let-in-assignment.js From df3d0fe0d1d1e6c7f2e8d20aa95b5a377bdf3bbc Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Fri, 16 Dec 2022 10:56:50 +0800 Subject: [PATCH 07/19] Add changelog --- changelog_unreleased/javascript/14000.md | 21 ++++++++++++++++ .../__snapshots__/jsfmt.spec.js.snap | 24 +++++++++++++++++++ .../parentheses/let-in-assignment.js | 6 +++++ 3 files changed, 51 insertions(+) create mode 100644 changelog_unreleased/javascript/14000.md diff --git a/changelog_unreleased/javascript/14000.md b/changelog_unreleased/javascript/14000.md new file mode 100644 index 000000000000..e853652bbf56 --- /dev/null +++ b/changelog_unreleased/javascript/14000.md @@ -0,0 +1,21 @@ +#### Fix missing parentheses when assigning properties to `let` (#14000 by @fisker) + + + + +```jsx +// Input +(let[0] = 2); + +// Prettier stable +let[0] = 2; + +// Prettier stable (second format) +SyntaxError: Unexpected token (1:5) +> 1 | let[0] = 2; + | ^ + 2 | + +// Prettier main +(let)[0] = 2; +``` diff --git a/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap index 376f62de9c7e..0c97e9ff93a1 100644 --- a/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap @@ -35,6 +35,12 @@ foo(let)[a] = 1; foo = []; foo(let[a])[a] = 1; +foo = []; +(let[0] = 1); + +foo = []; +(let["a"] = 1); + =====================================output===================================== let.a = 1 @@ -64,6 +70,12 @@ foo(let)[a] = 1 foo = [] foo(let[a])[a] = 1 +foo = [] +;(let)[0] = 1 + +foo = [] +;(let)["a"] = 1 + ================================================================================ `; @@ -101,6 +113,12 @@ foo(let)[a] = 1; foo = []; foo(let[a])[a] = 1; +foo = []; +(let[0] = 1); + +foo = []; +(let["a"] = 1); + =====================================output===================================== let.a = 1; @@ -130,5 +148,11 @@ foo(let)[a] = 1; foo = []; foo(let[a])[a] = 1; +foo = []; +(let)[0] = 1; + +foo = []; +(let)["a"] = 1; + ================================================================================ `; diff --git a/tests/format/js/indentifier/parentheses/let-in-assignment.js b/tests/format/js/indentifier/parentheses/let-in-assignment.js index 978534b8ac86..54bd53f45235 100644 --- a/tests/format/js/indentifier/parentheses/let-in-assignment.js +++ b/tests/format/js/indentifier/parentheses/let-in-assignment.js @@ -25,3 +25,9 @@ foo(let)[a] = 1; foo = []; foo(let[a])[a] = 1; + +foo = []; +(let[0] = 1); + +foo = []; +(let["a"] = 1); From dff50c43fcb862fa5c0082a4e6027e165223b74c Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Fri, 16 Dec 2022 11:01:21 +0800 Subject: [PATCH 08/19] More tests --- .../__snapshots__/jsfmt.spec.js.snap | 56 ++++++------------- .../parentheses/let-in-assignment.js | 14 ++--- .../__snapshots__/jsfmt.spec.js.snap | 54 ++++++++++++++++++ .../misc/errors/js/assignment/jsfmt.spec.js | 10 +++- 4 files changed, 83 insertions(+), 51 deletions(-) diff --git a/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap index 0c97e9ff93a1..44799df8679f 100644 --- a/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap @@ -9,73 +9,61 @@ semi: false =====================================input====================================== let.a = 1; -foo = []; (let[a] = 1); -foo = []; (let[a].b.c.e = 1); -foo = []; foo[let[a]] = 1; -foo = []; (let)[let[a]] = 1; -foo = []; (let[a] ??= 1); foo = let[a]; -foo = []; let()[a] = 1; -foo = []; foo(let)[a] = 1; -foo = []; foo(let[a])[a] = 1; -foo = []; (let[0] = 1); -foo = []; (let["a"] = 1); +let = 1; + +var let = 1; + =====================================output===================================== let.a = 1 -foo = [] ;(let)[a] = 1 -foo = [] ;(let)[a].b.c.e = 1 -foo = [] foo[let[a]] = 1 -foo = [] ;(let)[let[a]] = 1 -foo = [] ;(let)[a] ??= 1 foo = let[a] -foo = [] let()[a] = 1 -foo = [] foo(let)[a] = 1 -foo = [] foo(let[a])[a] = 1 -foo = [] ;(let)[0] = 1 -foo = [] ;(let)["a"] = 1 +let = 1 + +var let = 1 + ================================================================================ `; @@ -87,72 +75,60 @@ printWidth: 80 =====================================input====================================== let.a = 1; -foo = []; (let[a] = 1); -foo = []; (let[a].b.c.e = 1); -foo = []; foo[let[a]] = 1; -foo = []; (let)[let[a]] = 1; -foo = []; (let[a] ??= 1); foo = let[a]; -foo = []; let()[a] = 1; -foo = []; foo(let)[a] = 1; -foo = []; foo(let[a])[a] = 1; -foo = []; (let[0] = 1); -foo = []; (let["a"] = 1); +let = 1; + +var let = 1; + =====================================output===================================== let.a = 1; -foo = []; (let)[a] = 1; -foo = []; (let)[a].b.c.e = 1; -foo = []; foo[let[a]] = 1; -foo = []; (let)[let[a]] = 1; -foo = []; (let)[a] ??= 1; foo = let[a]; -foo = []; let()[a] = 1; -foo = []; foo(let)[a] = 1; -foo = []; foo(let[a])[a] = 1; -foo = []; (let)[0] = 1; -foo = []; (let)["a"] = 1; +let = 1; + +var let = 1; + ================================================================================ `; diff --git a/tests/format/js/indentifier/parentheses/let-in-assignment.js b/tests/format/js/indentifier/parentheses/let-in-assignment.js index 54bd53f45235..c9955e98b7c8 100644 --- a/tests/format/js/indentifier/parentheses/let-in-assignment.js +++ b/tests/format/js/indentifier/parentheses/let-in-assignment.js @@ -1,33 +1,27 @@ let.a = 1; -foo = []; (let[a] = 1); -foo = []; (let[a].b.c.e = 1); -foo = []; foo[let[a]] = 1; -foo = []; (let)[let[a]] = 1; -foo = []; (let[a] ??= 1); foo = let[a]; -foo = []; let()[a] = 1; -foo = []; foo(let)[a] = 1; -foo = []; foo(let[a])[a] = 1; -foo = []; (let[0] = 1); -foo = []; (let["a"] = 1); + +let = 1; + +var let = 1; diff --git a/tests/format/misc/errors/js/assignment/__snapshots__/jsfmt.spec.js.snap b/tests/format/misc/errors/js/assignment/__snapshots__/jsfmt.spec.js.snap index 1ece57b5bafd..7797ccc5dd89 100644 --- a/tests/format/misc/errors/js/assignment/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/misc/errors/js/assignment/__snapshots__/jsfmt.spec.js.snap @@ -6,26 +6,80 @@ exports[`snippet: #0 [acorn] format 1`] = ` | ^" `; +exports[`snippet: #0 [acorn] format 2`] = ` +"The keyword 'let' is reserved (1:1) +> 1 | let?.()[a] =1 + | ^" +`; + exports[`snippet: #0 [babel] format 1`] = ` "Invalid parenthesized assignment pattern. (1:1) > 1 | ({}) = x; | ^" `; +exports[`snippet: #0 [babel] format 2`] = ` +"Invalid left-hand side in assignment expression. (1:1) +> 1 | let?.()[a] =1 + | ^" +`; + exports[`snippet: #0 [babel-ts] format 1`] = ` "Invalid parenthesized assignment pattern. (1:1) > 1 | ({}) = x; | ^" `; +exports[`snippet: #0 [babel-ts] format 2`] = ` +"Invalid left-hand side in assignment expression. (1:1) +> 1 | let?.()[a] =1 + | ^" +`; + exports[`snippet: #0 [espree] format 1`] = ` "Assigning to rvalue (1:1) > 1 | ({}) = x; | ^" `; +exports[`snippet: #0 [espree] format 2`] = ` +"The keyword 'let' is reserved (1:1) +> 1 | let?.()[a] =1 + | ^" +`; + exports[`snippet: #0 [meriyah] format 1`] = ` "Invalid left-hand side in assignment (1:6) > 1 | ({}) = x; | ^" `; + +exports[`snippet: #1 [acorn] format 1`] = ` +"The keyword 'let' is reserved (1:1) +> 1 | let?.[a] = 1 + | ^" +`; + +exports[`snippet: #1 [babel] format 1`] = ` +"Invalid left-hand side in assignment expression. (1:1) +> 1 | let?.[a] = 1 + | ^" +`; + +exports[`snippet: #1 [babel-ts] format 1`] = ` +"Invalid left-hand side in assignment expression. (1:1) +> 1 | let?.[a] = 1 + | ^" +`; + +exports[`snippet: #1 [espree] format 1`] = ` +"The keyword 'let' is reserved (1:1) +> 1 | let?.[a] = 1 + | ^" +`; + +exports[`snippet: #1 [meriyah] format 1`] = ` +"\`let\` declaration not allowed here and \`let\` cannot be a regular var name in strict mode (1:5) +> 1 | let?.[a] = 1 + | ^" +`; diff --git a/tests/format/misc/errors/js/assignment/jsfmt.spec.js b/tests/format/misc/errors/js/assignment/jsfmt.spec.js index b83f8d1c7169..da077f67cc94 100644 --- a/tests/format/misc/errors/js/assignment/jsfmt.spec.js +++ b/tests/format/misc/errors/js/assignment/jsfmt.spec.js @@ -1,7 +1,15 @@ run_spec( { dirname: __dirname, - snippets: ["({}) = x;"], + snippets: ["({}) = x;", "let?.[a] = 1"], }, ["babel", "babel-ts", "acorn", "espree", "meriyah"] ); + +run_spec( + { + dirname: __dirname, + snippets: ["let?.()[a] =1"], + }, + ["babel", "babel-ts", "acorn", "espree"] +); From 374746b47f680a8b854d708124c4250f97536327 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Fri, 16 Dec 2022 11:02:19 +0800 Subject: [PATCH 09/19] Update changelog --- changelog_unreleased/javascript/14000.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/changelog_unreleased/javascript/14000.md b/changelog_unreleased/javascript/14000.md index e853652bbf56..779e0cfed006 100644 --- a/changelog_unreleased/javascript/14000.md +++ b/changelog_unreleased/javascript/14000.md @@ -1,6 +1,4 @@ -#### Fix missing parentheses when assigning properties to `let` (#14000 by @fisker) - - +#### Fix missing parentheses when assigning to property of variable named `let` (#14000 by @fisker) ```jsx From 51a5308cf8eaf3db0f7f1f93e15792a2b4e563ff Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Fri, 16 Dec 2022 11:18:20 +0800 Subject: [PATCH 10/19] Mark unstable --- tests/config/format-test.js | 4 ++++ .../parentheses/__snapshots__/jsfmt.spec.js.snap | 0 .../js/{indentifier => identifier}/parentheses/jsfmt.spec.js | 0 .../parentheses/let-in-assignment.js | 0 4 files changed, 4 insertions(+) rename tests/format/js/{indentifier => identifier}/parentheses/__snapshots__/jsfmt.spec.js.snap (100%) rename tests/format/js/{indentifier => identifier}/parentheses/jsfmt.spec.js (100%) rename tests/format/js/{indentifier => identifier}/parentheses/let-in-assignment.js (100%) diff --git a/tests/config/format-test.js b/tests/config/format-test.js index 3574fddf1e40..c4e6710b3953 100644 --- a/tests/config/format-test.js +++ b/tests/config/format-test.js @@ -41,6 +41,10 @@ const unstableTests = new Map( "js/comments/html-like/comment.js", "js/for/continue-and-break-comment-without-blocks.js", "typescript/satisfies-operators/comments-unstable.ts", + [ + "js/identifier/parentheses/let-in-assignment.js", + (options) => options.semi === false, + ], ].map((fixture) => { const [file, isUnstable = () => true] = Array.isArray(fixture) ? fixture diff --git a/tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/identifier/parentheses/__snapshots__/jsfmt.spec.js.snap similarity index 100% rename from tests/format/js/indentifier/parentheses/__snapshots__/jsfmt.spec.js.snap rename to tests/format/js/identifier/parentheses/__snapshots__/jsfmt.spec.js.snap diff --git a/tests/format/js/indentifier/parentheses/jsfmt.spec.js b/tests/format/js/identifier/parentheses/jsfmt.spec.js similarity index 100% rename from tests/format/js/indentifier/parentheses/jsfmt.spec.js rename to tests/format/js/identifier/parentheses/jsfmt.spec.js diff --git a/tests/format/js/indentifier/parentheses/let-in-assignment.js b/tests/format/js/identifier/parentheses/let-in-assignment.js similarity index 100% rename from tests/format/js/indentifier/parentheses/let-in-assignment.js rename to tests/format/js/identifier/parentheses/let-in-assignment.js From 6e7ba19f85c907bdbc19fbf93a0f0925ada69810 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Fri, 16 Dec 2022 12:16:04 +0800 Subject: [PATCH 11/19] more tests --- .../__snapshots__/jsfmt.spec.js.snap | 24 +++++++++++++++++++ .../parentheses/let-in-assignment.js | 6 +++++ 2 files changed, 30 insertions(+) diff --git a/tests/format/js/identifier/parentheses/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/identifier/parentheses/__snapshots__/jsfmt.spec.js.snap index 44799df8679f..10f9e020740f 100644 --- a/tests/format/js/identifier/parentheses/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/js/identifier/parentheses/__snapshots__/jsfmt.spec.js.snap @@ -9,6 +9,8 @@ semi: false =====================================input====================================== let.a = 1; +let.a[0] = 1; + (let[a] = 1); (let[a].b.c.e = 1); @@ -35,9 +37,15 @@ let = 1; var let = 1; +[let[a]] = 1; + +({a: let[a]} = 1) + =====================================output===================================== let.a = 1 +let.a[0] = 1 + ;(let)[a] = 1 ;(let)[a].b.c.e = 1 @@ -64,6 +72,10 @@ let = 1 var let = 1 +;[let[a]] = 1 + +;({ a: let[a] } = 1) + ================================================================================ `; @@ -75,6 +87,8 @@ printWidth: 80 =====================================input====================================== let.a = 1; +let.a[0] = 1; + (let[a] = 1); (let[a].b.c.e = 1); @@ -101,9 +115,15 @@ let = 1; var let = 1; +[let[a]] = 1; + +({a: let[a]} = 1) + =====================================output===================================== let.a = 1; +let.a[0] = 1; + (let)[a] = 1; (let)[a].b.c.e = 1; @@ -130,5 +150,9 @@ let = 1; var let = 1; +[let[a]] = 1; + +({ a: let[a] } = 1); + ================================================================================ `; diff --git a/tests/format/js/identifier/parentheses/let-in-assignment.js b/tests/format/js/identifier/parentheses/let-in-assignment.js index c9955e98b7c8..f3e12529d653 100644 --- a/tests/format/js/identifier/parentheses/let-in-assignment.js +++ b/tests/format/js/identifier/parentheses/let-in-assignment.js @@ -1,5 +1,7 @@ let.a = 1; +let.a[0] = 1; + (let[a] = 1); (let[a].b.c.e = 1); @@ -25,3 +27,7 @@ foo(let[a])[a] = 1; let = 1; var let = 1; + +[let[a]] = 1; + +({a: let[a]} = 1) From 1fb2914061477c313ec75395c21e3def6bf4ece6 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Fri, 16 Dec 2022 13:46:33 +0800 Subject: [PATCH 12/19] More test --- .../__snapshots__/jsfmt.spec.js.snap | 279 +++++++++++++++++- .../format/js/identifier/parentheses/const.js | 1 + .../parentheses/let-in-assignment.js | 60 +++- .../__snapshots__/jsfmt.spec.js.snap | 28 +- .../misc/errors/js/assignment/jsfmt.spec.js | 11 + 5 files changed, 374 insertions(+), 5 deletions(-) create mode 100644 tests/format/js/identifier/parentheses/const.js diff --git a/tests/format/js/identifier/parentheses/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/identifier/parentheses/__snapshots__/jsfmt.spec.js.snap index 10f9e020740f..d297906faae2 100644 --- a/tests/format/js/identifier/parentheses/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/js/identifier/parentheses/__snapshots__/jsfmt.spec.js.snap @@ -1,5 +1,34 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`const.js - {"semi":false} format 1`] = ` +====================================options===================================== +parsers: ["babel", "typescript"] +printWidth: 80 +semi: false + | printWidth +=====================================input====================================== +const [a = ((let)[0] = 1)] = 2; + +=====================================output===================================== +const [a = ((let)[0] = 1)] = 2 + +================================================================================ +`; + +exports[`const.js format 1`] = ` +====================================options===================================== +parsers: ["babel", "typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +const [a = ((let)[0] = 1)] = 2; + +=====================================output===================================== +const [a = ((let)[0] = 1)] = 2; + +================================================================================ +`; + exports[`let-in-assignment.js - {"semi":false} format 1`] = ` ====================================options===================================== parsers: ["babel", "typescript"] @@ -39,7 +68,65 @@ var let = 1; [let[a]] = 1; -({a: let[a]} = 1) +({a: let[a]} = 1); + +alert(let[0] = 1); + +(let[0] = 1) || 2; + +((let[0] = 1), 2); + +((let[0] = 1) ? a : b); + +if (let[0] = 1); + +while (let[0] = 1); + +do{} while (let[0] = 1); + +var a = (let[0] = 1); + +(let[0] = 1) instanceof a; + +void (let[0] = 1); + +(let[0] = 1)(); + +new (let[0] = 1)(); + +((let)[0] = 1)\`\`; + +((let)[0] = 1).toString; + +((let)[0] = 1)?.toString; + +[...(let[0] = 1)]; + +foo = () => (let[0] = 1); + +function * foo() {yield (let[0] = 1)} + +async function foo() {await (let[0] = 1)} + +function foo() {return (let[0] = 1)} + +while (true) (let[0] = 1); + +throw (let[0] = 1); + +({foo: (let[0] = 1)}); + +[(let[0] = 1)]; + +for ((let[0] = 1);;); + +switch (let[0] = 1) {} + +switch (foo) { + case let[0] = 1: +} + +with (let[0] = 1); =====================================output===================================== let.a = 1 @@ -76,6 +163,71 @@ var let = 1 ;({ a: let[a] } = 1) +alert(((let)[0] = 1)) + +;((let)[0] = 1) || 2 + +;((let)[0] = 1), 2 + +;((let)[0] = 1) ? a : b + +if (((let)[0] = 1)); + +while (((let)[0] = 1)); + +do {} while (((let)[0] = 1)) + +var a = ((let)[0] = 1) + +;((let)[0] = 1) instanceof a + +void ((let)[0] = 1) + +;((let)[0] = 1)() + +new ((let)[0] = 1)() + +;((let)[0] = 1)\`\` + +;((let)[0] = 1).toString + +;((let)[0] = 1)?.toString + +;[...((let)[0] = 1)] + +foo = () => ((let)[0] = 1) + +function* foo() { + yield ((let)[0] = 1) +} + +async function foo() { + await ((let)[0] = 1) +} + +function foo() { + return ((let)[0] = 1) +} + +while (true) (let)[0] = 1 + +throw ((let)[0] = 1) + +;({ foo: ((let)[0] = 1) }) + +;[((let)[0] = 1)] + +for ((let)[0] = 1; ; ); + +switch (((let)[0] = 1)) { +} + +switch (foo) { + case ((let)[0] = 1): +} + +with (((let)[0] = 1)); + ================================================================================ `; @@ -117,7 +269,65 @@ var let = 1; [let[a]] = 1; -({a: let[a]} = 1) +({a: let[a]} = 1); + +alert(let[0] = 1); + +(let[0] = 1) || 2; + +((let[0] = 1), 2); + +((let[0] = 1) ? a : b); + +if (let[0] = 1); + +while (let[0] = 1); + +do{} while (let[0] = 1); + +var a = (let[0] = 1); + +(let[0] = 1) instanceof a; + +void (let[0] = 1); + +(let[0] = 1)(); + +new (let[0] = 1)(); + +((let)[0] = 1)\`\`; + +((let)[0] = 1).toString; + +((let)[0] = 1)?.toString; + +[...(let[0] = 1)]; + +foo = () => (let[0] = 1); + +function * foo() {yield (let[0] = 1)} + +async function foo() {await (let[0] = 1)} + +function foo() {return (let[0] = 1)} + +while (true) (let[0] = 1); + +throw (let[0] = 1); + +({foo: (let[0] = 1)}); + +[(let[0] = 1)]; + +for ((let[0] = 1);;); + +switch (let[0] = 1) {} + +switch (foo) { + case let[0] = 1: +} + +with (let[0] = 1); =====================================output===================================== let.a = 1; @@ -154,5 +364,70 @@ var let = 1; ({ a: let[a] } = 1); +alert(((let)[0] = 1)); + +((let)[0] = 1) || 2; + +((let)[0] = 1), 2; + +((let)[0] = 1) ? a : b; + +if (((let)[0] = 1)); + +while (((let)[0] = 1)); + +do {} while (((let)[0] = 1)); + +var a = ((let)[0] = 1); + +((let)[0] = 1) instanceof a; + +void ((let)[0] = 1); + +((let)[0] = 1)(); + +new ((let)[0] = 1)(); + +((let)[0] = 1)\`\`; + +((let)[0] = 1).toString; + +((let)[0] = 1)?.toString; + +[...((let)[0] = 1)]; + +foo = () => ((let)[0] = 1); + +function* foo() { + yield ((let)[0] = 1); +} + +async function foo() { + await ((let)[0] = 1); +} + +function foo() { + return ((let)[0] = 1); +} + +while (true) (let)[0] = 1; + +throw ((let)[0] = 1); + +({ foo: ((let)[0] = 1) }); + +[((let)[0] = 1)]; + +for ((let)[0] = 1; ; ); + +switch (((let)[0] = 1)) { +} + +switch (foo) { + case ((let)[0] = 1): +} + +with (((let)[0] = 1)); + ================================================================================ `; diff --git a/tests/format/js/identifier/parentheses/const.js b/tests/format/js/identifier/parentheses/const.js new file mode 100644 index 000000000000..8fa111711c35 --- /dev/null +++ b/tests/format/js/identifier/parentheses/const.js @@ -0,0 +1 @@ +const [a = ((let)[0] = 1)] = 2; diff --git a/tests/format/js/identifier/parentheses/let-in-assignment.js b/tests/format/js/identifier/parentheses/let-in-assignment.js index f3e12529d653..ff578ad3c8ba 100644 --- a/tests/format/js/identifier/parentheses/let-in-assignment.js +++ b/tests/format/js/identifier/parentheses/let-in-assignment.js @@ -30,4 +30,62 @@ var let = 1; [let[a]] = 1; -({a: let[a]} = 1) +({a: let[a]} = 1); + +alert(let[0] = 1); + +(let[0] = 1) || 2; + +((let[0] = 1), 2); + +((let[0] = 1) ? a : b); + +if (let[0] = 1); + +while (let[0] = 1); + +do{} while (let[0] = 1); + +var a = (let[0] = 1); + +(let[0] = 1) instanceof a; + +void (let[0] = 1); + +(let[0] = 1)(); + +new (let[0] = 1)(); + +((let)[0] = 1)``; + +((let)[0] = 1).toString; + +((let)[0] = 1)?.toString; + +[...(let[0] = 1)]; + +foo = () => (let[0] = 1); + +function * foo() {yield (let[0] = 1)} + +async function foo() {await (let[0] = 1)} + +function foo() {return (let[0] = 1)} + +while (true) (let[0] = 1); + +throw (let[0] = 1); + +({foo: (let[0] = 1)}); + +[(let[0] = 1)]; + +for ((let[0] = 1);;); + +switch (let[0] = 1) {} + +switch (foo) { + case let[0] = 1: +} + +with (let[0] = 1); diff --git a/tests/format/misc/errors/js/assignment/__snapshots__/jsfmt.spec.js.snap b/tests/format/misc/errors/js/assignment/__snapshots__/jsfmt.spec.js.snap index 7797ccc5dd89..a0c3d03e3851 100644 --- a/tests/format/misc/errors/js/assignment/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/misc/errors/js/assignment/__snapshots__/jsfmt.spec.js.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`snippet: #0 [acorn] format 1`] = ` -"Assigning to rvalue (1:1) +"Parenthesized pattern (1:1) > 1 | ({}) = x; | ^" `; @@ -37,7 +37,7 @@ exports[`snippet: #0 [babel-ts] format 2`] = ` `; exports[`snippet: #0 [espree] format 1`] = ` -"Assigning to rvalue (1:1) +"Parenthesized pattern (1:1) > 1 | ({}) = x; | ^" `; @@ -48,12 +48,24 @@ exports[`snippet: #0 [espree] format 2`] = ` | ^" `; +exports[`snippet: #0 [espree] format 3`] = ` +"The keyword 'let' is reserved (1:18) +> 1 | export default ((let)[0] = 1); + | ^" +`; + exports[`snippet: #0 [meriyah] format 1`] = ` "Invalid left-hand side in assignment (1:6) > 1 | ({}) = x; | ^" `; +exports[`snippet: #0 [meriyah] format 2`] = ` +"The identifier 'let' must not be in expression position in strict mode (1:21) +> 1 | export default ((let)[0] = 1); + | ^" +`; + exports[`snippet: #1 [acorn] format 1`] = ` "The keyword 'let' is reserved (1:1) > 1 | let?.[a] = 1 @@ -78,8 +90,20 @@ exports[`snippet: #1 [espree] format 1`] = ` | ^" `; +exports[`snippet: #1 [espree] format 2`] = ` +"The keyword 'let' is reserved (1:21) +> 1 | class Foo extends ((let)[0] = 1) {} + | ^" +`; + exports[`snippet: #1 [meriyah] format 1`] = ` "\`let\` declaration not allowed here and \`let\` cannot be a regular var name in strict mode (1:5) > 1 | let?.[a] = 1 | ^" `; + +exports[`snippet: #1 [meriyah] format 2`] = ` +"The identifier 'let' must not be in expression position in strict mode (1:24) +> 1 | class Foo extends ((let)[0] = 1) {} + | ^" +`; diff --git a/tests/format/misc/errors/js/assignment/jsfmt.spec.js b/tests/format/misc/errors/js/assignment/jsfmt.spec.js index da077f67cc94..62ab4b67f616 100644 --- a/tests/format/misc/errors/js/assignment/jsfmt.spec.js +++ b/tests/format/misc/errors/js/assignment/jsfmt.spec.js @@ -13,3 +13,14 @@ run_spec( }, ["babel", "babel-ts", "acorn", "espree"] ); + +run_spec( + { + dirname: __dirname, + snippets: [ + "export default ((let)[0] = 1);", + "class Foo extends ((let)[0] = 1) {}", + ], + }, + ["espree", "meriyah"] +); From e2d377adc98efc1e55b748db9c4a31523157fa7e Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Fri, 16 Dec 2022 13:57:15 +0800 Subject: [PATCH 13/19] Update acorn & espree --- package.json | 4 +-- .../__snapshots__/jsfmt.spec.js.snap | 34 +++++++++++-------- .../misc/errors/js/assignment/jsfmt.spec.js | 13 ++++--- yarn.lock | 24 ++++++++++--- 4 files changed, 50 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index d87d6b49792f..5c6e20827e5d 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "@glimmer/syntax": "0.84.2", "@iarna/toml": "2.2.5", "@typescript-eslint/typescript-estree": "5.45.0", - "acorn": "8.8.0", + "acorn": "8.8.1", "acorn-jsx": "5.3.2", "angular-estree-parser": "2.5.1", "angular-html-parser": "1.8.0", @@ -44,7 +44,7 @@ "editorconfig": "0.15.3", "editorconfig-to-prettier": "0.2.0", "escape-string-regexp": "5.0.0", - "espree": "9.4.0", + "espree": "9.4.1", "esutils": "2.0.3", "fast-glob": "3.2.11", "fast-json-stable-stringify": "2.1.0", diff --git a/tests/format/misc/errors/js/assignment/__snapshots__/jsfmt.spec.js.snap b/tests/format/misc/errors/js/assignment/__snapshots__/jsfmt.spec.js.snap index a0c3d03e3851..f4b45b707e0f 100644 --- a/tests/format/misc/errors/js/assignment/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/misc/errors/js/assignment/__snapshots__/jsfmt.spec.js.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`snippet: #0 [acorn] format 1`] = ` -"Parenthesized pattern (1:1) +"Assigning to rvalue (1:1) > 1 | ({}) = x; | ^" `; @@ -12,6 +12,12 @@ exports[`snippet: #0 [acorn] format 2`] = ` | ^" `; +exports[`snippet: #0 [acorn] format 3`] = ` +"The keyword 'let' is reserved (1:21) +> 1 | class Foo extends ((let)[0] = 1) {} + | ^" +`; + exports[`snippet: #0 [babel] format 1`] = ` "Invalid parenthesized assignment pattern. (1:1) > 1 | ({}) = x; @@ -37,7 +43,7 @@ exports[`snippet: #0 [babel-ts] format 2`] = ` `; exports[`snippet: #0 [espree] format 1`] = ` -"Parenthesized pattern (1:1) +"Assigning to rvalue (1:1) > 1 | ({}) = x; | ^" `; @@ -49,6 +55,12 @@ exports[`snippet: #0 [espree] format 2`] = ` `; exports[`snippet: #0 [espree] format 3`] = ` +"The keyword 'let' is reserved (1:21) +> 1 | class Foo extends ((let)[0] = 1) {} + | ^" +`; + +exports[`snippet: #0 [espree] format 4`] = ` "The keyword 'let' is reserved (1:18) > 1 | export default ((let)[0] = 1); | ^" @@ -61,6 +73,12 @@ exports[`snippet: #0 [meriyah] format 1`] = ` `; exports[`snippet: #0 [meriyah] format 2`] = ` +"The identifier 'let' must not be in expression position in strict mode (1:24) +> 1 | class Foo extends ((let)[0] = 1) {} + | ^" +`; + +exports[`snippet: #0 [meriyah] format 3`] = ` "The identifier 'let' must not be in expression position in strict mode (1:21) > 1 | export default ((let)[0] = 1); | ^" @@ -90,20 +108,8 @@ exports[`snippet: #1 [espree] format 1`] = ` | ^" `; -exports[`snippet: #1 [espree] format 2`] = ` -"The keyword 'let' is reserved (1:21) -> 1 | class Foo extends ((let)[0] = 1) {} - | ^" -`; - exports[`snippet: #1 [meriyah] format 1`] = ` "\`let\` declaration not allowed here and \`let\` cannot be a regular var name in strict mode (1:5) > 1 | let?.[a] = 1 | ^" `; - -exports[`snippet: #1 [meriyah] format 2`] = ` -"The identifier 'let' must not be in expression position in strict mode (1:24) -> 1 | class Foo extends ((let)[0] = 1) {} - | ^" -`; diff --git a/tests/format/misc/errors/js/assignment/jsfmt.spec.js b/tests/format/misc/errors/js/assignment/jsfmt.spec.js index 62ab4b67f616..29f1195c4852 100644 --- a/tests/format/misc/errors/js/assignment/jsfmt.spec.js +++ b/tests/format/misc/errors/js/assignment/jsfmt.spec.js @@ -17,10 +17,15 @@ run_spec( run_spec( { dirname: __dirname, - snippets: [ - "export default ((let)[0] = 1);", - "class Foo extends ((let)[0] = 1) {}", - ], + snippets: ["class Foo extends ((let)[0] = 1) {}"], + }, + ["acorn", "espree", "meriyah"] +); + +run_spec( + { + dirname: __dirname, + snippets: ["export default ((let)[0] = 1);"], }, ["espree", "meriyah"] ); diff --git a/yarn.lock b/yarn.lock index 172f1f94fa58..6da260364cfe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1811,16 +1811,21 @@ acorn-walk@^7.1.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== -acorn@8.8.0, acorn@^8.2.4, acorn@^8.8.0: - version "8.8.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" - integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== +acorn@8.8.1: + version "8.8.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73" + integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== acorn@^7.1.1: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== +acorn@^8.2.4, acorn@^8.8.0: + version "8.8.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" + integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== + agent-base@6: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -3176,7 +3181,16 @@ esm-utils@3.0.0: dependencies: url-or-path "2.1.0" -espree@9.4.0, espree@^9.4.0: +espree@9.4.1: + version "9.4.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.1.tgz#51d6092615567a2c2cff7833445e37c28c0065bd" + integrity sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg== + dependencies: + acorn "^8.8.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.3.0" + +espree@^9.4.0: version "9.4.0" resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.0.tgz#cd4bc3d6e9336c433265fc0aa016fc1aaf182f8a" integrity sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw== From 74d873c293db9c605babfe0fcce7abfc5c331c73 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Fri, 16 Dec 2022 13:59:20 +0800 Subject: [PATCH 14/19] Fix lock --- yarn.lock | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6da260364cfe..c9930b25eae4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1811,7 +1811,7 @@ acorn-walk@^7.1.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== -acorn@8.8.1: +acorn@8.8.1, acorn@^8.2.4, acorn@^8.8.0: version "8.8.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73" integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== @@ -1821,11 +1821,6 @@ acorn@^7.1.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.2.4, acorn@^8.8.0: - version "8.8.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" - integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== - agent-base@6: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" From b5bba84e594f0fbfb81753a6c2a7e48f577de8fe Mon Sep 17 00:00:00 2001 From: Georgii Dolzhykov Date: Tue, 20 Dec 2022 15:06:25 +0200 Subject: [PATCH 15/19] Tweak startsWithNoLookaheadToken --- changelog_unreleased/javascript/14000.md | 2 +- src/language-js/needs-parens.js | 33 +++--- src/language-js/print/function.js | 5 +- src/language-js/utils/index.js | 73 ++++-------- .../__snapshots__/jsfmt.spec.js.snap | 104 +++++++++++------- .../parentheses/let-in-assignment.js | 6 + 6 files changed, 117 insertions(+), 106 deletions(-) diff --git a/changelog_unreleased/javascript/14000.md b/changelog_unreleased/javascript/14000.md index 779e0cfed006..a8388fda0f1a 100644 --- a/changelog_unreleased/javascript/14000.md +++ b/changelog_unreleased/javascript/14000.md @@ -1,4 +1,4 @@ -#### Fix missing parentheses when assigning to property of variable named `let` (#14000 by @fisker) +#### Fix missing parentheses when an expression statement starts with `let[` (#14000 by @fisker, @thorn0) ```jsx diff --git a/src/language-js/needs-parens.js b/src/language-js/needs-parens.js index 213bef347089..b56857ef5bf3 100644 --- a/src/language-js/needs-parens.js +++ b/src/language-js/needs-parens.js @@ -85,7 +85,18 @@ function needsParens(path, options) { parent.computed && !parent.optional ) { - return path.callParent(isAssignmentExpressionLeft); + const expressionStatement = path.findAncestor( + (node) => node.type === "ExpressionStatement" + ); + if ( + expressionStatement && + startsWithNoLookaheadToken( + expressionStatement.expression, + (leftmostNode) => leftmostNode === node + ) + ) { + return true; + } } return false; @@ -168,7 +179,11 @@ function needsParens(path, options) { if ( startsWithNoLookaheadToken( node, - /* forbidFunctionClassAndDoExpr */ true + (node) => + node.type === "ObjectExpression" || + node.type === "FunctionExpression" || + node.type === "ClassExpression" || + node.type === "DoExpression" ) ) { return true; @@ -181,7 +196,7 @@ function needsParens(path, options) { node.type !== "SequenceExpression" && // these have parens added anyway startsWithNoLookaheadToken( node, - /* forbidFunctionClassAndDoExpr */ false + (node) => node.type === "ObjectExpression" ) ) { return true; @@ -974,16 +989,4 @@ function shouldWrapFunctionForExportDefault(path, options) { ); } -function isAssignmentExpressionLeft(path) { - const name = path.getName(); - const parent = path.getParentNode(); - - // "OptionalMemberExpression" can't be here - if (name === "object" && parent.type === "MemberExpression") { - return path.callParent(isAssignmentExpressionLeft); - } - - return name === "left" && parent.type === "AssignmentExpression"; -} - module.exports = needsParens; diff --git a/src/language-js/print/function.js b/src/language-js/print/function.js index 8263a11f0886..6323c639da45 100644 --- a/src/language-js/print/function.js +++ b/src/language-js/print/function.js @@ -373,7 +373,10 @@ function printArrowFunction(path, options, print, args) { // a <= a ? a : a const shouldAddParens = node.body.type === "ConditionalExpression" && - !startsWithNoLookaheadToken(node.body, /* forbidFunctionAndClass */ false); + !startsWithNoLookaheadToken( + node.body, + (node) => node.type === "ObjectExpression" + ); return group([ ...parts, diff --git a/src/language-js/utils/index.js b/src/language-js/utils/index.js index 097010953a13..52b34e054d8d 100644 --- a/src/language-js/utils/index.js +++ b/src/language-js/utils/index.js @@ -939,74 +939,56 @@ function shouldPrintComma(options, level = "es5") { } /** - * Tests if an expression starts with `{`, or (if forbidFunctionClassAndDoExpr - * holds) `function`, `class`, or `do {}`. Will be overzealous if there's - * already necessary grouping parentheses. + * Tests if an expression starts with something forbidden specified by the + * `forbid` predicate. E.g., used to check if expression statements start with: + * + * - `{` + * - `function`, `class`, or `do {}` + * - `let[` + * + * Will be overzealous if there's already necessary grouping parentheses. * * @param {Node} node - * @param {boolean} forbidFunctionClassAndDoExpr + * @param {(leftmostNode: Node) => boolean} forbid * @returns {boolean} */ -function startsWithNoLookaheadToken(node, forbidFunctionClassAndDoExpr) { - node = getLeftMost(node); +function startsWithNoLookaheadToken(node, forbid) { switch (node.type) { - case "FunctionExpression": - case "ClassExpression": - case "DoExpression": - return forbidFunctionClassAndDoExpr; - case "ObjectExpression": - return true; + case "BinaryExpression": + case "LogicalExpression": + case "AssignmentExpression": + case "NGPipeExpression": + return startsWithNoLookaheadToken(node.left, forbid); case "MemberExpression": case "OptionalMemberExpression": - return startsWithNoLookaheadToken( - node.object, - forbidFunctionClassAndDoExpr - ); + return startsWithNoLookaheadToken(node.object, forbid); case "TaggedTemplateExpression": if (node.tag.type === "FunctionExpression") { // IIFEs are always already parenthesized return false; } - return startsWithNoLookaheadToken(node.tag, forbidFunctionClassAndDoExpr); + return startsWithNoLookaheadToken(node.tag, forbid); case "CallExpression": case "OptionalCallExpression": if (node.callee.type === "FunctionExpression") { // IIFEs are always already parenthesized return false; } - return startsWithNoLookaheadToken( - node.callee, - forbidFunctionClassAndDoExpr - ); + return startsWithNoLookaheadToken(node.callee, forbid); case "ConditionalExpression": - return startsWithNoLookaheadToken( - node.test, - forbidFunctionClassAndDoExpr - ); + return startsWithNoLookaheadToken(node.test, forbid); case "UpdateExpression": - return ( - !node.prefix && - startsWithNoLookaheadToken(node.argument, forbidFunctionClassAndDoExpr) - ); + return !node.prefix && startsWithNoLookaheadToken(node.argument, forbid); case "BindExpression": - return ( - node.object && - startsWithNoLookaheadToken(node.object, forbidFunctionClassAndDoExpr) - ); + return node.object && startsWithNoLookaheadToken(node.object, forbid); case "SequenceExpression": - return startsWithNoLookaheadToken( - node.expressions[0], - forbidFunctionClassAndDoExpr - ); + return startsWithNoLookaheadToken(node.expressions[0], forbid); case "TSSatisfiesExpression": case "TSAsExpression": case "TSNonNullExpression": - return startsWithNoLookaheadToken( - node.expression, - forbidFunctionClassAndDoExpr - ); + return startsWithNoLookaheadToken(node.expression, forbid); default: - return false; + return forbid(node); } } @@ -1092,13 +1074,6 @@ function getPrecedence(operator) { return PRECEDENCE.get(operator); } -function getLeftMost(node) { - while (node.left) { - node = node.left; - } - return node; -} - function isBitwiseOperator(operator) { return ( Boolean(bitshiftOperators[operator]) || diff --git a/tests/format/js/identifier/parentheses/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/identifier/parentheses/__snapshots__/jsfmt.spec.js.snap index d297906faae2..2dd644b9804f 100644 --- a/tests/format/js/identifier/parentheses/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/js/identifier/parentheses/__snapshots__/jsfmt.spec.js.snap @@ -10,7 +10,7 @@ semi: false const [a = ((let)[0] = 1)] = 2; =====================================output===================================== -const [a = ((let)[0] = 1)] = 2 +const [a = (let[0] = 1)] = 2 ================================================================================ `; @@ -24,7 +24,7 @@ printWidth: 80 const [a = ((let)[0] = 1)] = 2; =====================================output===================================== -const [a = ((let)[0] = 1)] = 2; +const [a = (let[0] = 1)] = 2; ================================================================================ `; @@ -128,6 +128,12 @@ switch (foo) { with (let[0] = 1); +(let[x]).foo(); + +let.let[x].foo(); + +a = let[x].foo(); + =====================================output===================================== let.a = 1 @@ -163,7 +169,7 @@ var let = 1 ;({ a: let[a] } = 1) -alert(((let)[0] = 1)) +alert((let[0] = 1)) ;((let)[0] = 1) || 2 @@ -171,21 +177,21 @@ alert(((let)[0] = 1)) ;((let)[0] = 1) ? a : b -if (((let)[0] = 1)); +if ((let[0] = 1)); -while (((let)[0] = 1)); +while ((let[0] = 1)); -do {} while (((let)[0] = 1)) +do {} while ((let[0] = 1)) -var a = ((let)[0] = 1) +var a = (let[0] = 1) ;((let)[0] = 1) instanceof a -void ((let)[0] = 1) +void (let[0] = 1) ;((let)[0] = 1)() -new ((let)[0] = 1)() +new (let[0] = 1)() ;((let)[0] = 1)\`\` @@ -193,40 +199,46 @@ new ((let)[0] = 1)() ;((let)[0] = 1)?.toString -;[...((let)[0] = 1)] +;[...(let[0] = 1)] -foo = () => ((let)[0] = 1) +foo = () => (let[0] = 1) function* foo() { - yield ((let)[0] = 1) + yield (let[0] = 1) } async function foo() { - await ((let)[0] = 1) + await (let[0] = 1) } function foo() { - return ((let)[0] = 1) + return (let[0] = 1) } while (true) (let)[0] = 1 -throw ((let)[0] = 1) +throw (let[0] = 1) -;({ foo: ((let)[0] = 1) }) +;({ foo: (let[0] = 1) }) -;[((let)[0] = 1)] +;[(let[0] = 1)] -for ((let)[0] = 1; ; ); +for (let[0] = 1; ; ); -switch (((let)[0] = 1)) { +switch ((let[0] = 1)) { } switch (foo) { - case ((let)[0] = 1): + case (let[0] = 1): } -with (((let)[0] = 1)); +with ((let[0] = 1)); + +;(let)[x].foo() + +let.let[x].foo() + +a = let[x].foo() ================================================================================ `; @@ -329,6 +341,12 @@ switch (foo) { with (let[0] = 1); +(let[x]).foo(); + +let.let[x].foo(); + +a = let[x].foo(); + =====================================output===================================== let.a = 1; @@ -364,7 +382,7 @@ var let = 1; ({ a: let[a] } = 1); -alert(((let)[0] = 1)); +alert((let[0] = 1)); ((let)[0] = 1) || 2; @@ -372,21 +390,21 @@ alert(((let)[0] = 1)); ((let)[0] = 1) ? a : b; -if (((let)[0] = 1)); +if ((let[0] = 1)); -while (((let)[0] = 1)); +while ((let[0] = 1)); -do {} while (((let)[0] = 1)); +do {} while ((let[0] = 1)); -var a = ((let)[0] = 1); +var a = (let[0] = 1); ((let)[0] = 1) instanceof a; -void ((let)[0] = 1); +void (let[0] = 1); ((let)[0] = 1)(); -new ((let)[0] = 1)(); +new (let[0] = 1)(); ((let)[0] = 1)\`\`; @@ -394,40 +412,46 @@ new ((let)[0] = 1)(); ((let)[0] = 1)?.toString; -[...((let)[0] = 1)]; +[...(let[0] = 1)]; -foo = () => ((let)[0] = 1); +foo = () => (let[0] = 1); function* foo() { - yield ((let)[0] = 1); + yield (let[0] = 1); } async function foo() { - await ((let)[0] = 1); + await (let[0] = 1); } function foo() { - return ((let)[0] = 1); + return (let[0] = 1); } while (true) (let)[0] = 1; -throw ((let)[0] = 1); +throw (let[0] = 1); -({ foo: ((let)[0] = 1) }); +({ foo: (let[0] = 1) }); -[((let)[0] = 1)]; +[(let[0] = 1)]; -for ((let)[0] = 1; ; ); +for (let[0] = 1; ; ); -switch (((let)[0] = 1)) { +switch ((let[0] = 1)) { } switch (foo) { - case ((let)[0] = 1): + case (let[0] = 1): } -with (((let)[0] = 1)); +with ((let[0] = 1)); + +(let)[x].foo(); + +let.let[x].foo(); + +a = let[x].foo(); ================================================================================ `; diff --git a/tests/format/js/identifier/parentheses/let-in-assignment.js b/tests/format/js/identifier/parentheses/let-in-assignment.js index ff578ad3c8ba..8ac166a4f472 100644 --- a/tests/format/js/identifier/parentheses/let-in-assignment.js +++ b/tests/format/js/identifier/parentheses/let-in-assignment.js @@ -89,3 +89,9 @@ switch (foo) { } with (let[0] = 1); + +(let[x]).foo(); + +let.let[x].foo(); + +a = let[x].foo(); From b5475e757138f92155367496a38b111f770275b2 Mon Sep 17 00:00:00 2001 From: Georgii Dolzhykov Date: Tue, 20 Dec 2022 15:36:20 +0200 Subject: [PATCH 16/19] Fix for loops --- .../parentheses/__snapshots__/jsfmt.spec.js.snap | 12 ++++++++++-- .../js/identifier/parentheses/let-in-assignment.js | 2 ++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/format/js/identifier/parentheses/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/identifier/parentheses/__snapshots__/jsfmt.spec.js.snap index 2dd644b9804f..6773e995e7fc 100644 --- a/tests/format/js/identifier/parentheses/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/js/identifier/parentheses/__snapshots__/jsfmt.spec.js.snap @@ -119,6 +119,8 @@ throw (let[0] = 1); [(let[0] = 1)]; for ((let[0] = 1);;); +for ((let)[0] in {}); +for ((let)[0] of []); switch (let[0] = 1) {} @@ -223,7 +225,9 @@ throw (let[0] = 1) ;[(let[0] = 1)] -for (let[0] = 1; ; ); +for ((let)[0] = 1; ; ); +for ((let)[0] in {}); +for ((let)[0] of []); switch ((let[0] = 1)) { } @@ -332,6 +336,8 @@ throw (let[0] = 1); [(let[0] = 1)]; for ((let[0] = 1);;); +for ((let)[0] in {}); +for ((let)[0] of []); switch (let[0] = 1) {} @@ -436,7 +442,9 @@ throw (let[0] = 1); [(let[0] = 1)]; -for (let[0] = 1; ; ); +for ((let)[0] = 1; ; ); +for ((let)[0] in {}); +for ((let)[0] of []); switch ((let[0] = 1)) { } diff --git a/tests/format/js/identifier/parentheses/let-in-assignment.js b/tests/format/js/identifier/parentheses/let-in-assignment.js index 8ac166a4f472..73a43eca6817 100644 --- a/tests/format/js/identifier/parentheses/let-in-assignment.js +++ b/tests/format/js/identifier/parentheses/let-in-assignment.js @@ -81,6 +81,8 @@ throw (let[0] = 1); [(let[0] = 1)]; for ((let[0] = 1);;); +for ((let)[0] in {}); +for ((let)[0] of []); switch (let[0] = 1) {} From a875550d999fd5b6f8722a6b725ad933e2ddf460 Mon Sep 17 00:00:00 2001 From: Georgii Dolzhykov Date: Tue, 20 Dec 2022 15:37:14 +0200 Subject: [PATCH 17/19] Fix for loops 2 --- src/language-js/needs-parens.js | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/language-js/needs-parens.js b/src/language-js/needs-parens.js index b56857ef5bf3..7a31778038dc 100644 --- a/src/language-js/needs-parens.js +++ b/src/language-js/needs-parens.js @@ -85,13 +85,24 @@ function needsParens(path, options) { parent.computed && !parent.optional ) { - const expressionStatement = path.findAncestor( - (node) => node.type === "ExpressionStatement" + const statement = path.findAncestor( + (node) => + node.type === "ExpressionStatement" || + node.type === "ForStatement" || + node.type === "ForInStatement" || + node.type === "ForOfStatement" ); + const expression = !statement + ? undefined + : statement.type === "ExpressionStatement" + ? statement.expression + : statement.type === "ForStatement" + ? statement.init + : statement.left; if ( - expressionStatement && + expression && startsWithNoLookaheadToken( - expressionStatement.expression, + expression, (leftmostNode) => leftmostNode === node ) ) { From 3e80b1a2b69091191b9b67f0a1ef5853783ab2f4 Mon Sep 17 00:00:00 2001 From: Georgii Dolzhykov Date: Tue, 20 Dec 2022 15:59:30 +0200 Subject: [PATCH 18/19] Improve comment --- src/language-js/utils/index.js | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/language-js/utils/index.js b/src/language-js/utils/index.js index 52b34e054d8d..15fd6069b7e9 100644 --- a/src/language-js/utils/index.js +++ b/src/language-js/utils/index.js @@ -939,56 +939,59 @@ function shouldPrintComma(options, level = "es5") { } /** - * Tests if an expression starts with something forbidden specified by the - * `forbid` predicate. E.g., used to check if expression statements start with: + * Tests if the leftmost node of the expression matches the predicate. E.g., + * used to check whether an expression statement needs to be wrapped in extra + * parentheses because it starts with: * * - `{` * - `function`, `class`, or `do {}` * - `let[` * - * Will be overzealous if there's already necessary grouping parentheses. + * Will be overzealous if there already are necessary grouping parentheses. * * @param {Node} node - * @param {(leftmostNode: Node) => boolean} forbid + * @param {(leftmostNode: Node) => boolean} predicate * @returns {boolean} */ -function startsWithNoLookaheadToken(node, forbid) { +function startsWithNoLookaheadToken(node, predicate) { switch (node.type) { case "BinaryExpression": case "LogicalExpression": case "AssignmentExpression": case "NGPipeExpression": - return startsWithNoLookaheadToken(node.left, forbid); + return startsWithNoLookaheadToken(node.left, predicate); case "MemberExpression": case "OptionalMemberExpression": - return startsWithNoLookaheadToken(node.object, forbid); + return startsWithNoLookaheadToken(node.object, predicate); case "TaggedTemplateExpression": if (node.tag.type === "FunctionExpression") { // IIFEs are always already parenthesized return false; } - return startsWithNoLookaheadToken(node.tag, forbid); + return startsWithNoLookaheadToken(node.tag, predicate); case "CallExpression": case "OptionalCallExpression": if (node.callee.type === "FunctionExpression") { // IIFEs are always already parenthesized return false; } - return startsWithNoLookaheadToken(node.callee, forbid); + return startsWithNoLookaheadToken(node.callee, predicate); case "ConditionalExpression": - return startsWithNoLookaheadToken(node.test, forbid); + return startsWithNoLookaheadToken(node.test, predicate); case "UpdateExpression": - return !node.prefix && startsWithNoLookaheadToken(node.argument, forbid); + return ( + !node.prefix && startsWithNoLookaheadToken(node.argument, predicate) + ); case "BindExpression": - return node.object && startsWithNoLookaheadToken(node.object, forbid); + return node.object && startsWithNoLookaheadToken(node.object, predicate); case "SequenceExpression": - return startsWithNoLookaheadToken(node.expressions[0], forbid); + return startsWithNoLookaheadToken(node.expressions[0], predicate); case "TSSatisfiesExpression": case "TSAsExpression": case "TSNonNullExpression": - return startsWithNoLookaheadToken(node.expression, forbid); + return startsWithNoLookaheadToken(node.expression, predicate); default: - return forbid(node); + return predicate(node); } } From ef08c06dff3a585192e055b5326264aada1dd897 Mon Sep 17 00:00:00 2001 From: fisker Date: Thu, 22 Dec 2022 09:37:50 +0800 Subject: [PATCH 19/19] More test --- .../__snapshots__/jsfmt.spec.js.snap | 20 +++++++++++++++++-- .../{let-in-assignment.js => let.js} | 4 ++++ 2 files changed, 22 insertions(+), 2 deletions(-) rename tests/format/js/identifier/parentheses/{let-in-assignment.js => let.js} (97%) diff --git a/tests/format/js/identifier/parentheses/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/identifier/parentheses/__snapshots__/jsfmt.spec.js.snap index 6773e995e7fc..6d0419713d22 100644 --- a/tests/format/js/identifier/parentheses/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/js/identifier/parentheses/__snapshots__/jsfmt.spec.js.snap @@ -29,7 +29,7 @@ const [a = (let[0] = 1)] = 2; ================================================================================ `; -exports[`let-in-assignment.js - {"semi":false} format 1`] = ` +exports[`let.js - {"semi":false} format 1`] = ` ====================================options===================================== parsers: ["babel", "typescript"] printWidth: 80 @@ -136,6 +136,10 @@ let.let[x].foo(); a = let[x].foo(); +(let)[2]; + +a[1] + (let[2] = 2); + =====================================output===================================== let.a = 1 @@ -244,10 +248,14 @@ let.let[x].foo() a = let[x].foo() +;(let)[2] + +a[1] + (let[2] = 2) + ================================================================================ `; -exports[`let-in-assignment.js format 1`] = ` +exports[`let.js format 1`] = ` ====================================options===================================== parsers: ["babel", "typescript"] printWidth: 80 @@ -353,6 +361,10 @@ let.let[x].foo(); a = let[x].foo(); +(let)[2]; + +a[1] + (let[2] = 2); + =====================================output===================================== let.a = 1; @@ -461,5 +473,9 @@ let.let[x].foo(); a = let[x].foo(); +(let)[2]; + +a[1] + (let[2] = 2); + ================================================================================ `; diff --git a/tests/format/js/identifier/parentheses/let-in-assignment.js b/tests/format/js/identifier/parentheses/let.js similarity index 97% rename from tests/format/js/identifier/parentheses/let-in-assignment.js rename to tests/format/js/identifier/parentheses/let.js index 73a43eca6817..2f0cc8a37b9a 100644 --- a/tests/format/js/identifier/parentheses/let-in-assignment.js +++ b/tests/format/js/identifier/parentheses/let.js @@ -97,3 +97,7 @@ with (let[0] = 1); let.let[x].foo(); a = let[x].foo(); + +(let)[2]; + +a[1] + (let[2] = 2);