diff --git a/packages/eslint-plugin/src/rules/no-extra-parens.ts b/packages/eslint-plugin/src/rules/no-extra-parens.ts index 38c5e3134cf..d4fe9afd54b 100644 --- a/packages/eslint-plugin/src/rules/no-extra-parens.ts +++ b/packages/eslint-plugin/src/rules/no-extra-parens.ts @@ -35,21 +35,26 @@ export default util.createRule({ const rule = rules.BinaryExpression as (n: typeof node) => void; // makes the rule think it should skip the left or right - if (util.isTypeAssertion(node.left)) { + const isLeftTypeAssertion = util.isTypeAssertion(node.left); + const isRightTypeAssertion = util.isTypeAssertion(node.right); + if (isLeftTypeAssertion && isRightTypeAssertion) { + return; // ignore + } + if (isLeftTypeAssertion) { return rule({ ...node, left: { ...node.left, - type: AST_NODE_TYPES.BinaryExpression as any, + type: AST_NODE_TYPES.SequenceExpression as any, }, }); } - if (util.isTypeAssertion(node.right)) { + if (isRightTypeAssertion) { return rule({ ...node, right: { ...node.right, - type: AST_NODE_TYPES.BinaryExpression as any, + type: AST_NODE_TYPES.SequenceExpression as any, }, }); } diff --git a/packages/eslint-plugin/tests/rules/no-extra-parens.test.ts b/packages/eslint-plugin/tests/rules/no-extra-parens.test.ts index 6d84149efb8..29afab88ec5 100644 --- a/packages/eslint-plugin/tests/rules/no-extra-parens.test.ts +++ b/packages/eslint-plugin/tests/rules/no-extra-parens.test.ts @@ -23,7 +23,6 @@ for (a in b, c); for (a in b); `, }), - `t.true((me.get as SinonStub).calledWithExactly('/foo', other));`, ...batchedSingleLineTests({ code: ` while ((foo = bar())) {} @@ -120,6 +119,27 @@ typeof (a); }), ...batchedSingleLineTests({ code: ` +const x = (1 as 1) | (1 as 1); +const x = (<1>1) | (<1>1); +const x = (1 as 1) | 2; +const x = (1 as 1) + 2 + 2; +const x = 1 + 1 + (2 as 2); +const x = 1 | (2 as 2); +const x = (<1>1) | 2; +const x = 1 | (<2>2); +t.true((me.get as SinonStub).calledWithExactly('/foo', other)); +t.true((me.get).calledWithExactly('/foo', other)); +(requestInit.headers as Headers).get('Cookie'); +( requestInit.headers).get('Cookie'); + `, + parserOptions: { + ecmaFeatures: { + jsx: false, + }, + }, + }), + ...batchedSingleLineTests({ + code: ` [a as b]; () => (1 as 1); x = a as b; @@ -155,6 +175,48 @@ switch (foo) { case 1: case (2 as 2): break; default: break; } }, ], }), + ...batchedSingleLineTests({ + code: ` +[a]; +() => (<1>1); +x = a; +const x = (<1>1) | 2; +const x = 1 | (<2>2); +const x = await (>foo); +const res2 = (fn)(); +(x) ? 1 : 0; +x ? (<1>1) : 2; +x ? 1 : (<2>2); +while (foo) {}; +do {} while (foo); +for (let i of ([])) {} +for (let i in ({})) {} +for ((<1>1);;) {} +for (;(<1>1);) {} +for (;;(<1>1)) {} +if (<1>1) {} +const x = (<1>1).toString(); +new (<1>1)(); +const x = { ...(<1>1), ...{} }; +throw (<1>1); +throw 1; +const x = !(<1>1); +const x = (<1>1)++; +function *x() { yield (<1>1); yield 1; } +switch (foo) { case 1: case (<2>2): break; default: break; } + `, + parserOptions: { + ecmaFeatures: { + jsx: false, + }, + }, + options: [ + 'all', + { + nestedBinaryExpressions: false, + }, + ], + }), ], invalid: [