diff --git a/docs/rules/no-extra-parens.md b/docs/rules/no-extra-parens.md index 68b986eff6c..b521dcbe268 100644 --- a/docs/rules/no-extra-parens.md +++ b/docs/rules/no-extra-parens.md @@ -48,6 +48,14 @@ for (a of (b)); typeof (a); (function(){} ? a() : b()); + +class A { + [(x)] = 1; +} + +class B { + x = (y + z); +} ``` Examples of **correct** code for this rule with the default `"all"` option: @@ -72,6 +80,14 @@ for (a of b); for (a in b, c); for (a in b); + +class A { + [x] = 1; +} + +class B { + x = y + z; +} ``` ### conditionalAssign diff --git a/lib/rules/no-extra-parens.js b/lib/rules/no-extra-parens.js index 307e340c958..d063350461d 100644 --- a/lib/rules/no-extra-parens.js +++ b/lib/rules/no-extra-parens.js @@ -808,13 +808,6 @@ module.exports = { CallExpression: checkCallNew, - ClassBody(node) { - node.body - .filter(member => member.type === "MethodDefinition" && member.computed && member.key) - .filter(member => hasExcessParensWithPrecedence(member.key, PRECEDENCE_OF_ASSIGNMENT_EXPR)) - .forEach(member => report(member.key)); - }, - ConditionalExpression(node) { if (isReturnAssignException(node)) { return; @@ -1063,6 +1056,12 @@ module.exports = { } }, + "MethodDefinition[computed=true]"(node) { + if (hasExcessParensWithPrecedence(node.key, PRECEDENCE_OF_ASSIGNMENT_EXPR)) { + report(node.key); + } + }, + NewExpression: checkCallNew, ObjectExpression(node) { @@ -1090,6 +1089,16 @@ module.exports = { } }, + PropertyDefinition(node) { + if (node.computed && hasExcessParensWithPrecedence(node.key, PRECEDENCE_OF_ASSIGNMENT_EXPR)) { + report(node.key); + } + + if (node.value && hasExcessParensWithPrecedence(node.value, PRECEDENCE_OF_ASSIGNMENT_EXPR)) { + report(node.value); + } + }, + RestElement(node) { const argument = node.argument; diff --git a/tests/lib/rules/no-extra-parens.js b/tests/lib/rules/no-extra-parens.js index a14ececc099..5a4dba6482e 100644 --- a/tests/lib/rules/no-extra-parens.js +++ b/tests/lib/rules/no-extra-parens.js @@ -44,7 +44,7 @@ function invalid(code, output, type, line, config) { const ruleTester = new RuleTester({ parserOptions: { - ecmaVersion: 2021, + ecmaVersion: 2022, ecmaFeatures: { jsx: true } @@ -182,6 +182,25 @@ ruleTester.run("no-extra-parens", rule, { "class foo { a(){} [b](){} c(){} [(d,e)](){} }", "class foo { [(a,b)](){} c(){} [d](){} e(){} }", "const foo = class { constructor(){} a(){} get b(){} set b(bar){} get c(){} set d(baz){} static e(){} }", + "class foo { x; }", + "class foo { static x; }", + "class foo { x = 1; }", + "class foo { static x = 1; }", + "class foo { #x; }", + "class foo { static #x; }", + "class foo { static #x = 1; }", + "class foo { #x(){} get #y() {} set #y(value) {} static #z(){} static get #q() {} static set #q(value) {} }", + "const foo = class { #x(){} get #y() {} set #y(value) {} static #z(){} static get #q() {} static set #q(value) {} }", + "class foo { [(x, y)]; }", + "class foo { static [(x, y)]; }", + "class foo { [(x, y)] = 1; }", + "class foo { static [(x, y)] = 1; }", + "class foo { x = (y, z); }", + "class foo { static x = (y, z); }", + "class foo { #x = (y, z); }", + "class foo { static #x = (y, z); }", + "class foo { [(1, 2)] = (3, 4) }", + "const foo = class { [(1, 2)] = (3, 4) }", // ExpressionStatement restricted productions "({});", @@ -771,6 +790,26 @@ ruleTester.run("no-extra-parens", rule, { invalid("class foo { [(a,b)](){} [(c+d)](){} }", "class foo { [(a,b)](){} [c+d](){} }", "BinaryExpression"), invalid("class foo { [a+(b*c)](){} }", "class foo { [a+b*c](){} }", "BinaryExpression"), invalid("const foo = class { [(a)](){} }", "const foo = class { [a](){} }", "Identifier"), + invalid("class foo { [(x)]; }", "class foo { [x]; }", "Identifier"), + invalid("class foo { static [(x)]; }", "class foo { static [x]; }", "Identifier"), + invalid("class foo { [(x)] = 1; }", "class foo { [x] = 1; }", "Identifier"), + invalid("class foo { static [(x)] = 1; }", "class foo { static [x] = 1; }", "Identifier"), + invalid("const foo = class { [(x)]; }", "const foo = class { [x]; }", "Identifier"), + invalid("class foo { [(x = y)]; }", "class foo { [x = y]; }", "AssignmentExpression"), + invalid("class foo { [(x + y)]; }", "class foo { [x + y]; }", "BinaryExpression"), + invalid("class foo { [(x ? y : z)]; }", "class foo { [x ? y : z]; }", "ConditionalExpression"), + invalid("class foo { [((x, y))]; }", "class foo { [(x, y)]; }", "SequenceExpression"), + invalid("class foo { x = (y); }", "class foo { x = y; }", "Identifier"), + invalid("class foo { static x = (y); }", "class foo { static x = y; }", "Identifier"), + invalid("class foo { #x = (y); }", "class foo { #x = y; }", "Identifier"), + invalid("class foo { static #x = (y); }", "class foo { static #x = y; }", "Identifier"), + invalid("const foo = class { x = (y); }", "const foo = class { x = y; }", "Identifier"), + invalid("class foo { x = (() => {}); }", "class foo { x = () => {}; }", "ArrowFunctionExpression"), + invalid("class foo { x = (y + z); }", "class foo { x = y + z; }", "BinaryExpression"), + invalid("class foo { x = (y ? z : q); }", "class foo { x = y ? z : q; }", "ConditionalExpression"), + invalid("class foo { x = ((y, z)); }", "class foo { x = (y, z); }", "SequenceExpression"), + + // invalid( "var foo = (function*() { if ((yield foo())) { return; } }())", "var foo = (function*() { if (yield foo()) { return; } }())",