Skip to content

Commit

Permalink
Fix XO to not override rules from user's config (#761)
Browse files Browse the repository at this point in the history
  • Loading branch information
melusc authored Jul 23, 2024
1 parent 112e657 commit 9cdab84
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 17 deletions.
34 changes: 17 additions & 17 deletions lib/options-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -348,58 +348,58 @@ const buildXOConfig = options => config => {
for (const [rule, ruleConfig] of Object.entries(ENGINE_RULES)) {
for (const minVersion of Object.keys(ruleConfig).sort(semver.rcompare)) {
if (!options.nodeVersion || semver.intersects(options.nodeVersion, `<${minVersion}`)) {
config.baseConfig.rules[rule] = ruleConfig[minVersion];
config.baseConfig.rules[rule] ??= ruleConfig[minVersion];
}
}
}

if (options.nodeVersion) {
config.baseConfig.rules['n/no-unsupported-features/es-builtins'] = ['error', {version: options.nodeVersion}];
config.baseConfig.rules['n/no-unsupported-features/es-syntax'] = ['error', {version: options.nodeVersion, ignores: ['modules']}];
config.baseConfig.rules['n/no-unsupported-features/node-builtins'] = ['error', {version: options.nodeVersion}];
config.baseConfig.rules['n/no-unsupported-features/es-builtins'] ??= ['error', {version: options.nodeVersion}];
config.baseConfig.rules['n/no-unsupported-features/es-syntax'] ??= ['error', {version: options.nodeVersion, ignores: ['modules']}];
config.baseConfig.rules['n/no-unsupported-features/node-builtins'] ??= ['error', {version: options.nodeVersion}];
}

if (options.space && !options.prettier) {
if (options.ts) {
config.baseConfig.rules['@typescript-eslint/indent'] = ['error', spaces, {SwitchCase: 1}];
config.baseConfig.rules['@typescript-eslint/indent'] ??= ['error', spaces, {SwitchCase: 1}];
} else {
config.baseConfig.rules.indent = ['error', spaces, {SwitchCase: 1}];
config.baseConfig.rules.indent ??= ['error', spaces, {SwitchCase: 1}];
}

// Only apply if the user has the React plugin
if (options.cwd && resolveFrom.silent('eslint-plugin-react', options.cwd)) {
config.baseConfig.plugins.push('react');
config.baseConfig.rules['react/jsx-indent-props'] = ['error', spaces];
config.baseConfig.rules['react/jsx-indent'] = ['error', spaces];
config.baseConfig.rules['react/jsx-indent-props'] ??= ['error', spaces];
config.baseConfig.rules['react/jsx-indent'] ??= ['error', spaces];
}
}

if (options.semicolon === false && !options.prettier) {
if (options.ts) {
config.baseConfig.rules['@typescript-eslint/semi'] = ['error', 'never'];
config.baseConfig.rules['@typescript-eslint/semi'] ??= ['error', 'never'];
} else {
config.baseConfig.rules.semi = ['error', 'never'];
config.baseConfig.rules.semi ??= ['error', 'never'];
}

config.baseConfig.rules['semi-spacing'] = ['error', {
config.baseConfig.rules['semi-spacing'] ??= ['error', {
before: false,
after: true,
}];
}

if (options.ts) {
config.baseConfig.rules['unicorn/import-style'] = 'off';
config.baseConfig.rules['node/file-extension-in-import'] = 'off';
config.baseConfig.rules['unicorn/import-style'] ??= 'off';
config.baseConfig.rules['node/file-extension-in-import'] ??= 'off';

// Disabled because of https://github.com/benmosher/eslint-plugin-import/issues/1590
config.baseConfig.rules['import/export'] = 'off';
config.baseConfig.rules['import/export'] ??= 'off';

// Does not work when the TS definition exports a default const.
config.baseConfig.rules['import/default'] = 'off';
config.baseConfig.rules['import/default'] ??= 'off';

// Disabled as it doesn't work with TypeScript.
// This issue and some others: https://github.com/benmosher/eslint-plugin-import/issues/1341
config.baseConfig.rules['import/named'] = 'off';
config.baseConfig.rules['import/named'] ??= 'off';
}

config.baseConfig.settings['import/resolver'] = gatherImportResolvers(options);
Expand Down Expand Up @@ -444,7 +444,7 @@ const buildPrettierConfig = (options, prettierConfig) => config => {
config.baseConfig.extends.push('plugin:prettier/recommended');

// The `prettier/prettier` rule reports errors if the code is not formatted in accordance to Prettier
config.baseConfig.rules['prettier/prettier'] = ['error', mergeWithPrettierConfig(options, prettierConfig)];
config.baseConfig.rules['prettier/prettier'] ??= ['error', mergeWithPrettierConfig(options, prettierConfig)];
}

return config;
Expand Down
26 changes: 26 additions & 0 deletions test/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,29 @@ test('print-config flag without filename', async t => {
);
t.is(error.stderr.trim(), 'The `--print-config` flag must be used with exactly one filename');
});

test('Do not override user-config', async t => {
const cwd = path.join(__dirname, 'fixtures/no-override-user-config');
const {stdout} = await main(['--print-config', 'index.js'], {cwd});
const config = JSON.parse(stdout);
t.like(config, {
rules: {
'n/no-unsupported-features/es-builtins': ['off'],
'n/no-unsupported-features/es-syntax': ['off'],
'n/no-unsupported-features/node-builtins': ['off'],
},
});

const {stdout: stdoutOverrides} = await main(['--print-config', 'overrides.js'], {cwd});
const configOverrides = JSON.parse(stdoutOverrides);
t.like(configOverrides, {
rules: {
'n/no-unsupported-features/es-builtins': ['off'],
'n/no-unsupported-features/es-syntax': ['off'],
'n/no-unsupported-features/node-builtins': ['error'],
},
});

await t.notThrowsAsync(() => main(['index.js'], {cwd}));
await t.throwsAsync(() => main(['overrides.js'], {cwd}));
});
1 change: 1 addition & 0 deletions test/fixtures/no-override-user-config/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
const _ = new FormData();
1 change: 1 addition & 0 deletions test/fixtures/no-override-user-config/overrides.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
const _ = new FormData();
20 changes: 20 additions & 0 deletions test/fixtures/no-override-user-config/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"xo": {
"rules": {
"n/no-unsupported-features/es-builtins": "off",
"n/no-unsupported-features/es-syntax": "off",
"n/no-unsupported-features/node-builtins": "off"
},
"overrides": [
{
"files": "overrides.js",
"rules": {
"n/no-unsupported-features/node-builtins": "error"
}
}
]
},
"engines": {
"node": ">=18"
}
}

0 comments on commit 9cdab84

Please sign in to comment.