diff --git a/CHANGELOG.md b/CHANGELOG.md index 77c643af0e..8514858751 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange * [Refactor] [`no-deprecated`]: improve performance ([#3271][] @golopot) * [Refactor] [`no-did-mount-set-state`], [`no-did-update-set-state`], [`no-will-update-set-state`]: improve performance ([#3272][] @golopot) * [Refactor] improve performance by avoiding unnecessary `Components.detect` ([#3273][] @golopot) +* [Refactor] add `isParenthesized` AST util ([#3203][] @Belco90) [#3273]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3273 [#3272]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3272 @@ -39,6 +40,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange [#3258]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3258 [#3254]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3254 [#3251]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3251 +[#3203]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3203 [#3248]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3248 [#3244]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3244 [#3235]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3235 diff --git a/lib/rules/jsx-wrap-multilines.js b/lib/rules/jsx-wrap-multilines.js index 94600efa61..f865cb970a 100644 --- a/lib/rules/jsx-wrap-multilines.js +++ b/lib/rules/jsx-wrap-multilines.js @@ -9,6 +9,7 @@ const has = require('object.hasown/polyfill')(); const docsUrl = require('../util/docsUrl'); const jsxUtil = require('../util/jsx'); const reportC = require('../util/report'); +const isParenthesized = require('../util/ast').isParenthesized; // ------------------------------------------------------------------------------ // Constants @@ -89,20 +90,10 @@ module.exports = { return option && option !== 'ignore'; } - function isParenthesised(node) { - const sourceCode = context.getSourceCode(); - const previousToken = sourceCode.getTokenBefore(node); - const nextToken = sourceCode.getTokenAfter(node); - - return previousToken && nextToken - && previousToken.value === '(' && previousToken.range[1] <= node.range[0] - && nextToken.value === ')' && nextToken.range[0] >= node.range[1]; - } - function needsOpeningNewLine(node) { const previousToken = context.getSourceCode().getTokenBefore(node); - if (!isParenthesised(node)) { + if (!isParenthesized(context, node)) { return false; } @@ -116,7 +107,7 @@ module.exports = { function needsClosingNewLine(node) { const nextToken = context.getSourceCode().getTokenAfter(node); - if (!isParenthesised(node)) { + if (!isParenthesized(context, node)) { return false; } @@ -153,12 +144,12 @@ module.exports = { const sourceCode = context.getSourceCode(); const option = getOption(type); - if ((option === true || option === 'parens') && !isParenthesised(node) && isMultilines(node)) { + if ((option === true || option === 'parens') && !isParenthesized(context, node) && isMultilines(node)) { report(node, 'missingParens', (fixer) => fixer.replaceText(node, `(${sourceCode.getText(node)})`)); } if (option === 'parens-new-line' && isMultilines(node)) { - if (!isParenthesised(node)) { + if (!isParenthesized(context, node)) { const tokenBefore = sourceCode.getTokenBefore(node, { includeComments: true }); const tokenAfter = sourceCode.getTokenAfter(node, { includeComments: true }); const start = node.loc.start; diff --git a/lib/util/ast.js b/lib/util/ast.js index d25cab4630..596ae9fdaf 100644 --- a/lib/util/ast.js +++ b/lib/util/ast.js @@ -294,6 +294,23 @@ function getKeyValue(context, node) { return key.type === 'Identifier' ? key.name : key.value; } +/** + * Checks if a node is surrounded by parenthesis. + * + * @param {object} context - Context from the rule + * @param {ASTNode} node - Node to be checked + * @returns {boolean} + */ +function isParenthesized(context, node) { + const sourceCode = context.getSourceCode(); + const previousToken = sourceCode.getTokenBefore(node); + const nextToken = sourceCode.getTokenAfter(node); + + return !!previousToken && !!nextToken + && previousToken.value === '(' && previousToken.range[1] <= node.range[0] + && nextToken.value === ')' && nextToken.range[0] >= node.range[1]; +} + /** * Checks if a node is being assigned a value: props.bar = 'bar' * @param {ASTNode} node The AST node being checked. @@ -410,6 +427,7 @@ module.exports = { getPropertyNameNode, getComponentProperties, getKeyValue, + isParenthesized, isAssignmentLHS, isClass, isFunction,