diff --git a/src/build-from-oxlint-config.spec.ts b/src/build-from-oxlint-config.spec.ts index 4f258553..41bfc03f 100644 --- a/src/build-from-oxlint-config.spec.ts +++ b/src/build-from-oxlint-config.spec.ts @@ -7,6 +7,18 @@ import fs from 'node:fs'; import { execSync } from 'node:child_process'; import type { Linter } from 'eslint'; import { typescriptRulesExtendEslintRules } from './constants.js'; +import configByCategory from './generated/configs-by-category.js'; + +const allRulesObjects = Object.values(configByCategory).map( + (config) => config.rules +); +const allRules: string[] = allRulesObjects.flatMap((rulesObject) => + Object.keys(rulesObject) +); + +const supportedTypescriptRulesExtendEslintRules = allRules.filter((rule) => + typescriptRulesExtendEslintRules.includes(rule) +); describe('buildFromOxlintConfig', () => { describe('rule values', () => { @@ -184,6 +196,23 @@ describe('buildFromOxlintConfig', () => { expect('unknown' in configs[0].rules!).toBe(false); expect('@next/next/no-img-element' in configs[0].rules!).toBe(false); }); + + for (const alias of supportedTypescriptRulesExtendEslintRules) { + it(`disables matching typescript and eslint rules for ${alias}`, () => { + for (const rule of [alias, `@typescript-eslint/${alias}`]) { + const rules = buildFromOxlintConfig({ + rules: { + [rule]: 'warn', + }, + }); + + expect(rules.length).toBe(1); + expect(rules[0].rules).not.toBeUndefined(); + expect(alias in rules[0].rules!).toBe(true); + expect(`@typescript-eslint/${alias}` in rules[0].rules!).toBe(true); + } + }); + } }); const createConfigFileAndBuildFromIt = ( diff --git a/src/build-from-oxlint-config.ts b/src/build-from-oxlint-config.ts index 5d00f85a..2638bbf6 100644 --- a/src/build-from-oxlint-config.ts +++ b/src/build-from-oxlint-config.ts @@ -109,10 +109,18 @@ const handleCategoriesScope = ( } }; -const getEsLintRuleName = (rule: string): string | undefined => { +/** + * returns all eslint rules names for a oxlint rule. + * oxlint rules are deactivating one or more eslint rules. + * + * Oxlint rules do not need a plugin-scope. + * When no eslint rules are found, an empty array is returned. + * + */ +const getEsLintRuleNames = (rule: string): string[] => { // there is no plugin prefix, it can be all plugin if (!rule.includes('/')) { - return allRules.find( + return allRules.filter( (search) => search.endsWith(`/${rule}`) || search === rule ); } @@ -121,7 +129,7 @@ const getEsLintRuleName = (rule: string): string | undefined => { const match = rule.match(/(^.*)\/(.*)/); if (match === null) { - return undefined; + return []; } const pluginName = match[1]; @@ -143,7 +151,19 @@ const getEsLintRuleName = (rule: string): string | undefined => { const expectedRule = esPluginName === '' ? ruleName : `${esPluginName}/${ruleName}`; - return allRules.find((rule) => rule == expectedRule); + // Some typescript-eslint rules are re-implemented version of eslint rules. + if (esPluginName === '@typescript-eslint' || esPluginName === '') { + return allRules.filter( + (rule) => + rule === expectedRule || + (esPluginName === '@typescript-eslint' && rule === ruleName) || + (esPluginName === '' && rule === `@typescript-eslint/${ruleName}`) + ); + } + + const found = allRules.find((rule) => rule === expectedRule); + + return found === undefined ? [] : [found]; }; /** @@ -154,21 +174,23 @@ const handleRulesScope = ( rules: Record ): void => { for (const rule in oxlintRules) { - const eslintName = getEsLintRuleName(rule); + const eslintNames = getEsLintRuleNames(rule); - if (eslintName === undefined) { + if (eslintNames.length === 0) { console.warn( `eslint-plugin-oxlint: could not find matching eslint rule for "${rule}"` ); continue; } - // is this rules not turned off - if (isActiveValue(oxlintRules[rule])) { - rules[eslintName] = 'off'; - } else if (rule in rules && isDeactivateValue(oxlintRules[rule])) { - // rules extended by categories or plugins can be disabled manually - delete rules[eslintName]; + for (const eslintName of eslintNames) { + // is this rules not turned off + if (isActiveValue(oxlintRules[rule])) { + rules[eslintName] = 'off'; + } else if (rule in rules && isDeactivateValue(oxlintRules[rule])) { + // rules extended by categories or plugins can be disabled manually + delete rules[eslintName]; + } } } };