From ed08f815553c2bdcffc63cc38e2171cd2ea93413 Mon Sep 17 00:00:00 2001 From: Pavel Klibani Date: Wed, 23 Oct 2024 21:19:52 +0200 Subject: [PATCH] Fix(codemods): Fix bug with extra parentheses - codemods were adding extra parentheses to the code when there was return statement --- packages/codemods/src/helpers/index.ts | 3 +- .../codemods/src/helpers/removeParentheses.ts | 49 +++++++++++++++++++ .../button-isSquare-prop-name.input.tsx | 1 + .../button-isSquare-prop-name.output.tsx | 1 + .../buttonLink-isSquare-prop-name.input.tsx | 1 + .../buttonLink-isSquare-prop-name.output.tsx | 1 + .../heading-elementType-prop.input.tsx | 1 + .../heading-elementType-prop.output.tsx | 1 + .../link-underlined-prop.input.tsx | 18 ++++--- .../link-underlined-prop.output.tsx | 18 ++++--- .../toastbar-inverted-neutral.input.tsx | 1 + .../toastbar-inverted-neutral.output.tsx | 1 + .../v3/web-react/button-isSquare-prop-name.ts | 3 +- .../buttonLink-isSquare-prop-name.ts | 3 +- .../v3/web-react/heading-elementType-prop.ts | 3 +- .../link-hasVisitedStyleAllowed-prop.ts | 3 +- .../v3/web-react/link-underlined-prop.ts | 3 +- .../v3/web-react/toastbar-inverted-neutral.ts | 3 +- packages/codemods/tsconfig.json | 3 +- 19 files changed, 93 insertions(+), 24 deletions(-) create mode 100644 packages/codemods/src/helpers/removeParentheses.ts diff --git a/packages/codemods/src/helpers/index.ts b/packages/codemods/src/helpers/index.ts index 9f7bc11221..e451cbbd1e 100644 --- a/packages/codemods/src/helpers/index.ts +++ b/packages/codemods/src/helpers/index.ts @@ -1,4 +1,5 @@ import { errorMessage, infoMessage, logMessage } from './message'; import { _dirname } from './path'; +import { removeParentheses } from './removeParentheses'; -export { _dirname, errorMessage, infoMessage, logMessage }; +export { _dirname, errorMessage, infoMessage, logMessage, removeParentheses }; diff --git a/packages/codemods/src/helpers/removeParentheses.ts b/packages/codemods/src/helpers/removeParentheses.ts new file mode 100644 index 0000000000..0810cde5e1 --- /dev/null +++ b/packages/codemods/src/helpers/removeParentheses.ts @@ -0,0 +1,49 @@ +// This function removes circle brackets from the return statement in the JSX component. +// This bug is introduced by 'recast library' which is used by 'jscodeshift' library. +// There is pull request to fix this issue: https://github.com/benjamn/recast/pull/1406, but it is not merged yet. +// @see https://github.com/facebook/jscodeshift/issues/534 +// @todo Can be removed when the issue is fixed in the 'recast' library. + +const REG_RETURN = /return\s+\((\s+)\(<([^\s>]+)/g; + +export const removeParentheses = (string: string): string => { + const matches: IterableIterator = string.matchAll(REG_RETURN); + let result = ''; + + const allMatches = [...matches]; + if (allMatches.length === 0) return string; + + allMatches.forEach((match) => { + const [, spaces, componentName] = match; + const sl: number = spaces.length; + + const REG_DOUBLE_TAG = `(return\\s+\\(\\s{${sl}})\\((<${componentName}.+?\\s{${sl}}<\\/${componentName}>)\\)(\\s+\\))`; + const REG_SELF_CLOSING = `(return\\s+\\(\\s{${sl}})\\((<${componentName}.+?\\/>)\\)(\\s+\\))`; + const regexp = new RegExp(`${REG_DOUBLE_TAG}|${REG_SELF_CLOSING}`, 'gs'); + + result = string.replace( + regexp, + ( + match: string, // eslint-disable-line + doubleTagStart?: string, + doubleTagContent?: string, + doubleTagEnd?: string, + selfTagStart?: string, + selfTagContent?: string, + selfTagEnd?: string, + ): string => { + if (doubleTagStart && doubleTagContent && doubleTagEnd) { + return doubleTagStart + doubleTagContent + doubleTagEnd; + } + + if (selfTagStart && selfTagContent && selfTagEnd) { + return selfTagStart + selfTagContent + selfTagEnd; + } + + return match; + }, + ); + }); + + return result; +}; diff --git a/packages/codemods/src/transforms/v3/web-react/__testfixtures__/button-isSquare-prop-name.input.tsx b/packages/codemods/src/transforms/v3/web-react/__testfixtures__/button-isSquare-prop-name.input.tsx index 865de759f6..42d31866b1 100644 --- a/packages/codemods/src/transforms/v3/web-react/__testfixtures__/button-isSquare-prop-name.input.tsx +++ b/packages/codemods/src/transforms/v3/web-react/__testfixtures__/button-isSquare-prop-name.input.tsx @@ -1,3 +1,4 @@ +import React from 'react'; // @ts-ignore: No declaration -- The library is not installed; we don't need to install it for fixtures. import { Button } from '@lmc-eu/spirit-web-react'; diff --git a/packages/codemods/src/transforms/v3/web-react/__testfixtures__/button-isSquare-prop-name.output.tsx b/packages/codemods/src/transforms/v3/web-react/__testfixtures__/button-isSquare-prop-name.output.tsx index 17bed9b9b9..3f7cd9cae5 100644 --- a/packages/codemods/src/transforms/v3/web-react/__testfixtures__/button-isSquare-prop-name.output.tsx +++ b/packages/codemods/src/transforms/v3/web-react/__testfixtures__/button-isSquare-prop-name.output.tsx @@ -1,3 +1,4 @@ +import React from 'react'; // @ts-ignore: No declaration -- The library is not installed; we don't need to install it for fixtures. import { Button } from '@lmc-eu/spirit-web-react'; diff --git a/packages/codemods/src/transforms/v3/web-react/__testfixtures__/buttonLink-isSquare-prop-name.input.tsx b/packages/codemods/src/transforms/v3/web-react/__testfixtures__/buttonLink-isSquare-prop-name.input.tsx index faa8f68394..f3c5c5296b 100644 --- a/packages/codemods/src/transforms/v3/web-react/__testfixtures__/buttonLink-isSquare-prop-name.input.tsx +++ b/packages/codemods/src/transforms/v3/web-react/__testfixtures__/buttonLink-isSquare-prop-name.input.tsx @@ -1,3 +1,4 @@ +import React from 'react'; // @ts-ignore: No declaration -- The library is not installed; we don't need to install it for fixtures. import { ButtonLink } from '@lmc-eu/spirit-web-react'; diff --git a/packages/codemods/src/transforms/v3/web-react/__testfixtures__/buttonLink-isSquare-prop-name.output.tsx b/packages/codemods/src/transforms/v3/web-react/__testfixtures__/buttonLink-isSquare-prop-name.output.tsx index 2ab1b2d51d..fd6a131c0f 100644 --- a/packages/codemods/src/transforms/v3/web-react/__testfixtures__/buttonLink-isSquare-prop-name.output.tsx +++ b/packages/codemods/src/transforms/v3/web-react/__testfixtures__/buttonLink-isSquare-prop-name.output.tsx @@ -1,3 +1,4 @@ +import React from 'react'; // @ts-ignore: No declaration -- The library is not installed; we don't need to install it for fixtures. import { ButtonLink } from '@lmc-eu/spirit-web-react'; diff --git a/packages/codemods/src/transforms/v3/web-react/__testfixtures__/heading-elementType-prop.input.tsx b/packages/codemods/src/transforms/v3/web-react/__testfixtures__/heading-elementType-prop.input.tsx index 77d8fee5c7..48b4374a51 100644 --- a/packages/codemods/src/transforms/v3/web-react/__testfixtures__/heading-elementType-prop.input.tsx +++ b/packages/codemods/src/transforms/v3/web-react/__testfixtures__/heading-elementType-prop.input.tsx @@ -1,3 +1,4 @@ +import React from 'react'; // @ts-ignore: No declaration -- The library is not installed; we don't need to install it for fixtures. import { Heading } from '@lmc-eu/spirit-web-react'; diff --git a/packages/codemods/src/transforms/v3/web-react/__testfixtures__/heading-elementType-prop.output.tsx b/packages/codemods/src/transforms/v3/web-react/__testfixtures__/heading-elementType-prop.output.tsx index 9b03b15a4c..3da426f4bf 100644 --- a/packages/codemods/src/transforms/v3/web-react/__testfixtures__/heading-elementType-prop.output.tsx +++ b/packages/codemods/src/transforms/v3/web-react/__testfixtures__/heading-elementType-prop.output.tsx @@ -1,3 +1,4 @@ +import React from 'react'; // @ts-ignore: No declaration -- The library is not installed; we don't need to install it for fixtures. import { Heading } from '@lmc-eu/spirit-web-react'; diff --git a/packages/codemods/src/transforms/v3/web-react/__testfixtures__/link-underlined-prop.input.tsx b/packages/codemods/src/transforms/v3/web-react/__testfixtures__/link-underlined-prop.input.tsx index 90af8e3291..a2fc3cd974 100644 --- a/packages/codemods/src/transforms/v3/web-react/__testfixtures__/link-underlined-prop.input.tsx +++ b/packages/codemods/src/transforms/v3/web-react/__testfixtures__/link-underlined-prop.input.tsx @@ -2,11 +2,13 @@ import React from 'react'; // @ts-ignore: No declaration -- The library is not installed; we don't need to install it for fixtures. import { Link } from '@lmc-eu/spirit-web-react'; -export const MyComponent = () => ( - <> - - - - - -); +export const MyComponent = () => { + return ( +
+ + + + +
+ ); +}; diff --git a/packages/codemods/src/transforms/v3/web-react/__testfixtures__/link-underlined-prop.output.tsx b/packages/codemods/src/transforms/v3/web-react/__testfixtures__/link-underlined-prop.output.tsx index 35c1fbb249..3ae1ad5821 100644 --- a/packages/codemods/src/transforms/v3/web-react/__testfixtures__/link-underlined-prop.output.tsx +++ b/packages/codemods/src/transforms/v3/web-react/__testfixtures__/link-underlined-prop.output.tsx @@ -2,11 +2,13 @@ import React from 'react'; // @ts-ignore: No declaration -- The library is not installed; we don't need to install it for fixtures. import { Link } from '@lmc-eu/spirit-web-react'; -export const MyComponent = () => ( - <> - - - - - -); +export const MyComponent = () => { + return ( +
+ + + + +
+ ); +}; diff --git a/packages/codemods/src/transforms/v3/web-react/__testfixtures__/toastbar-inverted-neutral.input.tsx b/packages/codemods/src/transforms/v3/web-react/__testfixtures__/toastbar-inverted-neutral.input.tsx index 5e4249ea01..faf169599d 100644 --- a/packages/codemods/src/transforms/v3/web-react/__testfixtures__/toastbar-inverted-neutral.input.tsx +++ b/packages/codemods/src/transforms/v3/web-react/__testfixtures__/toastbar-inverted-neutral.input.tsx @@ -1,3 +1,4 @@ +import React from 'react'; // @ts-ignore: No declaration -- The library is not installed; we don't need to install it for fixtures. import { ToastBar } from '@lmc-eu/spirit-web-react'; diff --git a/packages/codemods/src/transforms/v3/web-react/__testfixtures__/toastbar-inverted-neutral.output.tsx b/packages/codemods/src/transforms/v3/web-react/__testfixtures__/toastbar-inverted-neutral.output.tsx index fefa506eb0..d0a191ef2d 100644 --- a/packages/codemods/src/transforms/v3/web-react/__testfixtures__/toastbar-inverted-neutral.output.tsx +++ b/packages/codemods/src/transforms/v3/web-react/__testfixtures__/toastbar-inverted-neutral.output.tsx @@ -1,3 +1,4 @@ +import React from 'react'; // @ts-ignore: No declaration -- The library is not installed; we don't need to install it for fixtures. import { ToastBar } from '@lmc-eu/spirit-web-react'; diff --git a/packages/codemods/src/transforms/v3/web-react/button-isSquare-prop-name.ts b/packages/codemods/src/transforms/v3/web-react/button-isSquare-prop-name.ts index 8cc5de70f0..f2ed23eb87 100644 --- a/packages/codemods/src/transforms/v3/web-react/button-isSquare-prop-name.ts +++ b/packages/codemods/src/transforms/v3/web-react/button-isSquare-prop-name.ts @@ -1,4 +1,5 @@ import { API, FileInfo } from 'jscodeshift'; +import { removeParentheses } from '../../../helpers'; const transform = (fileInfo: FileInfo, api: API) => { const j = api.jscodeshift; @@ -44,7 +45,7 @@ const transform = (fileInfo: FileInfo, api: API) => { } } - return root.toSource(); + return removeParentheses(root.toSource()); }; export default transform; diff --git a/packages/codemods/src/transforms/v3/web-react/buttonLink-isSquare-prop-name.ts b/packages/codemods/src/transforms/v3/web-react/buttonLink-isSquare-prop-name.ts index 0f5da0116c..3851325d99 100644 --- a/packages/codemods/src/transforms/v3/web-react/buttonLink-isSquare-prop-name.ts +++ b/packages/codemods/src/transforms/v3/web-react/buttonLink-isSquare-prop-name.ts @@ -1,4 +1,5 @@ import { API, FileInfo } from 'jscodeshift'; +import { removeParentheses } from '../../../helpers'; const transform = (fileInfo: FileInfo, api: API) => { const j = api.jscodeshift; @@ -44,7 +45,7 @@ const transform = (fileInfo: FileInfo, api: API) => { } } - return root.toSource(); + return removeParentheses(root.toSource()); }; export default transform; diff --git a/packages/codemods/src/transforms/v3/web-react/heading-elementType-prop.ts b/packages/codemods/src/transforms/v3/web-react/heading-elementType-prop.ts index 1f6d8a65f6..2247d84520 100644 --- a/packages/codemods/src/transforms/v3/web-react/heading-elementType-prop.ts +++ b/packages/codemods/src/transforms/v3/web-react/heading-elementType-prop.ts @@ -1,4 +1,5 @@ import { API, FileInfo } from 'jscodeshift'; +import { removeParentheses } from '../../../helpers'; const transform = (fileInfo: FileInfo, api: API) => { const j = api.jscodeshift; @@ -43,7 +44,7 @@ const transform = (fileInfo: FileInfo, api: API) => { } } - return root.toSource(); + return removeParentheses(root.toSource()); }; export default transform; diff --git a/packages/codemods/src/transforms/v3/web-react/link-hasVisitedStyleAllowed-prop.ts b/packages/codemods/src/transforms/v3/web-react/link-hasVisitedStyleAllowed-prop.ts index afe4bb059c..377afdbd29 100644 --- a/packages/codemods/src/transforms/v3/web-react/link-hasVisitedStyleAllowed-prop.ts +++ b/packages/codemods/src/transforms/v3/web-react/link-hasVisitedStyleAllowed-prop.ts @@ -1,4 +1,5 @@ import { API, FileInfo } from 'jscodeshift'; +import { removeParentheses } from '../../../helpers'; const transform = (fileInfo: FileInfo, api: API) => { const j = api.jscodeshift; @@ -42,7 +43,7 @@ const transform = (fileInfo: FileInfo, api: API) => { } } - return root.toSource(); + return removeParentheses(root.toSource()); }; export default transform; diff --git a/packages/codemods/src/transforms/v3/web-react/link-underlined-prop.ts b/packages/codemods/src/transforms/v3/web-react/link-underlined-prop.ts index 608fced2e3..b859f3f0b1 100644 --- a/packages/codemods/src/transforms/v3/web-react/link-underlined-prop.ts +++ b/packages/codemods/src/transforms/v3/web-react/link-underlined-prop.ts @@ -8,6 +8,7 @@ import { ImportDeclaration, JSXOpeningElement, } from 'jscodeshift'; +import { removeParentheses } from '../../../helpers'; const transform = (fileInfo: FileInfo, api: API): string => { const j: JSCodeshift = api.jscodeshift; @@ -61,7 +62,7 @@ const transform = (fileInfo: FileInfo, api: API): string => { }); } - return root.toSource(); + return removeParentheses(root.toSource()); }; export default transform; diff --git a/packages/codemods/src/transforms/v3/web-react/toastbar-inverted-neutral.ts b/packages/codemods/src/transforms/v3/web-react/toastbar-inverted-neutral.ts index 24a6e23c7e..833c63da43 100644 --- a/packages/codemods/src/transforms/v3/web-react/toastbar-inverted-neutral.ts +++ b/packages/codemods/src/transforms/v3/web-react/toastbar-inverted-neutral.ts @@ -1,4 +1,5 @@ import { API, FileInfo } from 'jscodeshift'; +import { removeParentheses } from '../../../helpers'; const transform = (fileInfo: FileInfo, api: API) => { const j = api.jscodeshift; @@ -46,7 +47,7 @@ const transform = (fileInfo: FileInfo, api: API) => { } } - return root.toSource(); + return removeParentheses(root.toSource()); }; export default transform; diff --git a/packages/codemods/tsconfig.json b/packages/codemods/tsconfig.json index 893379463b..81aa57037d 100644 --- a/packages/codemods/tsconfig.json +++ b/packages/codemods/tsconfig.json @@ -25,7 +25,8 @@ "skipLibCheck": true, "typeRoots": ["../../node_modules/@types"], "types": ["node", "jest"], - "module": "es2020" + "module": "es2020", + "target": "es2020" }, "include": ["./", "./.eslintrc.js"], "exclude": ["./node_modules", "**/__testfixtures__/**"]