From 83a54e0d06ab4dc1e2df9d5ca558018191e37c19 Mon Sep 17 00:00:00 2001 From: Yuji Sugiura <6259812+leaysgur@users.noreply.github.com> Date: Thu, 25 Jan 2024 17:32:26 +0900 Subject: [PATCH] feat(tasks): Add more plugins for tasks/lint_rules2 (#2167) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Part pf #2020 - [x] jsx-a11y - [x] react, react-hooks, react-perf - [x] nextjs Now, we can track all target plugins(AFAIK)? 🕵🏻 --- tasks/lint_rules2/package.json | 5 ++ tasks/lint_rules2/src/eslint-rules.cjs | 83 +++++++++++++++++++++++++- tasks/lint_rules2/src/main.cjs | 16 ++++- 3 files changed, 102 insertions(+), 2 deletions(-) diff --git a/tasks/lint_rules2/package.json b/tasks/lint_rules2/package.json index 5fa35e62ad2da..454235d0f02d5 100644 --- a/tasks/lint_rules2/package.json +++ b/tasks/lint_rules2/package.json @@ -7,12 +7,17 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { + "@next/eslint-plugin-next": "latest", "@typescript-eslint/eslint-plugin": "latest", "eslint": "latest", "eslint-plugin-import": "latest", "eslint-plugin-jest": "latest", "eslint-plugin-jsdoc": "latest", + "eslint-plugin-jsx-a11y": "latest", "eslint-plugin-n": "latest", + "eslint-plugin-react": "latest", + "eslint-plugin-react-hooks": "latest", + "eslint-plugin-react-perf": "latest", "eslint-plugin-unicorn": "latest" } } diff --git a/tasks/lint_rules2/src/eslint-rules.cjs b/tasks/lint_rules2/src/eslint-rules.cjs index 2271f8e26aa39..fcc461c0ba6e4 100644 --- a/tasks/lint_rules2/src/eslint-rules.cjs +++ b/tasks/lint_rules2/src/eslint-rules.cjs @@ -5,8 +5,9 @@ const { Linter } = require("eslint"); // Even worse, every plugin has slightly different types, different way of configuration in detail... // // So here, we need to list all rules while normalizing recommended and deprecated flags. -// - rule.meta.docs.recommended // - rule.meta.deprecated +// - rule.meta.docs.recommended +// Some plugins have the recommended flag in rule itself, but some plugins have it in config. // https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/index.ts const { @@ -32,8 +33,26 @@ const { rules: pluginImportAllRules, configs: pluginImportConfigs, } = require("eslint-plugin-import"); +// https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/src/index.js +const { + rules: pluginJSXA11yAllRules, + configs: pluginJSXA11yConfigs, +} = require("eslint-plugin-jsx-a11y"); // https://github.com/jest-community/eslint-plugin-jest/blob/main/src/index.ts const { rules: pluginJestAllRules } = require("eslint-plugin-jest"); +// https://github.com/jsx-eslint/eslint-plugin-react/blob/master/index.js +const { rules: pluginReactAllRules } = require("eslint-plugin-react"); +// https://github.com/facebook/react/blob/main/packages/eslint-plugin-react-hooks/src/index.js +const { + rules: pluginReactHooksAllRules, +} = require("eslint-plugin-react-hooks"); +// https://github.com/cvazac/eslint-plugin-react-perf/blob/master/index.js +const { + rules: pluginReactPerfAllRules, + configs: pluginReactPerfConfigs, +} = require("eslint-plugin-react-perf"); +// https://github.com/vercel/next.js/blob/canary/packages/eslint-plugin-next/src/index.ts +const { rules: pluginNextAllRules } = require("@next/eslint-plugin-next"); // All rules(including deprecated, recommended) are loaded initially. exports.createESLintLinter = () => new Linter(); @@ -116,6 +135,25 @@ exports.loadPluginImportRules = (linter) => { } }; +/** @param {import("eslint").Linter} linter */ +exports.loadPluginJSXA11yRules = (linter) => { + const pluginJSXA11yRecommendedRules = new Map( + Object.entries(pluginJSXA11yConfigs.recommended.rules), + ); + for (const [name, rule] of Object.entries(pluginJSXA11yAllRules)) { + const prefixedName = `jsx-a11y/${name}`; + + const recommendedValue = pluginJSXA11yRecommendedRules.get(prefixedName); + rule.meta.docs.recommended = + recommendedValue && + // Type is `string | [string, opt]` + recommendedValue !== "off" && + recommendedValue[0] !== "off"; + + linter.defineRule(prefixedName, rule); + } +}; + /** @param {import("eslint").Linter} linter */ exports.loadPluginJestRules = (linter) => { for (const [name, rule] of Object.entries(pluginJestAllRules)) { @@ -127,3 +165,46 @@ exports.loadPluginJestRules = (linter) => { linter.defineRule(prefixedName, rule); } }; + +/** @param {import("eslint").Linter} linter */ +exports.loadPluginReactRules = (linter) => { + for (const [name, rule] of Object.entries(pluginReactAllRules)) { + const prefixedName = `react/${name}`; + + linter.defineRule(prefixedName, rule); + } +}; + +/** @param {import("eslint").Linter} linter */ +exports.loadPluginReactHooksRules = (linter) => { + for (const [name, rule] of Object.entries(pluginReactHooksAllRules)) { + const prefixedName = `react-hooks/${name}`; + + // @ts-expect-error: The types of 'meta.type', 'string' is not assignable to type '"problem" | "suggestion" | "layout" | undefined'. + linter.defineRule(prefixedName, rule); + } +}; + +/** @param {import("eslint").Linter} linter */ +exports.loadPluginReactPerfRules = (linter) => { + const pluginReactPerfRecommendedRules = new Map( + Object.entries(pluginReactPerfConfigs.recommended.rules), + ); + for (const [name, rule] of Object.entries(pluginReactPerfAllRules)) { + const prefixedName = `react-perf/${name}`; + + rule.meta.docs.recommended = + pluginReactPerfRecommendedRules.has(prefixedName); + + linter.defineRule(prefixedName, rule); + } +}; + +/** @param {import("eslint").Linter} linter */ +exports.loadPluginNextRules = (linter) => { + for (const [name, rule] of Object.entries(pluginNextAllRules)) { + const prefixedName = `nextjs/${name}`; + + linter.defineRule(prefixedName, rule); + } +}; diff --git a/tasks/lint_rules2/src/main.cjs b/tasks/lint_rules2/src/main.cjs index c93b51e5c51b0..dfebfa48595c5 100644 --- a/tasks/lint_rules2/src/main.cjs +++ b/tasks/lint_rules2/src/main.cjs @@ -6,7 +6,12 @@ const { loadPluginUnicornRules, loadPluginJSDocRules, loadPluginImportRules, + loadPluginJSXA11yRules, loadPluginJestRules, + loadPluginReactRules, + loadPluginReactHooksRules, + loadPluginReactPerfRules, + loadPluginNextRules, } = require("./eslint-rules.cjs"); const { createRuleEntries, @@ -23,7 +28,12 @@ const ALL_TARGET_PLUGIN_NAMES = new Set([ "unicorn", "jsdoc", "import", + "jsx-a11y", "jest", + "react", + "react-hooks", + "react-perf", + "nextjs", ]); const HELP = ` @@ -67,8 +77,12 @@ Plugins: ${[...ALL_TARGET_PLUGIN_NAMES].join(", ")} loadPluginUnicornRules(linter); loadPluginJSDocRules(linter); loadPluginImportRules(linter); + loadPluginJSXA11yRules(linter); loadPluginJestRules(linter); - // TODO: more plugins + loadPluginReactRules(linter); + loadPluginReactHooksRules(linter); + loadPluginReactPerfRules(linter); + loadPluginNextRules(linter); // // Generate entry and update status