Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: disable alias eslint and @typescript-eslint rules together #238

Closed
wants to merge 9 commits into from
29 changes: 29 additions & 0 deletions src/build-from-oxlint-config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down Expand Up @@ -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 = (
Expand Down
46 changes: 34 additions & 12 deletions src/build-from-oxlint-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
);
}
Expand All @@ -121,7 +129,7 @@ const getEsLintRuleName = (rule: string): string | undefined => {
const match = rule.match(/(^.*)\/(.*)/);

if (match === null) {
return undefined;
return [];
}

const pluginName = match[1];
Expand All @@ -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];
};

/**
Expand All @@ -154,21 +174,23 @@ const handleRulesScope = (
rules: Record<string, 'off'>
): 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];
}
}
}
};
Expand Down