From 2af9e54f860e8a4ffa6e22b33076107fee526b62 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Sat, 19 Nov 2022 16:52:58 +0530 Subject: [PATCH 1/8] feat: add new `allowParensAfterComment` option (`no-extra-parens`) --- lib/rules/no-extra-parens.js | 8 ++- tests/lib/rules/no-extra-parens.js | 93 ++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 1 deletion(-) diff --git a/lib/rules/no-extra-parens.js b/lib/rules/no-extra-parens.js index 246a5a0d5e1..a57b3ed78f4 100644 --- a/lib/rules/no-extra-parens.js +++ b/lib/rules/no-extra-parens.js @@ -52,7 +52,8 @@ module.exports = { enforceForArrowConditionals: { type: "boolean" }, enforceForSequenceExpressions: { type: "boolean" }, enforceForNewInMemberExpressions: { type: "boolean" }, - enforceForFunctionPrototypeMethods: { type: "boolean" } + enforceForFunctionPrototypeMethods: { type: "boolean" }, + allowParensAfterComment: { type: "boolean" } }, additionalProperties: false } @@ -86,6 +87,7 @@ module.exports = { context.options[1].enforceForNewInMemberExpressions === false; const IGNORE_FUNCTION_PROTOTYPE_METHODS = ALL_NODES && context.options[1] && context.options[1].enforceForFunctionPrototypeMethods === false; + const ALLOW_PARENS_AFTER_COMMENT = ALL_NODES && context.options[1] && context.options[1].allowParensAfterComment === true; const PRECEDENCE_OF_ASSIGNMENT_EXPR = precedence({ type: "AssignmentExpression" }); const PRECEDENCE_OF_UPDATE_EXPR = precedence({ type: "UpdateExpression" }); @@ -402,6 +404,10 @@ module.exports = { if (isIIFE(node) && !isParenthesised(node.callee)) { return; } + + if (ALLOW_PARENS_AFTER_COMMENT && isParenthesised(node) && sourceCode.getCommentsBefore(leftParenToken).length > 0) { + return; + } } /** diff --git a/tests/lib/rules/no-extra-parens.js b/tests/lib/rules/no-extra-parens.js index 96ae9f5bddf..67f0786999e 100644 --- a/tests/lib/rules/no-extra-parens.js +++ b/tests/lib/rules/no-extra-parens.js @@ -739,6 +739,42 @@ ruleTester.run("no-extra-parens", rule, { { code: "(Object.prototype.toString.call())", options: ["functions"], + }, + + // "allowParensAfterComment" option + { + code: "const span = /**@type {HTMLSpanElement}*/(event.currentTarget);", + options: ["all", { allowParensAfterComment: true }], + parserOptions: { ecmaVersion: 2020 } + }, + { + code: "if (/** @type {Compiler | MultiCompiler} */(options).hooks) console.log('good');", + options: ["all", { allowParensAfterComment: true }], + parserOptions: { ecmaVersion: 2020 } + }, + { + code: ` + validate(/** @type {Schema} */ (schema), options, { + name: "Dev Server", + baseDataPath: "options", + }); + `, + options: ["all", { allowParensAfterComment: true }], + parserOptions: { ecmaVersion: 2020 } + }, + { + code: ` + if (condition) { + /** @type {ServerOptions} */ + (options.server.options).requestCert = false; + } + `, + options: ["all", { allowParensAfterComment: true }], + parserOptions: { ecmaVersion: 2020 } + }, + { + code: "const net = ipaddr.parseCIDR(/** @type {string} */ (cidr));", + options: ["all", { allowParensAfterComment: true }], parserOptions: { ecmaVersion: 2020 } } ], @@ -3192,6 +3228,63 @@ ruleTester.run("no-extra-parens", rule, { errors: [{ messageId: "unexpected" }] }, + // "allowParensAfterComment" option + { + code: "const span = /**@type {HTMLSpanElement}*/(event.currentTarget);", + output: "const span = /**@type {HTMLSpanElement}*/event.currentTarget;", + options: ["all", { allowParensAfterComment: false }], + parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpected" }] + }, + { + code: "if (/** @type {Compiler | MultiCompiler} */(options).hooks) console.log('good');", + output: "if (/** @type {Compiler | MultiCompiler} */options.hooks) console.log('good');", + options: ["all", { allowParensAfterComment: false }], + parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpected" }] + }, + { + code: ` + validate(/** @type {Schema} */ (schema), options, { + name: "Dev Server", + baseDataPath: "options", + }); + `, + output: ` + validate(/** @type {Schema} */ schema, options, { + name: "Dev Server", + baseDataPath: "options", + }); + `, + options: ["all", { allowParensAfterComment: false }], + parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpected" }] + }, + { + code: ` + if (condition) { + /** @type {ServerOptions} */ + (options.server.options).requestCert = false; + } + `, + output: ` + if (condition) { + /** @type {ServerOptions} */ + options.server.options.requestCert = false; + } + `, + options: ["all", { allowParensAfterComment: false }], + parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpected" }] + }, + { + code: "const net = ipaddr.parseCIDR(/** @type {string} */ (cidr));", + output: "const net = ipaddr.parseCIDR(/** @type {string} */ cidr);", + options: ["all", { allowParensAfterComment: false }], + parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpected" }] + }, + // Optional chaining { code: "var v = (obj?.aaa)?.aaa", From 9cf3e200705d4a0bb1c0cde9089506e4e4e4fcda Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Sun, 20 Nov 2022 16:01:39 +0530 Subject: [PATCH 2/8] feat: add new `allowParensAfterCommentPattern` option to the `no-extra-parens` rule --- docs/src/rules/no-extra-parens.md | 1 + lib/rules/no-extra-parens.js | 17 +++++-- tests/lib/rules/no-extra-parens.js | 81 +++++++++++++++++++++++++----- 3 files changed, 82 insertions(+), 17 deletions(-) diff --git a/docs/src/rules/no-extra-parens.md b/docs/src/rules/no-extra-parens.md index 8e5bb714cbd..d8108ceb99e 100644 --- a/docs/src/rules/no-extra-parens.md +++ b/docs/src/rules/no-extra-parens.md @@ -38,6 +38,7 @@ This rule has an object option for exceptions to the `"all"` option: * `"enforceForSequenceExpressions": false` allows extra parentheses around sequence expressions * `"enforceForNewInMemberExpressions": false` allows extra parentheses around `new` expressions in member expressions * `"enforceForFunctionPrototypeMethods": false` allows extra parentheses around immediate `.call` and `.apply` method calls on function expressions and around function expressions in the same context. +* `"allowParensAfterComment": true` allows extra parentheses preceded by a comment that matches a regular expression ### all diff --git a/lib/rules/no-extra-parens.js b/lib/rules/no-extra-parens.js index a57b3ed78f4..343a8b6ace8 100644 --- a/lib/rules/no-extra-parens.js +++ b/lib/rules/no-extra-parens.js @@ -53,7 +53,7 @@ module.exports = { enforceForSequenceExpressions: { type: "boolean" }, enforceForNewInMemberExpressions: { type: "boolean" }, enforceForFunctionPrototypeMethods: { type: "boolean" }, - allowParensAfterComment: { type: "boolean" } + allowParensAfterCommentPattern: { type: "string" } }, additionalProperties: false } @@ -87,7 +87,7 @@ module.exports = { context.options[1].enforceForNewInMemberExpressions === false; const IGNORE_FUNCTION_PROTOTYPE_METHODS = ALL_NODES && context.options[1] && context.options[1].enforceForFunctionPrototypeMethods === false; - const ALLOW_PARENS_AFTER_COMMENT = ALL_NODES && context.options[1] && context.options[1].allowParensAfterComment === true; + const ALLOW_PARENS_AFTER_COMMENT_PATTERN = ALL_NODES && context.options[1] && context.options[1].allowParensAfterCommentPattern; const PRECEDENCE_OF_ASSIGNMENT_EXPR = precedence({ type: "AssignmentExpression" }); const PRECEDENCE_OF_UPDATE_EXPR = precedence({ type: "UpdateExpression" }); @@ -405,8 +405,17 @@ module.exports = { return; } - if (ALLOW_PARENS_AFTER_COMMENT && isParenthesised(node) && sourceCode.getCommentsBefore(leftParenToken).length > 0) { - return; + if (ALLOW_PARENS_AFTER_COMMENT_PATTERN && isParenthesised(node)) { + const commentsBeforeLeftParenToken = sourceCode.getCommentsBefore(leftParenToken); + const totalCommentsBeforeLeftParenTokenCount = commentsBeforeLeftParenToken.length; + const ignorePattern = new RegExp(ALLOW_PARENS_AFTER_COMMENT_PATTERN, "u"); + + if ( + totalCommentsBeforeLeftParenTokenCount > 0 && + ignorePattern.test(commentsBeforeLeftParenToken[totalCommentsBeforeLeftParenTokenCount - 1].value) + ) { + return; + } } } diff --git a/tests/lib/rules/no-extra-parens.js b/tests/lib/rules/no-extra-parens.js index 67f0786999e..5412683c5bc 100644 --- a/tests/lib/rules/no-extra-parens.js +++ b/tests/lib/rules/no-extra-parens.js @@ -738,18 +738,18 @@ ruleTester.run("no-extra-parens", rule, { }, { code: "(Object.prototype.toString.call())", - options: ["functions"], + options: ["functions"] }, - // "allowParensAfterComment" option + // "allowParensAfterCommentPattern" option { code: "const span = /**@type {HTMLSpanElement}*/(event.currentTarget);", - options: ["all", { allowParensAfterComment: true }], + options: ["all", { allowParensAfterCommentPattern: "@type" }], parserOptions: { ecmaVersion: 2020 } }, { code: "if (/** @type {Compiler | MultiCompiler} */(options).hooks) console.log('good');", - options: ["all", { allowParensAfterComment: true }], + options: ["all", { allowParensAfterCommentPattern: "@type" }], parserOptions: { ecmaVersion: 2020 } }, { @@ -759,7 +759,7 @@ ruleTester.run("no-extra-parens", rule, { baseDataPath: "options", }); `, - options: ["all", { allowParensAfterComment: true }], + options: ["all", { allowParensAfterCommentPattern: "@type" }], parserOptions: { ecmaVersion: 2020 } }, { @@ -769,12 +769,12 @@ ruleTester.run("no-extra-parens", rule, { (options.server.options).requestCert = false; } `, - options: ["all", { allowParensAfterComment: true }], + options: ["all", { allowParensAfterCommentPattern: "@type" }], parserOptions: { ecmaVersion: 2020 } }, { code: "const net = ipaddr.parseCIDR(/** @type {string} */ (cidr));", - options: ["all", { allowParensAfterComment: true }], + options: ["all", { allowParensAfterCommentPattern: "@type" }], parserOptions: { ecmaVersion: 2020 } } ], @@ -3228,18 +3228,73 @@ ruleTester.run("no-extra-parens", rule, { errors: [{ messageId: "unexpected" }] }, - // "allowParensAfterComment" option + // "allowParensAfterCommentPattern" option (off by default) + { + code: "const span = /**@type {HTMLSpanElement}*/(event.currentTarget);", + output: "const span = /**@type {HTMLSpanElement}*/event.currentTarget;", + options: ["all"], + parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpected" }] + }, + { + code: "if (/** @type {Compiler | MultiCompiler} */(options).hooks) console.log('good');", + output: "if (/** @type {Compiler | MultiCompiler} */options.hooks) console.log('good');", + options: ["all"], + parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpected" }] + }, + { + code: ` + validate(/** @type {Schema} */ (schema), options, { + name: "Dev Server", + baseDataPath: "options", + }); + `, + output: ` + validate(/** @type {Schema} */ schema, options, { + name: "Dev Server", + baseDataPath: "options", + }); + `, + options: ["all"], + parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpected" }] + }, + { + code: ` + if (condition) { + /** @type {ServerOptions} */ + (options.server.options).requestCert = false; + } + `, + output: ` + if (condition) { + /** @type {ServerOptions} */ + options.server.options.requestCert = false; + } + `, + options: ["all"], + parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpected" }] + }, + { + code: "const net = ipaddr.parseCIDR(/** @type {string} */ (cidr));", + output: "const net = ipaddr.parseCIDR(/** @type {string} */ cidr);", + options: ["all"], + parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpected" }] + }, { code: "const span = /**@type {HTMLSpanElement}*/(event.currentTarget);", output: "const span = /**@type {HTMLSpanElement}*/event.currentTarget;", - options: ["all", { allowParensAfterComment: false }], + options: ["all", { allowParensAfterCommentPattern: "invalid" }], parserOptions: { ecmaVersion: 2020 }, errors: [{ messageId: "unexpected" }] }, { code: "if (/** @type {Compiler | MultiCompiler} */(options).hooks) console.log('good');", output: "if (/** @type {Compiler | MultiCompiler} */options.hooks) console.log('good');", - options: ["all", { allowParensAfterComment: false }], + options: ["all", { allowParensAfterCommentPattern: "invalid" }], parserOptions: { ecmaVersion: 2020 }, errors: [{ messageId: "unexpected" }] }, @@ -3256,7 +3311,7 @@ ruleTester.run("no-extra-parens", rule, { baseDataPath: "options", }); `, - options: ["all", { allowParensAfterComment: false }], + options: ["all", { allowParensAfterCommentPattern: "invalid" }], parserOptions: { ecmaVersion: 2020 }, errors: [{ messageId: "unexpected" }] }, @@ -3273,14 +3328,14 @@ ruleTester.run("no-extra-parens", rule, { options.server.options.requestCert = false; } `, - options: ["all", { allowParensAfterComment: false }], + options: ["all", { allowParensAfterCommentPattern: "invalid" }], parserOptions: { ecmaVersion: 2020 }, errors: [{ messageId: "unexpected" }] }, { code: "const net = ipaddr.parseCIDR(/** @type {string} */ (cidr));", output: "const net = ipaddr.parseCIDR(/** @type {string} */ cidr);", - options: ["all", { allowParensAfterComment: false }], + options: ["all", { allowParensAfterCommentPattern: "invalid" }], parserOptions: { ecmaVersion: 2020 }, errors: [{ messageId: "unexpected" }] }, From 58dff4dc1f59f51c6c9735fedc5ca2adb7566df0 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Sun, 20 Nov 2022 16:08:01 +0530 Subject: [PATCH 3/8] docs: add new `allowParensAfterCommentPattern` option to the `no-extra-parens` rule --- docs/src/rules/no-extra-parens.md | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/docs/src/rules/no-extra-parens.md b/docs/src/rules/no-extra-parens.md index d8108ceb99e..53baabd1faf 100644 --- a/docs/src/rules/no-extra-parens.md +++ b/docs/src/rules/no-extra-parens.md @@ -38,7 +38,7 @@ This rule has an object option for exceptions to the `"all"` option: * `"enforceForSequenceExpressions": false` allows extra parentheses around sequence expressions * `"enforceForNewInMemberExpressions": false` allows extra parentheses around `new` expressions in member expressions * `"enforceForFunctionPrototypeMethods": false` allows extra parentheses around immediate `.call` and `.apply` method calls on function expressions and around function expressions in the same context. -* `"allowParensAfterComment": true` allows extra parentheses preceded by a comment that matches a regular expression +* `"allowParensAfterCommentPattern": true` allows extra parentheses preceded by a comment that matches a regular expression. ### all @@ -323,6 +323,32 @@ const quux = (function () {}.apply()); ::: +### allowParensAfterCommentPattern + +Examples of **correct** code for this rule with the `"all"` and `{ "allowParensAfterCommentPattern": "@type" }` options: + +::: correct + +```js +/* eslint no-extra-parens: ["error", "all", { "enforceForFunctionPrototypeMethods": false }] */ + +const span = /**@type {HTMLSpanElement}*/(event.currentTarget); + +if (/** @type {Foo | Bar} */(options).baz) console.log('Lint free'); + +foo(/** @type {Bar} */ (bar), options, { + name: "name", + path: "path", +}); + +if (foo) { + /** @type {Bar} */ + (bar).prop = false; +} +``` + +::: + ### functions Examples of **incorrect** code for this rule with the `"functions"` option: From ee63b2a712827233845f567c31639f9125d96af3 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Sun, 20 Nov 2022 16:08:39 +0530 Subject: [PATCH 4/8] docs: add new `allowParensAfterCommentPattern` option to the `no-extra-parens` rule --- docs/src/rules/no-extra-parens.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/rules/no-extra-parens.md b/docs/src/rules/no-extra-parens.md index 53baabd1faf..e2756b99704 100644 --- a/docs/src/rules/no-extra-parens.md +++ b/docs/src/rules/no-extra-parens.md @@ -330,7 +330,7 @@ Examples of **correct** code for this rule with the `"all"` and `{ "allowParensA ::: correct ```js -/* eslint no-extra-parens: ["error", "all", { "enforceForFunctionPrototypeMethods": false }] */ +/* eslint no-extra-parens: ["error", "all", { "allowParensAfterCommentPattern": "@type" }] */ const span = /**@type {HTMLSpanElement}*/(event.currentTarget); From ab5a29dd55aa3c3ef0a6092e75d66b2ff0473923 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Sun, 20 Nov 2022 16:16:16 +0530 Subject: [PATCH 5/8] docs: add more information for `allowParensAfterCommentPattern` --- docs/src/rules/no-extra-parens.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/src/rules/no-extra-parens.md b/docs/src/rules/no-extra-parens.md index e2756b99704..9b1b8df0725 100644 --- a/docs/src/rules/no-extra-parens.md +++ b/docs/src/rules/no-extra-parens.md @@ -38,7 +38,7 @@ This rule has an object option for exceptions to the `"all"` option: * `"enforceForSequenceExpressions": false` allows extra parentheses around sequence expressions * `"enforceForNewInMemberExpressions": false` allows extra parentheses around `new` expressions in member expressions * `"enforceForFunctionPrototypeMethods": false` allows extra parentheses around immediate `.call` and `.apply` method calls on function expressions and around function expressions in the same context. -* `"allowParensAfterCommentPattern": true` allows extra parentheses preceded by a comment that matches a regular expression. +* `"allowParensAfterCommentPattern": "any-string-pattern"` allows extra parentheses preceded by a comment that matches a regular expression. ### all @@ -325,6 +325,8 @@ const quux = (function () {}.apply()); ### allowParensAfterCommentPattern +To make this rule allow extra parentheses preceded by specific comments, set this option to a string pattern that will be passed to the [`RegExp` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/RegExp). + Examples of **correct** code for this rule with the `"all"` and `{ "allowParensAfterCommentPattern": "@type" }` options: ::: correct From 9f718f262abd59949d07b164ab036c00d34c6647 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Sun, 20 Nov 2022 16:27:48 +0530 Subject: [PATCH 6/8] test: add another invalid case --- tests/lib/rules/no-extra-parens.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/lib/rules/no-extra-parens.js b/tests/lib/rules/no-extra-parens.js index 5412683c5bc..fdf2e276137 100644 --- a/tests/lib/rules/no-extra-parens.js +++ b/tests/lib/rules/no-extra-parens.js @@ -3332,6 +3332,25 @@ ruleTester.run("no-extra-parens", rule, { parserOptions: { ecmaVersion: 2020 }, errors: [{ messageId: "unexpected" }] }, + { + code: ` + if (condition) { + /** @type {ServerOptions} */ + /** extra coment */ + (options.server.options).requestCert = false; + } + `, + output: ` + if (condition) { + /** @type {ServerOptions} */ + /** extra coment */ + options.server.options.requestCert = false; + } + `, + options: ["all", { allowParensAfterCommentPattern: "@type" }], + parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpected" }] + }, { code: "const net = ipaddr.parseCIDR(/** @type {string} */ (cidr));", output: "const net = ipaddr.parseCIDR(/** @type {string} */ cidr);", From 660713040e196f38d4fdea6d4949cc6ceb3ad1b2 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Mon, 21 Nov 2022 19:38:23 +0530 Subject: [PATCH 7/8] refactor: remove extra condition Co-authored-by: Milos Djermanovic --- lib/rules/no-extra-parens.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rules/no-extra-parens.js b/lib/rules/no-extra-parens.js index 343a8b6ace8..75ac606ea74 100644 --- a/lib/rules/no-extra-parens.js +++ b/lib/rules/no-extra-parens.js @@ -405,7 +405,7 @@ module.exports = { return; } - if (ALLOW_PARENS_AFTER_COMMENT_PATTERN && isParenthesised(node)) { + if (ALLOW_PARENS_AFTER_COMMENT_PATTERN) { const commentsBeforeLeftParenToken = sourceCode.getCommentsBefore(leftParenToken); const totalCommentsBeforeLeftParenTokenCount = commentsBeforeLeftParenToken.length; const ignorePattern = new RegExp(ALLOW_PARENS_AFTER_COMMENT_PATTERN, "u"); From e29b72714c86a37bdbfe73eb7efbb92f13f1f278 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Thu, 24 Nov 2022 19:23:26 +0530 Subject: [PATCH 8/8] test: add more invalid cases --- tests/lib/rules/no-extra-parens.js | 60 +++++++++++++++++++----------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/tests/lib/rules/no-extra-parens.js b/tests/lib/rules/no-extra-parens.js index fdf2e276137..3f57e5b2958 100644 --- a/tests/lib/rules/no-extra-parens.js +++ b/tests/lib/rules/no-extra-parens.js @@ -744,13 +744,11 @@ ruleTester.run("no-extra-parens", rule, { // "allowParensAfterCommentPattern" option { code: "const span = /**@type {HTMLSpanElement}*/(event.currentTarget);", - options: ["all", { allowParensAfterCommentPattern: "@type" }], - parserOptions: { ecmaVersion: 2020 } + options: ["all", { allowParensAfterCommentPattern: "@type" }] }, { code: "if (/** @type {Compiler | MultiCompiler} */(options).hooks) console.log('good');", - options: ["all", { allowParensAfterCommentPattern: "@type" }], - parserOptions: { ecmaVersion: 2020 } + options: ["all", { allowParensAfterCommentPattern: "@type" }] }, { code: ` @@ -759,8 +757,7 @@ ruleTester.run("no-extra-parens", rule, { baseDataPath: "options", }); `, - options: ["all", { allowParensAfterCommentPattern: "@type" }], - parserOptions: { ecmaVersion: 2020 } + options: ["all", { allowParensAfterCommentPattern: "@type" }] }, { code: ` @@ -769,13 +766,11 @@ ruleTester.run("no-extra-parens", rule, { (options.server.options).requestCert = false; } `, - options: ["all", { allowParensAfterCommentPattern: "@type" }], - parserOptions: { ecmaVersion: 2020 } + options: ["all", { allowParensAfterCommentPattern: "@type" }] }, { code: "const net = ipaddr.parseCIDR(/** @type {string} */ (cidr));", - options: ["all", { allowParensAfterCommentPattern: "@type" }], - parserOptions: { ecmaVersion: 2020 } + options: ["all", { allowParensAfterCommentPattern: "@type" }] } ], @@ -3233,14 +3228,12 @@ ruleTester.run("no-extra-parens", rule, { code: "const span = /**@type {HTMLSpanElement}*/(event.currentTarget);", output: "const span = /**@type {HTMLSpanElement}*/event.currentTarget;", options: ["all"], - parserOptions: { ecmaVersion: 2020 }, errors: [{ messageId: "unexpected" }] }, { code: "if (/** @type {Compiler | MultiCompiler} */(options).hooks) console.log('good');", output: "if (/** @type {Compiler | MultiCompiler} */options.hooks) console.log('good');", options: ["all"], - parserOptions: { ecmaVersion: 2020 }, errors: [{ messageId: "unexpected" }] }, { @@ -3257,7 +3250,6 @@ ruleTester.run("no-extra-parens", rule, { }); `, options: ["all"], - parserOptions: { ecmaVersion: 2020 }, errors: [{ messageId: "unexpected" }] }, { @@ -3274,28 +3266,24 @@ ruleTester.run("no-extra-parens", rule, { } `, options: ["all"], - parserOptions: { ecmaVersion: 2020 }, errors: [{ messageId: "unexpected" }] }, { code: "const net = ipaddr.parseCIDR(/** @type {string} */ (cidr));", output: "const net = ipaddr.parseCIDR(/** @type {string} */ cidr);", options: ["all"], - parserOptions: { ecmaVersion: 2020 }, errors: [{ messageId: "unexpected" }] }, { code: "const span = /**@type {HTMLSpanElement}*/(event.currentTarget);", output: "const span = /**@type {HTMLSpanElement}*/event.currentTarget;", options: ["all", { allowParensAfterCommentPattern: "invalid" }], - parserOptions: { ecmaVersion: 2020 }, errors: [{ messageId: "unexpected" }] }, { code: "if (/** @type {Compiler | MultiCompiler} */(options).hooks) console.log('good');", output: "if (/** @type {Compiler | MultiCompiler} */options.hooks) console.log('good');", options: ["all", { allowParensAfterCommentPattern: "invalid" }], - parserOptions: { ecmaVersion: 2020 }, errors: [{ messageId: "unexpected" }] }, { @@ -3312,7 +3300,6 @@ ruleTester.run("no-extra-parens", rule, { }); `, options: ["all", { allowParensAfterCommentPattern: "invalid" }], - parserOptions: { ecmaVersion: 2020 }, errors: [{ messageId: "unexpected" }] }, { @@ -3329,7 +3316,6 @@ ruleTester.run("no-extra-parens", rule, { } `, options: ["all", { allowParensAfterCommentPattern: "invalid" }], - parserOptions: { ecmaVersion: 2020 }, errors: [{ messageId: "unexpected" }] }, { @@ -3348,14 +3334,46 @@ ruleTester.run("no-extra-parens", rule, { } `, options: ["all", { allowParensAfterCommentPattern: "@type" }], - parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpected" }] + }, + { + code: ` + if (condition) { + /** @type {ServerOptions} */ + ((options.server.options)).requestCert = false; + } + `, + output: ` + if (condition) { + /** @type {ServerOptions} */ + (options.server.options).requestCert = false; + } + `, + options: ["all", { allowParensAfterCommentPattern: "@type" }], + errors: [{ messageId: "unexpected" }] + }, + { + code: ` + if (condition) { + /** @type {ServerOptions} */ + let foo = "bar"; + (options.server.options).requestCert = false; + } + `, + output: ` + if (condition) { + /** @type {ServerOptions} */ + let foo = "bar"; + options.server.options.requestCert = false; + } + `, + options: ["all", { allowParensAfterCommentPattern: "@type" }], errors: [{ messageId: "unexpected" }] }, { code: "const net = ipaddr.parseCIDR(/** @type {string} */ (cidr));", output: "const net = ipaddr.parseCIDR(/** @type {string} */ cidr);", options: ["all", { allowParensAfterCommentPattern: "invalid" }], - parserOptions: { ecmaVersion: 2020 }, errors: [{ messageId: "unexpected" }] },