Skip to content

Commit 9cdab84

Browse files
authoredJul 23, 2024··
Fix XO to not override rules from user's config (#761)
1 parent 112e657 commit 9cdab84

File tree

5 files changed

+65
-17
lines changed

5 files changed

+65
-17
lines changed
 

‎lib/options-manager.js

+17-17
Original file line numberDiff line numberDiff line change
@@ -348,58 +348,58 @@ const buildXOConfig = options => config => {
348348
for (const [rule, ruleConfig] of Object.entries(ENGINE_RULES)) {
349349
for (const minVersion of Object.keys(ruleConfig).sort(semver.rcompare)) {
350350
if (!options.nodeVersion || semver.intersects(options.nodeVersion, `<${minVersion}`)) {
351-
config.baseConfig.rules[rule] = ruleConfig[minVersion];
351+
config.baseConfig.rules[rule] ??= ruleConfig[minVersion];
352352
}
353353
}
354354
}
355355

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

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

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

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

384-
config.baseConfig.rules['semi-spacing'] = ['error', {
384+
config.baseConfig.rules['semi-spacing'] ??= ['error', {
385385
before: false,
386386
after: true,
387387
}];
388388
}
389389

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

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

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

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

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

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

450450
return config;

‎test/cli.js

+26
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,29 @@ test('print-config flag without filename', async t => {
197197
);
198198
t.is(error.stderr.trim(), 'The `--print-config` flag must be used with exactly one filename');
199199
});
200+
201+
test('Do not override user-config', async t => {
202+
const cwd = path.join(__dirname, 'fixtures/no-override-user-config');
203+
const {stdout} = await main(['--print-config', 'index.js'], {cwd});
204+
const config = JSON.parse(stdout);
205+
t.like(config, {
206+
rules: {
207+
'n/no-unsupported-features/es-builtins': ['off'],
208+
'n/no-unsupported-features/es-syntax': ['off'],
209+
'n/no-unsupported-features/node-builtins': ['off'],
210+
},
211+
});
212+
213+
const {stdout: stdoutOverrides} = await main(['--print-config', 'overrides.js'], {cwd});
214+
const configOverrides = JSON.parse(stdoutOverrides);
215+
t.like(configOverrides, {
216+
rules: {
217+
'n/no-unsupported-features/es-builtins': ['off'],
218+
'n/no-unsupported-features/es-syntax': ['off'],
219+
'n/no-unsupported-features/node-builtins': ['error'],
220+
},
221+
});
222+
223+
await t.notThrowsAsync(() => main(['index.js'], {cwd}));
224+
await t.throwsAsync(() => main(['overrides.js'], {cwd}));
225+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
const _ = new FormData();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
const _ = new FormData();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"xo": {
3+
"rules": {
4+
"n/no-unsupported-features/es-builtins": "off",
5+
"n/no-unsupported-features/es-syntax": "off",
6+
"n/no-unsupported-features/node-builtins": "off"
7+
},
8+
"overrides": [
9+
{
10+
"files": "overrides.js",
11+
"rules": {
12+
"n/no-unsupported-features/node-builtins": "error"
13+
}
14+
}
15+
]
16+
},
17+
"engines": {
18+
"node": ">=18"
19+
}
20+
}

0 commit comments

Comments
 (0)
Please sign in to comment.