diff --git a/package.json b/package.json index 829a4aa35..abc194a9b 100644 --- a/package.json +++ b/package.json @@ -12,10 +12,10 @@ "test:v5:single": "pf-codemods --no-cache test/test.tsx", "test:v6:single": "yarn build && pf-codemods --v6 --no-cache packages/eslint-plugin-pf-codemods/src/rules/v6/*/*Input.tsx", "test:v6:single:output": "yarn build && pf-codemods --v6 --no-cache packages/eslint-plugin-pf-codemods/src/rules/v6/*/*Output.tsx", - "test:koku": "pf-codemods --no-cache test/koku-ui", - "test:console": "pf-codemods --no-cache test/console/frontend", - "test:integreatly": "pf-codemods --no-cache test/tutorial-web-app", - "test:packages": "yarn get:packages && node --unhandled-rejections=strict packages/pf-codemods/index.js --no-cache test/packages", + "test:koku": "pf-codemods --v6 --no-cache test/koku-ui", + "test:console": "pf-codemods --v6 --no-cache test/console/frontend", + "test:integreatly": "pf-codemods --v6 --no-cache test/tutorial-web-app", + "test:packages": "yarn get:packages && node --unhandled-rejections=strict packages/pf-codemods/index.js --v6 --no-cache test/packages", "test:classnames": "class-name-updater --no-cache test", "get:packages": "node getPackages.js", "generate": "yarn build:generators && plop", diff --git a/packages/eslint-plugin-pf-codemods/package.json b/packages/eslint-plugin-pf-codemods/package.json index dd55aff7c..b6ac48ca6 100644 --- a/packages/eslint-plugin-pf-codemods/package.json +++ b/packages/eslint-plugin-pf-codemods/package.json @@ -23,6 +23,7 @@ "typescript": ">=3.8.3" }, "devDependencies": { - "@types/eslint": "^8.56.0" + "@types/eslint": "^8.56.0", + "@types/estree-jsx": "^1.0.4" } } diff --git a/packages/eslint-plugin-pf-codemods/src/rules/helpers/getFromPackage.ts b/packages/eslint-plugin-pf-codemods/src/rules/helpers/getFromPackage.ts new file mode 100644 index 000000000..2f16d2f6c --- /dev/null +++ b/packages/eslint-plugin-pf-codemods/src/rules/helpers/getFromPackage.ts @@ -0,0 +1,72 @@ +import { Rule } from "eslint"; +import { + ImportDeclaration, + ModuleDeclaration, + Statement, + Directive, + ExportNamedDeclaration, + ImportSpecifier, + ExportSpecifier, +} from "estree-jsx"; +import { pfPackageMatches } from "./pfPackageMatches"; + +type Declarations = ImportDeclaration | ExportNamedDeclaration; +type Specifiers = ImportSpecifier | ExportSpecifier; + +function filterByPackageName(nodes: Declarations[], packageName: string) { + return nodes.filter((node) => { + const nodeValue = node?.source?.value; + + if (typeof nodeValue !== "string") { + return false; + } + if (packageName.startsWith("@patternfly")) { + return pfPackageMatches(packageName, nodeValue); + } + return nodeValue === packageName; + }); +} + +function getSpecifiers< + NodeType extends Declarations, + SpecifierType extends Specifiers +>( + astBody: (ModuleDeclaration | Statement | Directive)[], + nodeType: "ImportDeclaration" | "ExportNamedDeclaration", + packageName: string +): SpecifierType[] { + const nodesOfSpecifiedType = astBody.filter( + (node) => node?.type === nodeType + ) as NodeType[]; + const pfNodes = filterByPackageName(nodesOfSpecifiedType, packageName); + const specifiers = pfNodes.map((node) => node.specifiers); + + const specifierType = + nodeType === "ImportDeclaration" ? "ImportSpecifier" : "ExportSpecifier"; + + const filteredSpecifiersByType = specifiers.filter((specifierArray) => + specifierArray.every((specifier) => specifier.type === specifierType) + ) as unknown as SpecifierType[]; + + return filteredSpecifiersByType.reduce( + (acc, val) => acc.concat(val), + [] as SpecifierType[] + ); +} + +export function getFromPackage(context: Rule.RuleContext, packageName: string) { + const astBody = context.sourceCode.ast.body; + + const imports = getSpecifiers( + astBody, + "ImportDeclaration", + packageName + ); + const exports = getSpecifiers( + astBody, + "ExportNamedDeclaration", + packageName + ); + + return { imports, exports }; +} diff --git a/packages/eslint-plugin-pf-codemods/src/rules/helpers.js b/packages/eslint-plugin-pf-codemods/src/rules/helpers/helpers.js similarity index 95% rename from packages/eslint-plugin-pf-codemods/src/rules/helpers.js rename to packages/eslint-plugin-pf-codemods/src/rules/helpers/helpers.js index d48769908..1f5368fc9 100644 --- a/packages/eslint-plugin-pf-codemods/src/rules/helpers.js +++ b/packages/eslint-plugin-pf-codemods/src/rules/helpers/helpers.js @@ -286,56 +286,6 @@ export function moveSpecifiers( }; } -export function pfPackageMatches(packageName, nodeSrc) { - const parts = packageName.split("/"); - const regex = new RegExp( - "^" + - parts[0] + - "/" + - parts[1] + - "(/dist/(esm|js))?" + - (parts[2] ? "/" + parts[2] : "") + - "(/(components|helpers)/.*)?$" - ); - return regex.test(nodeSrc); -} - -/** - * - * @param context - * @param {string} packageName - * @param {string[]} specifierNames - * @returns {{ imports, exports }} an object containing an array of imports and array of named exports - */ -export function getFromPackage(context, packageName, specifierNames = []) { - const astBody = context.getSourceCode().ast.body; - const getSpecifiers = (nodeType) => - astBody - .filter((node) => node?.type === nodeType) - .filter((node) => { - if (packageName.startsWith("@patternfly")) { - return pfPackageMatches(packageName, node?.source?.value); - } - return node?.source?.value === packageName; - }) - .map((node) => node?.specifiers) - .reduce((acc, val) => acc.concat(val), []); - - const imports = getSpecifiers("ImportDeclaration"); - const exports = getSpecifiers("ExportNamedDeclaration"); - - return !specifierNames.length - ? { imports, exports } - : { - imports: imports.filter((s) => - specifierNames?.includes(s?.imported?.name) - ), - exports: exports.filter((s) => - specifierNames?.includes(s?.local?.name) - ), - }; -} - export function splitSpecifiers(declaration, specifiersToSplit) { let keepSpecifiers = []; diff --git a/packages/eslint-plugin-pf-codemods/src/rules/helpers/index.ts b/packages/eslint-plugin-pf-codemods/src/rules/helpers/index.ts new file mode 100644 index 000000000..ed9f266fd --- /dev/null +++ b/packages/eslint-plugin-pf-codemods/src/rules/helpers/index.ts @@ -0,0 +1,3 @@ +export * from './helpers'; +export * from './pfPackageMatches'; +export * from './getFromPackage'; \ No newline at end of file diff --git a/packages/eslint-plugin-pf-codemods/src/rules/helpers/pfPackageMatches.ts b/packages/eslint-plugin-pf-codemods/src/rules/helpers/pfPackageMatches.ts new file mode 100644 index 000000000..e66b66ebf --- /dev/null +++ b/packages/eslint-plugin-pf-codemods/src/rules/helpers/pfPackageMatches.ts @@ -0,0 +1,22 @@ +import { ImportDeclaration } from "estree-jsx"; + +export function pfPackageMatches( + packageName: string, + nodeSrc: ImportDeclaration["source"]["value"] +) { + if (typeof nodeSrc !== "string") { + return false; + } + + const parts = packageName.split("/"); + const regex = new RegExp( + "^" + + parts[0] + + "/" + + parts[1] + + "(/dist/(esm|js))?" + + (parts[2] ? "/" + parts[2] : "") + + "(/(components|helpers)/.*)?$" + ); + return regex.test(nodeSrc); +} diff --git a/yarn.lock b/yarn.lock index aaf5af234..d664ea7b3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1056,6 +1056,13 @@ "@types/estree" "*" "@types/json-schema" "*" +"@types/estree-jsx@^1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@types/estree-jsx/-/estree-jsx-1.0.4.tgz#8d34b43444887dde8a73af530f772f23e1d3287c" + integrity sha512-5idy3hvI9lAMqsyilBM+N+boaCf1MgoefbDxN6KEO5aK17TOHwFAYT9sjxzeKAiIWRUBgLxmZ9mPcnzZXtTcRQ== + dependencies: + "@types/estree" "*" + "@types/estree@*": version "1.0.5" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4"