From f72505474928a7b2548dae1d8b91bf5da881a2c5 Mon Sep 17 00:00:00 2001 From: adamviktora Date: Mon, 4 Nov 2024 13:14:21 +0100 Subject: [PATCH 1/6] chore: add @typescript-eslint/utils package --- .../eslint-plugin-pf-codemods/package.json | 3 +- yarn.lock | 79 ++++++++++++++++++- 2 files changed, 79 insertions(+), 3 deletions(-) diff --git a/packages/eslint-plugin-pf-codemods/package.json b/packages/eslint-plugin-pf-codemods/package.json index 13d6a9d86..119dc1716 100644 --- a/packages/eslint-plugin-pf-codemods/package.json +++ b/packages/eslint-plugin-pf-codemods/package.json @@ -24,6 +24,7 @@ }, "devDependencies": { "@types/eslint": "^8.56.0", - "@types/estree-jsx": "^1.0.4" + "@types/estree-jsx": "^1.0.4", + "@typescript-eslint/utils": "^8.12.2" } } diff --git a/yarn.lock b/yarn.lock index 2170e7d47..9b87ce4c0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -37,6 +37,13 @@ dependencies: eslint-visitor-keys "^3.3.0" +"@eslint-community/eslint-utils@^4.4.0": + version "4.4.1" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz#d1145bf2c20132d6400495d6df4bf59362fd9d56" + integrity sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA== + dependencies: + eslint-visitor-keys "^3.4.3" + "@eslint-community/regexpp@^4.4.0": version "4.5.0" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.5.0.tgz#f6f729b02feee2c749f57e334b7a1b5f40a81724" @@ -1169,11 +1176,24 @@ "@typescript-eslint/types" "7.3.1" "@typescript-eslint/visitor-keys" "7.3.1" +"@typescript-eslint/scope-manager@8.12.2": + version "8.12.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.12.2.tgz#6db0213745e6392c8e90fe9af5915e6da32eb94a" + integrity sha512-gPLpLtrj9aMHOvxJkSbDBmbRuYdtiEbnvO25bCMza3DhMjTQw0u7Y1M+YR5JPbMsXXnSPuCf5hfq0nEkQDL/JQ== + dependencies: + "@typescript-eslint/types" "8.12.2" + "@typescript-eslint/visitor-keys" "8.12.2" + "@typescript-eslint/types@7.3.1": version "7.3.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.3.1.tgz#ae104de8efa4227a462c0874d856602c5994413c" integrity sha512-2tUf3uWggBDl4S4183nivWQ2HqceOZh1U4hhu4p1tPiIJoRRXrab7Y+Y0p+dozYwZVvLPRI6r5wKe9kToF9FIw== +"@typescript-eslint/types@8.12.2": + version "8.12.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.12.2.tgz#8d70098c0e90442495b53d0296acdca6d0f3f73c" + integrity sha512-VwDwMF1SZ7wPBUZwmMdnDJ6sIFk4K4s+ALKLP6aIQsISkPv8jhiw65sAK6SuWODN/ix+m+HgbYDkH+zLjrzvOA== + "@typescript-eslint/typescript-estree@7.3.1": version "7.3.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.3.1.tgz#598848195fad34c7aa73f548bd00a4d4e5f5e2bb" @@ -1188,6 +1208,30 @@ semver "^7.5.4" ts-api-utils "^1.0.1" +"@typescript-eslint/typescript-estree@8.12.2": + version "8.12.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.12.2.tgz#206df9b1cbff212aaa9401985ef99f04daa84da5" + integrity sha512-mME5MDwGe30Pq9zKPvyduyU86PH7aixwqYR2grTglAdB+AN8xXQ1vFGpYaUSJ5o5P/5znsSBeNcs5g5/2aQwow== + dependencies: + "@typescript-eslint/types" "8.12.2" + "@typescript-eslint/visitor-keys" "8.12.2" + debug "^4.3.4" + fast-glob "^3.3.2" + is-glob "^4.0.3" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^1.3.0" + +"@typescript-eslint/utils@^8.12.2": + version "8.12.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.12.2.tgz#726cc9f49f5866605bd15bbc1768ffc15637930e" + integrity sha512-UTTuDIX3fkfAz6iSVa5rTuSfWIYZ6ATtEocQ/umkRSyC9O919lbZ8dcH7mysshrCdrAM03skJOEYaBugxN+M6A== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@typescript-eslint/scope-manager" "8.12.2" + "@typescript-eslint/types" "8.12.2" + "@typescript-eslint/typescript-estree" "8.12.2" + "@typescript-eslint/visitor-keys@7.3.1": version "7.3.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.3.1.tgz#6ddef14a3ce2a79690f01176f5305c34d7b93d8c" @@ -1196,6 +1240,14 @@ "@typescript-eslint/types" "7.3.1" eslint-visitor-keys "^3.4.1" +"@typescript-eslint/visitor-keys@8.12.2": + version "8.12.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.12.2.tgz#94d7410f78eb6d134b9fcabaf1eeedb910ba8c38" + integrity sha512-PChz8UaKQAVNHghsHcPyx1OMHoFRUEA7rJSK/mDhdq85bk+PLsUHUBqTQTFt18VJZbmxBovM65fezlheQRsSDA== + dependencies: + "@typescript-eslint/types" "8.12.2" + eslint-visitor-keys "^3.4.3" + "@zkochan/cmd-shim@^3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@zkochan/cmd-shim/-/cmd-shim-3.1.0.tgz#2ab8ed81f5bb5452a85f25758eb9b8681982fd2e" @@ -2604,7 +2656,7 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz#c7f0f956124ce677047ddbc192a68f999454dedc" integrity sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ== -eslint-visitor-keys@^3.4.1: +eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: version "3.4.3" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== @@ -2822,6 +2874,17 @@ fast-glob@^3.2.11, fast-glob@^3.2.9: merge2 "^1.3.0" micromatch "^4.0.4" +fast-glob@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -4583,6 +4646,13 @@ minimatch@^9.0.1: dependencies: brace-expansion "^2.0.1" +minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + minimist-options@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954" @@ -6012,6 +6082,11 @@ semver@^7.5.4: dependencies: lru-cache "^6.0.0" +semver@^7.6.0: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + sentence-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/sentence-case/-/sentence-case-3.0.4.tgz#3645a7b8c117c787fde8702056225bb62a45131f" @@ -6682,7 +6757,7 @@ trim-off-newlines@^1.0.0: resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.3.tgz#8df24847fcb821b0ab27d58ab6efec9f2fe961a1" integrity sha512-kh6Tu6GbeSNMGfrrZh6Bb/4ZEHV1QlB4xNDBeog8Y9/QwFlKTRyWvY3Fs9tRDAMZliVUwieMgEdIeL/FtqjkJg== -ts-api-utils@^1.0.1: +ts-api-utils@^1.0.1, ts-api-utils@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== From 91aaa1bc191f001034af4766aa9db0313bf45a62 Mon Sep 17 00:00:00 2001 From: adamviktora Date: Mon, 4 Nov 2024 13:15:07 +0100 Subject: [PATCH 2/6] feat(helpers): renameInterface helper --- .../src/rules/helpers/index.ts | 2 + .../src/rules/helpers/renameInterface.ts | 77 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/helpers/renameInterface.ts diff --git a/packages/eslint-plugin-pf-codemods/src/rules/helpers/index.ts b/packages/eslint-plugin-pf-codemods/src/rules/helpers/index.ts index 4770ebeec..a4661bb9a 100644 --- a/packages/eslint-plugin-pf-codemods/src/rules/helpers/index.ts +++ b/packages/eslint-plugin-pf-codemods/src/rules/helpers/index.ts @@ -31,4 +31,6 @@ export * from "./pfPackageMatches"; export * from "./removeElement"; export * from "./removeEmptyLineAfter"; export * from "./removePropertiesFromObjectExpression"; +export * from "./renameComponent"; +export * from "./renameInterface"; export * from "./renameProps"; diff --git a/packages/eslint-plugin-pf-codemods/src/rules/helpers/renameInterface.ts b/packages/eslint-plugin-pf-codemods/src/rules/helpers/renameInterface.ts new file mode 100644 index 000000000..3d3493caa --- /dev/null +++ b/packages/eslint-plugin-pf-codemods/src/rules/helpers/renameInterface.ts @@ -0,0 +1,77 @@ +import { Rule } from "eslint"; +import { TSESTree } from "@typescript-eslint/utils"; +import { Identifier, ImportSpecifier, Node } from "estree-jsx"; +import { getFromPackage } from "./getFromPackage"; + +interface InterfaceRenames { + [currentName: string]: string; +} + +function formatDefaultMessage(oldName: string, newName: string) { + return `${oldName} has been renamed to ${newName}.`; +} + +export function renameInterface( + renames: InterfaceRenames, + packageName = "@patternfly/react-core" +) { + return function (context: Rule.RuleContext) { + const oldNames = Object.keys(renames); + const { imports } = getFromPackage(context, packageName, oldNames); + + if (imports.length === 0) { + return {}; + } + + return { + ImportSpecifier(node: ImportSpecifier) { + if ( + !imports.some( + (specifier) => specifier.imported.name === node.imported.name + ) + ) { + return; + } + + const oldName = node.imported.name; + const newName = renames[oldName]; + + context.report({ + node, + message: formatDefaultMessage(oldName, newName), + fix(fixer) { + return fixer.replaceText(node.imported, newName); + }, + }); + }, + TSTypeReference(node: TSESTree.TSTypeReference) { + const getMatchingImport = (name: string) => + imports.find((specifier) => specifier.local.name === name); + + if (node.typeName.type !== "Identifier") { + return; + } + + const matchingImport = getMatchingImport(node.typeName.name); + const shouldRename = + matchingImport && + matchingImport.local.name === matchingImport.imported.name; + + if (!shouldRename) { + return; + } + + const oldName = node.typeName.name; + const newName = renames[oldName]; + + context.report({ + node: node as unknown as Node, + message: formatDefaultMessage(oldName, newName), + fix(fixer) { + return fixer.replaceText(node.typeName as Identifier, newName); + }, + }); + }, + }; + }; +} From a4ead58bc85ab2400463acd85458f985fc489e7e Mon Sep 17 00:00:00 2001 From: adamviktora Date: Mon, 4 Nov 2024 13:16:21 +0100 Subject: [PATCH 3/6] feat(componentGroups): InvalidObjectProps rename to MissingPageProps --- ...dObjectProps-rename-to-missingPageProps.md | 18 ++++ ...ctProps-rename-to-missingPageProps.test.ts | 85 +++++++++++++++++++ ...dObjectProps-rename-to-missingPageProps.ts | 12 +++ ...jectPropsRenameToMissingPagePropsInput.tsx | 3 + ...ectPropsRenameToMissingPagePropsOutput.tsx | 3 + 5 files changed, 121 insertions(+) create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/component-groups-invalidObjectProps-rename-to-missingPageProps.md create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/component-groups-invalidObjectProps-rename-to-missingPageProps.test.ts create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/component-groups-invalidObjectProps-rename-to-missingPageProps.ts create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/componentGroupsInvalidObjectPropsRenameToMissingPagePropsInput.tsx create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/componentGroupsInvalidObjectPropsRenameToMissingPagePropsOutput.tsx diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/component-groups-invalidObjectProps-rename-to-missingPageProps.md b/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/component-groups-invalidObjectProps-rename-to-missingPageProps.md new file mode 100644 index 000000000..2094e6aa3 --- /dev/null +++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/component-groups-invalidObjectProps-rename-to-missingPageProps.md @@ -0,0 +1,18 @@ +### component-groups-invalidObjectProps-rename-to-missingPageProps [(react-component-groups/#313)](https://github.com/patternfly/react-component-groups/pull/313) + +In react-component-groups, we've renamed InvalidObjectProps interface to MissingPageProps + +#### Examples + +In: + +```jsx +%inputExample% +``` + +Out: + +```jsx +%outputExample% +``` + diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/component-groups-invalidObjectProps-rename-to-missingPageProps.test.ts b/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/component-groups-invalidObjectProps-rename-to-missingPageProps.test.ts new file mode 100644 index 000000000..ff08d46ef --- /dev/null +++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/component-groups-invalidObjectProps-rename-to-missingPageProps.test.ts @@ -0,0 +1,85 @@ +const ruleTester = require("../../ruletester"); +import * as rule from "./component-groups-invalidObjectProps-rename-to-missingPageProps"; + +ruleTester.run( + "component-groups-invalidObjectProps-rename-to-missingPageProps", + rule, + { + valid: [ + // missing import + { + code: `const props: InvalidObjectProps;`, + }, + // import from wrong package + { + code: `import { InvalidObjectProps } from '@patternfly/react-core';`, + }, + ], + invalid: [ + { + code: `import { InvalidObjectProps } from '@patternfly/react-component-groups'; + const props: InvalidObjectProps; + const otherProps = props as InvalidObjectProps;`, + output: `import { MissingPageProps } from '@patternfly/react-component-groups'; + const props: MissingPageProps; + const otherProps = props as MissingPageProps;`, + errors: [ + { + message: `InvalidObjectProps has been renamed to MissingPageProps.`, + type: "ImportSpecifier", + }, + { + message: `InvalidObjectProps has been renamed to MissingPageProps.`, + type: "TSTypeReference", + }, + { + message: `InvalidObjectProps has been renamed to MissingPageProps.`, + type: "TSTypeReference", + }, + ], + }, + // named import with alias + { + code: `import { InvalidObjectProps as InvObjProps } from '@patternfly/react-component-groups';`, + output: `import { MissingPageProps as InvObjProps } from '@patternfly/react-component-groups';`, + errors: [ + { + message: `InvalidObjectProps has been renamed to MissingPageProps.`, + type: "ImportSpecifier", + }, + ], + }, + // imports from dist + { + code: `import { InvalidObjectProps } from '@patternfly/react-component-groups/dist/cjs/InvalidObject';`, + output: `import { MissingPageProps } from '@patternfly/react-component-groups/dist/cjs/InvalidObject';`, + errors: [ + { + message: `InvalidObjectProps has been renamed to MissingPageProps.`, + type: "ImportSpecifier", + }, + ], + }, + { + code: `import { InvalidObjectProps } from '@patternfly/react-component-groups/dist/esm/InvalidObject';`, + output: `import { MissingPageProps } from '@patternfly/react-component-groups/dist/esm/InvalidObject';`, + errors: [ + { + message: `InvalidObjectProps has been renamed to MissingPageProps.`, + type: "ImportSpecifier", + }, + ], + }, + { + code: `import { InvalidObjectProps } from '@patternfly/react-component-groups/dist/dynamic/InvalidObject';`, + output: `import { MissingPageProps } from '@patternfly/react-component-groups/dist/dynamic/InvalidObject';`, + errors: [ + { + message: `InvalidObjectProps has been renamed to MissingPageProps.`, + type: "ImportSpecifier", + }, + ], + }, + ], + } +); diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/component-groups-invalidObjectProps-rename-to-missingPageProps.ts b/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/component-groups-invalidObjectProps-rename-to-missingPageProps.ts new file mode 100644 index 000000000..7ca2a9d94 --- /dev/null +++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/component-groups-invalidObjectProps-rename-to-missingPageProps.ts @@ -0,0 +1,12 @@ +import { renameInterface } from "../../helpers"; + +// https://github.com/patternfly/react-component-groups/pull/313 +module.exports = { + meta: { fixable: "code" }, + create: renameInterface( + { + InvalidObjectProps: "MissingPageProps", + }, + "@patternfly/react-component-groups" + ), +}; diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/componentGroupsInvalidObjectPropsRenameToMissingPagePropsInput.tsx b/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/componentGroupsInvalidObjectPropsRenameToMissingPagePropsInput.tsx new file mode 100644 index 000000000..c4e076e62 --- /dev/null +++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/componentGroupsInvalidObjectPropsRenameToMissingPagePropsInput.tsx @@ -0,0 +1,3 @@ +import { InvalidObjectProps } from "@patternfly/react-component-groups"; + +const props: InvalidObjectProps; diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/componentGroupsInvalidObjectPropsRenameToMissingPagePropsOutput.tsx b/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/componentGroupsInvalidObjectPropsRenameToMissingPagePropsOutput.tsx new file mode 100644 index 000000000..5ee805698 --- /dev/null +++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/componentGroupsInvalidObjectPropsRenameToMissingPagePropsOutput.tsx @@ -0,0 +1,3 @@ +import { MissingPageProps } from "@patternfly/react-component-groups"; + +const props: MissingPageProps; From b16ab25535b729a0ab8e48150f03d8410b9ceba2 Mon Sep 17 00:00:00 2001 From: adamviktora Date: Mon, 4 Nov 2024 17:09:37 +0100 Subject: [PATCH 4/6] fix(renameInterface helper): add TSInterfaceHeritage --- .../src/rules/helpers/renameInterface.ts | 55 +++++++++++-------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/packages/eslint-plugin-pf-codemods/src/rules/helpers/renameInterface.ts b/packages/eslint-plugin-pf-codemods/src/rules/helpers/renameInterface.ts index 3d3493caa..c5475aa38 100644 --- a/packages/eslint-plugin-pf-codemods/src/rules/helpers/renameInterface.ts +++ b/packages/eslint-plugin-pf-codemods/src/rules/helpers/renameInterface.ts @@ -23,6 +23,31 @@ export function renameInterface( return {}; } + const replaceIdentifier = (identifier: Identifier) => { + const getMatchingImport = (name: string) => + imports.find((specifier) => specifier.local.name === name); + + const matchingImport = getMatchingImport(identifier.name); + const shouldRename = + matchingImport && + matchingImport.local.name === matchingImport.imported.name; + + if (!shouldRename) { + return; + } + + const oldName = identifier.name; + const newName = renames[oldName]; + + context.report({ + node: identifier, + message: formatDefaultMessage(oldName, newName), + fix(fixer) { + return fixer.replaceText(identifier, newName); + }, + }); + }; + return { ImportSpecifier(node: ImportSpecifier) { if ( @@ -45,32 +70,14 @@ export function renameInterface( }); }, TSTypeReference(node: TSESTree.TSTypeReference) { - const getMatchingImport = (name: string) => - imports.find((specifier) => specifier.local.name === name); - - if (node.typeName.type !== "Identifier") { - return; + if (node.typeName.type === "Identifier") { + replaceIdentifier(node.typeName); } - - const matchingImport = getMatchingImport(node.typeName.name); - const shouldRename = - matchingImport && - matchingImport.local.name === matchingImport.imported.name; - - if (!shouldRename) { - return; + }, + TSInterfaceHeritage(node: TSESTree.TSInterfaceHeritage) { + if (node.expression.type === "Identifier") { + replaceIdentifier(node.expression); } - - const oldName = node.typeName.name; - const newName = renames[oldName]; - - context.report({ - node: node as unknown as Node, - message: formatDefaultMessage(oldName, newName), - fix(fixer) { - return fixer.replaceText(node.typeName as Identifier, newName); - }, - }); }, }; }; From 2d4b3d2ae71d98c90b6ef0063e78b4574d1cf0d5 Mon Sep 17 00:00:00 2001 From: adamviktora Date: Mon, 4 Nov 2024 17:10:30 +0100 Subject: [PATCH 5/6] feat(componentGroups mod): add interface example --- ...ctProps-rename-to-missingPageProps.test.ts | 36 ++++++++++++------- ...jectPropsRenameToMissingPagePropsInput.tsx | 1 + ...ectPropsRenameToMissingPagePropsOutput.tsx | 1 + 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/component-groups-invalidObjectProps-rename-to-missingPageProps.test.ts b/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/component-groups-invalidObjectProps-rename-to-missingPageProps.test.ts index ff08d46ef..91774249a 100644 --- a/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/component-groups-invalidObjectProps-rename-to-missingPageProps.test.ts +++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/component-groups-invalidObjectProps-rename-to-missingPageProps.test.ts @@ -1,6 +1,8 @@ const ruleTester = require("../../ruletester"); import * as rule from "./component-groups-invalidObjectProps-rename-to-missingPageProps"; +const message = `InvalidObjectProps has been renamed to MissingPageProps.`; + ruleTester.run( "component-groups-invalidObjectProps-rename-to-missingPageProps", rule, @@ -19,32 +21,40 @@ ruleTester.run( { code: `import { InvalidObjectProps } from '@patternfly/react-component-groups'; const props: InvalidObjectProps; - const otherProps = props as InvalidObjectProps;`, + const otherProps = props as InvalidObjectProps; + interface CustomProps extends InvalidObjectProps {};`, output: `import { MissingPageProps } from '@patternfly/react-component-groups'; const props: MissingPageProps; - const otherProps = props as MissingPageProps;`, + const otherProps = props as MissingPageProps; + interface CustomProps extends MissingPageProps {};`, errors: [ { - message: `InvalidObjectProps has been renamed to MissingPageProps.`, + message, type: "ImportSpecifier", }, { - message: `InvalidObjectProps has been renamed to MissingPageProps.`, - type: "TSTypeReference", + message, + type: "Identifier", + }, + { + message, + type: "Identifier", }, { - message: `InvalidObjectProps has been renamed to MissingPageProps.`, - type: "TSTypeReference", + message, + type: "Identifier", }, ], }, // named import with alias { - code: `import { InvalidObjectProps as InvObjProps } from '@patternfly/react-component-groups';`, - output: `import { MissingPageProps as InvObjProps } from '@patternfly/react-component-groups';`, + code: `import { InvalidObjectProps as InvObjProps } from '@patternfly/react-component-groups'; + const props: InvObjProps;`, + output: `import { MissingPageProps as InvObjProps } from '@patternfly/react-component-groups'; + const props: InvObjProps;`, errors: [ { - message: `InvalidObjectProps has been renamed to MissingPageProps.`, + message, type: "ImportSpecifier", }, ], @@ -55,7 +65,7 @@ ruleTester.run( output: `import { MissingPageProps } from '@patternfly/react-component-groups/dist/cjs/InvalidObject';`, errors: [ { - message: `InvalidObjectProps has been renamed to MissingPageProps.`, + message, type: "ImportSpecifier", }, ], @@ -65,7 +75,7 @@ ruleTester.run( output: `import { MissingPageProps } from '@patternfly/react-component-groups/dist/esm/InvalidObject';`, errors: [ { - message: `InvalidObjectProps has been renamed to MissingPageProps.`, + message, type: "ImportSpecifier", }, ], @@ -75,7 +85,7 @@ ruleTester.run( output: `import { MissingPageProps } from '@patternfly/react-component-groups/dist/dynamic/InvalidObject';`, errors: [ { - message: `InvalidObjectProps has been renamed to MissingPageProps.`, + message, type: "ImportSpecifier", }, ], diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/componentGroupsInvalidObjectPropsRenameToMissingPagePropsInput.tsx b/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/componentGroupsInvalidObjectPropsRenameToMissingPagePropsInput.tsx index c4e076e62..ec07c2052 100644 --- a/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/componentGroupsInvalidObjectPropsRenameToMissingPagePropsInput.tsx +++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/componentGroupsInvalidObjectPropsRenameToMissingPagePropsInput.tsx @@ -1,3 +1,4 @@ import { InvalidObjectProps } from "@patternfly/react-component-groups"; const props: InvalidObjectProps; +interface CustomProps extends InvalidObjectProps {} diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/componentGroupsInvalidObjectPropsRenameToMissingPagePropsOutput.tsx b/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/componentGroupsInvalidObjectPropsRenameToMissingPagePropsOutput.tsx index 5ee805698..c6f2a2760 100644 --- a/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/componentGroupsInvalidObjectPropsRenameToMissingPagePropsOutput.tsx +++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/componentGroupsInvalidObjectPropsRenameToMissingPagePropsOutput.tsx @@ -1,3 +1,4 @@ import { MissingPageProps } from "@patternfly/react-component-groups"; const props: MissingPageProps; +interface CustomProps extends MissingPageProps {} From 61f5a6ad5ce87568ff63fb1cfdabdfb077a63258 Mon Sep 17 00:00:00 2001 From: adamviktora Date: Tue, 12 Nov 2024 17:00:10 +0100 Subject: [PATCH 6/6] fix: PR review --- .../src/rules/helpers/index.ts | 1 + .../checkMatchingImportSpecifier.ts | 15 ++++++++ .../src/rules/helpers/renameInterface.ts | 35 +++++++++---------- ...ctProps-rename-to-missingPageProps.test.ts | 8 +++-- 4 files changed, 39 insertions(+), 20 deletions(-) create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/helpers/nodeMatches/checkMatchingImportSpecifier.ts diff --git a/packages/eslint-plugin-pf-codemods/src/rules/helpers/index.ts b/packages/eslint-plugin-pf-codemods/src/rules/helpers/index.ts index a4661bb9a..8393e4731 100644 --- a/packages/eslint-plugin-pf-codemods/src/rules/helpers/index.ts +++ b/packages/eslint-plugin-pf-codemods/src/rules/helpers/index.ts @@ -26,6 +26,7 @@ export * from "./isReactIcon"; export * from "./JSXAttributes"; export * from "./makeJSXElementSelfClosing"; export * from "./nodeMatches/checkMatchingImportDeclaration"; +export * from "./nodeMatches/checkMatchingImportSpecifier"; export * from "./nodeMatches/checkMatchingJSXOpeningElement"; export * from "./pfPackageMatches"; export * from "./removeElement"; diff --git a/packages/eslint-plugin-pf-codemods/src/rules/helpers/nodeMatches/checkMatchingImportSpecifier.ts b/packages/eslint-plugin-pf-codemods/src/rules/helpers/nodeMatches/checkMatchingImportSpecifier.ts new file mode 100644 index 000000000..0df936b5a --- /dev/null +++ b/packages/eslint-plugin-pf-codemods/src/rules/helpers/nodeMatches/checkMatchingImportSpecifier.ts @@ -0,0 +1,15 @@ +import { ImportSpecifier } from "estree-jsx"; + +/** Used to check whether the current ImportSpecifier node matches at least 1 of the import specifiers. */ +export function checkMatchingImportSpecifier( + node: ImportSpecifier, + imports: ImportSpecifier | ImportSpecifier[] +) { + if (Array.isArray(imports)) { + return imports.some( + (specifier) => specifier.imported.name === node.imported.name + ); + } + + return imports.imported.name === node.imported.name; +} diff --git a/packages/eslint-plugin-pf-codemods/src/rules/helpers/renameInterface.ts b/packages/eslint-plugin-pf-codemods/src/rules/helpers/renameInterface.ts index c5475aa38..04c45a3f5 100644 --- a/packages/eslint-plugin-pf-codemods/src/rules/helpers/renameInterface.ts +++ b/packages/eslint-plugin-pf-codemods/src/rules/helpers/renameInterface.ts @@ -1,7 +1,8 @@ import { Rule } from "eslint"; import { TSESTree } from "@typescript-eslint/utils"; -import { Identifier, ImportSpecifier, Node } from "estree-jsx"; +import { Identifier, ImportSpecifier } from "estree-jsx"; import { getFromPackage } from "./getFromPackage"; +import { checkMatchingImportSpecifier } from "./nodeMatches/checkMatchingImportSpecifier"; interface InterfaceRenames { [currentName: string]: string; @@ -23,19 +24,19 @@ export function renameInterface( return {}; } - const replaceIdentifier = (identifier: Identifier) => { - const getMatchingImport = (name: string) => - imports.find((specifier) => specifier.local.name === name); - - const matchingImport = getMatchingImport(identifier.name); - const shouldRename = - matchingImport && - matchingImport.local.name === matchingImport.imported.name; + const shouldRenameIdentifier = (identifier: Identifier) => { + const matchingImport = imports.find( + (specifier) => specifier.local.name === identifier.name + ); - if (!shouldRename) { - return; + if (!matchingImport) { + return false; } + return matchingImport.local.name === matchingImport.imported.name; + }; + + const replaceIdentifier = (identifier: Identifier) => { const oldName = identifier.name; const newName = renames[oldName]; @@ -50,11 +51,7 @@ export function renameInterface( return { ImportSpecifier(node: ImportSpecifier) { - if ( - !imports.some( - (specifier) => specifier.imported.name === node.imported.name - ) - ) { + if (!checkMatchingImportSpecifier(node, imports)) { return; } @@ -71,12 +68,14 @@ export function renameInterface( }, TSTypeReference(node: TSESTree.TSTypeReference) { if (node.typeName.type === "Identifier") { - replaceIdentifier(node.typeName); + shouldRenameIdentifier(node.typeName) && + replaceIdentifier(node.typeName); } }, TSInterfaceHeritage(node: TSESTree.TSInterfaceHeritage) { if (node.expression.type === "Identifier") { - replaceIdentifier(node.expression); + shouldRenameIdentifier(node.expression) && + replaceIdentifier(node.expression); } }, }; diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/component-groups-invalidObjectProps-rename-to-missingPageProps.test.ts b/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/component-groups-invalidObjectProps-rename-to-missingPageProps.test.ts index 91774249a..79174a4e5 100644 --- a/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/component-groups-invalidObjectProps-rename-to-missingPageProps.test.ts +++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/componentGroupsInvalidObjectPropsRenameToMissingPageProps/component-groups-invalidObjectProps-rename-to-missingPageProps.test.ts @@ -16,14 +16,18 @@ ruleTester.run( { code: `import { InvalidObjectProps } from '@patternfly/react-core';`, }, + // import of other props + { + code: `import { SomeOtherProps } from '@patternfly/react-component-groups';`, + }, ], invalid: [ { - code: `import { InvalidObjectProps } from '@patternfly/react-component-groups'; + code: `import { InvalidObjectProps, SomethingElse } from '@patternfly/react-component-groups'; const props: InvalidObjectProps; const otherProps = props as InvalidObjectProps; interface CustomProps extends InvalidObjectProps {};`, - output: `import { MissingPageProps } from '@patternfly/react-component-groups'; + output: `import { MissingPageProps, SomethingElse } from '@patternfly/react-component-groups'; const props: MissingPageProps; const otherProps = props as MissingPageProps; interface CustomProps extends MissingPageProps {};`,