From 292b1c0017bc442d399f67e01d699c59e6b71453 Mon Sep 17 00:00:00 2001 From: Milos Djermanovic Date: Fri, 15 Jan 2021 18:33:06 +0100 Subject: [PATCH] Fix: no-extra-parens false positive with `let` identifier in for-loop (#13981) --- lib/rules/no-extra-parens.js | 16 +++ tests/lib/rules/no-extra-parens.js | 175 +++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) diff --git a/lib/rules/no-extra-parens.js b/lib/rules/no-extra-parens.js index 8d358d23ad3..19c6fced79d 100644 --- a/lib/rules/no-extra-parens.js +++ b/lib/rules/no-extra-parens.js @@ -895,6 +895,22 @@ module.exports = { } if (node.init) { + + if (node.init.type !== "VariableDeclaration") { + const firstToken = sourceCode.getFirstToken(node.init, astUtils.isNotOpeningParenToken); + + if ( + firstToken.value === "let" && + astUtils.isOpeningBracketToken( + sourceCode.getTokenAfter(firstToken, astUtils.isNotClosingParenToken) + ) + ) { + + // ForStatement#init expression cannot start with `let[`. + tokensToIgnore.add(firstToken); + } + } + startNewReportsBuffering(); if (hasExcessParens(node.init)) { diff --git a/tests/lib/rules/no-extra-parens.js b/tests/lib/rules/no-extra-parens.js index 3fee9fefd8f..43c66c7562a 100644 --- a/tests/lib/rules/no-extra-parens.js +++ b/tests/lib/rules/no-extra-parens.js @@ -599,6 +599,22 @@ ruleTester.run("no-extra-parens", rule, { options: ["functions"] }, "(let)[foo]", + + // ForStatement#init expression cannot start with `let[`. It would be parsed as a `let` declaration with array pattern, or a syntax error. + "for ((let[a]);;);", + "for ((let)[a];;);", + "for ((let[a] = 1);;);", + "for ((let[a]) = 1;;);", + "for ((let)[a] = 1;;);", + "for ((let[a, b] = foo);;);", + "for ((let[a].b = 1);;);", + "for ((let[a].b) = 1;;);", + "for ((let[a]).b = 1;;);", + "for ((let)[a].b = 1;;);", + "for ((let[a])();;);", + "for ((let)[a]();;);", + "for ((let[a]) + b;;);", + "for ((let) in foo);", "for ((let[foo]) in bar);", "for ((let)[foo] in bar);", @@ -1880,6 +1896,165 @@ ruleTester.run("no-extra-parens", rule, { "Identifier", 1 ), + + // ForStatement#init expression cannot start with `let[`, but it can start with `let` if it isn't followed by `[` + invalid( + "for ((let);;);", + "for (let;;);", + "Identifier", + 1 + ), + invalid( + "for ((let = 1);;);", + "for (let = 1;;);", + "AssignmentExpression", + 1 + ), + invalid( + "for ((let) = 1;;);", + "for (let = 1;;);", + "Identifier", + 1 + ), + invalid( + "for ((let = []);;);", + "for (let = [];;);", + "AssignmentExpression", + 1 + ), + invalid( + "for ((let) = [];;);", + "for (let = [];;);", + "Identifier", + 1 + ), + invalid( + "for ((let());;);", + "for (let();;);", + "CallExpression", + 1 + ), + invalid( + "for ((let([]));;);", + "for (let([]);;);", + "CallExpression", + 1 + ), + invalid( + "for ((let())[a];;);", + "for (let()[a];;);", + "CallExpression", + 1 + ), + invalid( + "for ((let`[]`);;);", + "for (let`[]`;;);", + "TaggedTemplateExpression", + 1 + ), + invalid( + "for ((let.a);;);", + "for (let.a;;);", + "MemberExpression", + 1 + ), + invalid( + "for ((let).a;;);", + "for (let.a;;);", + "Identifier", + 1 + ), + invalid( + "for ((let).a = 1;;);", + "for (let.a = 1;;);", + "Identifier", + 1 + ), + invalid( + "for ((let).a[b];;);", + "for (let.a[b];;);", + "Identifier", + 1 + ), + invalid( + "for ((let.a)[b];;);", + "for (let.a[b];;);", + "MemberExpression", + 1 + ), + invalid( + "for ((let.a[b]);;);", + "for (let.a[b];;);", + "MemberExpression", + 1 + ), + invalid( + "for ((let);[];);", + "for (let;[];);", + "Identifier", + 1 + ), + invalid( + "for (((let[a]));;);", + "for ((let[a]);;);", + "MemberExpression", + 1 + ), + invalid( + "for (((let))[a];;);", + "for ((let)[a];;);", + "Identifier", + 1 + ), + invalid( + "for (((let[a])).b;;);", + "for ((let[a]).b;;);", + "MemberExpression", + 1 + ), + invalid( + "for (((let))[a].b;;);", + "for ((let)[a].b;;);", + "Identifier", + 1 + ), + invalid( + "for (((let)[a]).b;;);", + "for ((let)[a].b;;);", + "MemberExpression", + 1 + ), + invalid( + "for (((let[a]) = b);;);", + "for ((let[a]) = b;;);", + "AssignmentExpression", + 1 + ), + invalid( + "for (((let)[a]) = b;;);", + "for ((let)[a] = b;;);", + "MemberExpression", + 1 + ), + invalid( + "for (((let)[a] = b);;);", + "for ((let)[a] = b;;);", + "AssignmentExpression", + 1 + ), + invalid( + "for ((Let[a]);;);", + "for (Let[a];;);", + "MemberExpression", + 1 + ), + invalid( + "for ((lett)[a];;);", + "for (lett[a];;);", + "Identifier", + 1 + ), + invalid( "for ((let.foo) in bar);", "for (let.foo in bar);",