Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion integration_test/__snapshots__/autoprefixer.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1092,6 +1092,7 @@ exports[`autoprefixer --type-aware > autoprefixer--type-aware 1`] = `
"prefer-regex-literals",
],
"nursery": [
"@typescript-eslint/dot-notation",
"getter-return",
"import-x/export",
"no-undef",
Expand All @@ -1100,7 +1101,6 @@ exports[`autoprefixer --type-aware > autoprefixer--type-aware 1`] = `
"type-aware": [],
"unsupported": [
"camelcase",
"dot-notation",
"no-dupe-args",
"no-invalid-this",
"no-octal",
Expand Down
2 changes: 1 addition & 1 deletion integration_test/__snapshots__/nuxt-auth.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3180,13 +3180,13 @@ exports[`nuxt-auth --type-aware > nuxt-auth--type-aware 1`] = `
"vue/no-irregular-whitespace",
],
"nursery": [
"@typescript-eslint/dot-notation",
"no-undef",
"no-unreachable",
"getter-return",
],
"type-aware": [],
"unsupported": [
"dot-notation",
"no-dupe-args",
"no-octal",
"no-octal-escape",
Expand Down
3 changes: 1 addition & 2 deletions integration_test/__snapshots__/typescript.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1190,10 +1190,10 @@ exports[`typescript --type-aware > typescript--type-aware 1`] = `
"getter-return",
"no-undef",
"no-unreachable",
"@typescript-eslint/dot-notation",
"@typescript-eslint/prefer-optional-chain",
"@typescript-eslint/consistent-return",
"@typescript-eslint/consistent-type-exports",
"@typescript-eslint/dot-notation",
"@typescript-eslint/no-unnecessary-condition",
"@typescript-eslint/no-unnecessary-qualifier",
"@typescript-eslint/no-unnecessary-type-parameters",
Expand All @@ -1209,7 +1209,6 @@ exports[`typescript --type-aware > typescript--type-aware 1`] = `
"unsupported": [
"no-dupe-args",
"no-octal",
"dot-notation",
"no-return-await",
"no-undef-init",
],
Expand Down
8 changes: 8 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ export const rulesPrefixesForPlugins: Record<string, string> = {
vue: 'vue',
};

// Some ESLint rules are superseded by @typescript-eslint equivalents in oxlint.
// When --type-aware is enabled, we should remap these ESLint rules to their
// @typescript-eslint counterparts so they get migrated correctly.
export const eslintRulesToTypescriptEquivalents: Record<string, string> = {
'dot-notation': '@typescript-eslint/dot-notation',
'consistent-return': '@typescript-eslint/consistent-return',
};

// Some typescript-eslint rules are re-implemented version of eslint rules.
// Since oxlint supports these rules under eslint/* and it also supports TS,
// we should override these to make implementation status up-to-date.
Expand Down
61 changes: 61 additions & 0 deletions src/plugin_rules.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,67 @@ describe('rules and plugins', () => {
).toBe('error');
});

test('eslint rules remapped to typescript equivalents when type-aware is enabled', () => {
// dot-notation and consistent-return are unsupported as plain ESLint rules in oxlint,
// but oxlint supports them as @typescript-eslint type-aware rules.
const eslintConfig: ESLint.Config = {
rules: {
'dot-notation': 'error',
'consistent-return': 'warn',
},
};

const configWithoutTypeAware: OxlintConfig = {};
const configWithTypeAware: OxlintConfig = {};

// Without --type-aware: rules are not migrated (they are unsupported)
transformRuleEntry(eslintConfig, configWithoutTypeAware);
expect(configWithoutTypeAware.rules).toStrictEqual({});

// With --type-aware: remapped to @typescript-eslint equivalents
transformRuleEntry(eslintConfig, configWithTypeAware, undefined, {
typeAware: true,
withNursery: true,
});
assert(configWithTypeAware.rules);
expect(configWithTypeAware.rules['@typescript-eslint/dot-notation']).toBe(
'error'
);
expect(
configWithTypeAware.rules['@typescript-eslint/consistent-return']
).toBe('warn');
});

test('typescript rules still get mapped to typescript equivalents as expected', () => {
// Ensure that these two rules - despite being treated as extensions - still get mapped appropriately.
const eslintConfig: ESLint.Config = {
rules: {
'@typescript-eslint/dot-notation': 'error',
'@typescript-eslint/consistent-return': 'warn',
},
};

const configWithoutTypeAware: OxlintConfig = {};
const configWithTypeAware: OxlintConfig = {};

// Without --type-aware: rules are not migrated (they are unsupported)
transformRuleEntry(eslintConfig, configWithoutTypeAware);
expect(configWithoutTypeAware.rules).toStrictEqual({});

// With --type-aware: ported
transformRuleEntry(eslintConfig, configWithTypeAware, undefined, {
typeAware: true,
withNursery: true,
});
assert(configWithTypeAware.rules);
expect(configWithTypeAware.rules['@typescript-eslint/dot-notation']).toBe(
'error'
);
expect(
configWithTypeAware.rules['@typescript-eslint/consistent-return']
).toBe('warn');
});

test('does not report unsupported rules that are disabled', () => {
const enabledConfig: ESLint.Config = {
rules: {
Expand Down
11 changes: 10 additions & 1 deletion src/plugins_rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type {
Category,
} from './types.js';
import {
eslintRulesToTypescriptEquivalents,
rulesPrefixesForPlugins,
typescriptRulesExtendEslintRules,
} from './constants.js';
Expand Down Expand Up @@ -181,7 +182,15 @@ export const transformRuleEntry = (
? { ...globalPlugins, ...eslintConfig.plugins }
: eslintConfig.plugins;

for (const [rule, config] of Object.entries(eslintConfig.rules)) {
for (const [originalRule, config] of Object.entries(eslintConfig.rules)) {
// When --type-aware is enabled, remap ESLint rules to their @typescript-eslint
// equivalents that oxlint supports as type-aware rules.
const rule =
options?.typeAware &&
eslintRulesToTypescriptEquivalents[originalRule] !== undefined
? eslintRulesToTypescriptEquivalents[originalRule]
: originalRule;

const normalizedConfig = normalizeSeverityValue(config);

// removing rules from previous "overrides"
Expand Down