Skip to content

Commit 74b34bf

Browse files
authored
Disable rules based on Node.js version (#423)
1 parent 9fbdb97 commit 74b34bf

File tree

5 files changed

+93
-68
lines changed

5 files changed

+93
-68
lines changed

config/plugins.js

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,6 @@ module.exports = {
5454
// ],
5555
'unicorn/prevent-abbreviations': 'off',
5656

57-
// TODO: Enable this when targeting Node.js 12.
58-
'unicorn/prefer-flat-map': 'off',
59-
6057
// TODO: Remove this override when the rule is more stable.
6158
'unicorn/consistent-function-scoping': 'off',
6259

@@ -216,16 +213,14 @@ module.exports = {
216213
'error',
217214
'always'
218215
],
219-
220-
// Enable these when targeting Node.js 12.
221-
// 'node/prefer-global/text-decoder': [
222-
// 'error',
223-
// 'always'
224-
// ],
225-
// 'node/prefer-global/text-encoder': [
226-
// 'error',
227-
// 'always'
228-
// ],
216+
'node/prefer-global/text-decoder': [
217+
'error',
218+
'always'
219+
],
220+
'node/prefer-global/text-encoder': [
221+
'error',
222+
'always'
223+
],
229224

230225
'node/prefer-global/url-search-params': [
231226
'error',
@@ -235,11 +230,8 @@ module.exports = {
235230
'error',
236231
'always'
237232
],
238-
239-
// Enable these when targeting Node.js 12.
240-
// 'node/prefer-promises/dns': 'error',
241-
// 'node/prefer-promises/fs': 'error',
242-
233+
'node/prefer-promises/dns': 'error',
234+
'node/prefer-promises/fs': 'error',
243235
'eslint-comments/disable-enable-pair': [
244236
'error',
245237
{

lib/options-manager.js

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ const DEFAULT_CONFIG = {
4343
};
4444

4545
/**
46-
* Define the rules that are enabled only for specific version of Node.js based on `engines.node` in package.json or the `node-version` option.
46+
* Define the rules config that are overwritten only for specific version of Node.js based on `engines.node` in package.json or the `node-version` option.
4747
*
4848
* The keys are rule names and the values are an Object with a valid semver (`4.0.0` is valid `4` is not) as keys and the rule configuration as values.
4949
*
50-
* Each entry define the rule config and the minimum Node.js version for which to set it.
51-
* The entry with the highest version that is compliant with the `engines.node`/`node-version` range will be used.
50+
* Each entry define the rule config and the maximum Node.js version for which to set it.
51+
* The entry with the lowest version that is compliant with the `engines.node`/`node-version` range will be used.
5252
*
5353
* @type {Object}
5454
*
@@ -66,26 +66,50 @@ const DEFAULT_CONFIG = {
6666
* With `engines.node` set to `>=8` the rule `plugin/rule` will be used with the config `{prop: 'node-8-conf'}`.
6767
*/
6868
const ENGINE_RULES = {
69-
'node/prefer-global/text-decoder': {
70-
'11.0.0': [
71-
'error',
72-
'always'
73-
]
69+
'unicorn/prefer-spread': {
70+
'5.0.0': 'off'
71+
},
72+
'unicorn/no-new-buffer': {
73+
'5.10.0': 'off'
74+
},
75+
'prefer-rest-params': {
76+
'6.0.0': 'off'
77+
},
78+
'prefer-destructuring': {
79+
'6.0.0': 'off'
80+
},
81+
'promise/prefer-await-to-then': {
82+
'7.6.0': 'off'
83+
},
84+
'prefer-object-spread': {
85+
'8.3.0': 'off'
86+
},
87+
'node/prefer-global/url-search-params': {
88+
'10.0.0': 'off'
89+
},
90+
'node/prefer-global/url': {
91+
'10.0.0': 'off'
92+
},
93+
'no-useless-catch': {
94+
'10.0.0': 'off'
95+
},
96+
'prefer-named-capture-group': {
97+
'10.0.0': 'off'
7498
},
7599
'node/prefer-global/text-encoder': {
76-
'11.0.0': [
77-
'error',
78-
'always'
79-
]
100+
'11.0.0': 'off'
101+
},
102+
'node/prefer-global/text-decoder': {
103+
'11.0.0': 'off'
104+
},
105+
'unicorn/prefer-flat-map': {
106+
'11.0.0': 'off'
80107
},
81108
'node/prefer-promises/dns': {
82-
'12.0.0': 'error'
109+
'11.14.0': 'off'
83110
},
84111
'node/prefer-promises/fs': {
85-
'12.0.0': 'error'
86-
},
87-
'unicorn/prefer-flat-map': {
88-
'11.0.0': 'error'
112+
'11.14.0': 'off'
89113
}
90114
};
91115

@@ -209,13 +233,10 @@ const buildConfig = options => {
209233
);
210234
const spaces = normalizeSpaces(options);
211235

212-
if (options.nodeVersion) {
213-
for (const rule of Object.keys(ENGINE_RULES)) {
214-
// Use the rule value for the highest version that is lower or equal to the oldest version of Node.js supported
215-
for (const minVersion of Object.keys(ENGINE_RULES[rule]).sort(semver.compare)) {
216-
if (!semver.intersects(options.nodeVersion, `<${minVersion}`)) {
217-
config.rules[rule] = ENGINE_RULES[rule][minVersion];
218-
}
236+
for (const [rule, ruleConfig] of Object.entries(ENGINE_RULES)) {
237+
for (const minVersion of Object.keys(ruleConfig).sort(semver.rcompare)) {
238+
if (!options.nodeVersion || semver.intersects(options.nodeVersion, `<${minVersion}`)) {
239+
config.rules[rule] = ruleConfig[minVersion];
219240
}
220241
}
221242
}

test/lint-files.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,7 @@ test('multiple negative patterns should act as positive patterns', async t => {
100100
t.deepEqual(paths, ['!!unicorn.js', '!unicorn.js']);
101101
});
102102

103-
// TODO: We need a new fixture. Help welcome.
104-
test.failing('enable rules based on nodeVersion', async t => {
103+
test('enable rules based on nodeVersion', async t => {
105104
const {results} = await fn.lintFiles('**/*', {cwd: 'fixtures/engines-overrides'});
106105

107106
// The transpiled file (as specified in `overrides`) should use `await`

test/lint-text.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,7 @@ test('lint eslintignored files if filename is not given', async t => {
212212
t.true(results[0].errorCount > 0);
213213
});
214214

215-
// TODO: We need a new fixture. Help welcome.
216-
test.failing('enable rules based on nodeVersion', async t => {
215+
test('enable rules based on nodeVersion', async t => {
217216
const cwd = path.join(__dirname, 'fixtures', 'engines-overrides');
218217
const filename = path.join(cwd, 'promise-then.js');
219218
const text = await readFile(filename, 'utf8');
@@ -225,8 +224,7 @@ test.failing('enable rules based on nodeVersion', async t => {
225224
t.false(hasRule(results, 'promise/prefer-await-to-then'));
226225
});
227226

228-
// TODO: We need a new fixture. Help welcome.
229-
test.failing('enable rules based on nodeVersion in override', async t => {
227+
test('enable rules based on nodeVersion in override', async t => {
230228
const cwd = path.join(__dirname, 'fixtures', 'engines-overrides');
231229
const filename = path.join(cwd, 'promise-then.js');
232230
const text = await readFile(filename, 'utf8');

test/options-manager.js

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ test('buildConfig: space: 4', t => {
6565
});
6666

6767
test('buildConfig: semicolon', t => {
68-
const config = manager.buildConfig({semicolon: false});
68+
const config = manager.buildConfig({semicolon: false, nodeVersion: '12'});
6969
t.deepEqual(config.rules, {
7070
semi: ['error', 'never'],
7171
'semi-spacing': ['error', {
@@ -203,38 +203,53 @@ test('buildConfig: engines: undefined', t => {
203203
const config = manager.buildConfig({});
204204

205205
// Do not include any Node.js version specific rules
206-
t.is(config.rules['prefer-spread'], undefined);
207-
t.is(config.rules['prefer-rest-params'], undefined);
208-
t.is(config.rules['prefer-destructuring'], undefined);
209-
t.is(config.rules['promise/prefer-await-to-then'], undefined);
206+
t.is(config.rules['prefer-object-spread'], 'off');
207+
t.is(config.rules['prefer-rest-params'], 'off');
208+
t.is(config.rules['prefer-destructuring'], 'off');
209+
t.is(config.rules['promise/prefer-await-to-then'], 'off');
210+
t.is(config.rules['unicorn/prefer-flat-map'], 'off');
211+
t.is(config.rules['node/prefer-promises/dns'], 'off');
212+
t.is(config.rules['node/prefer-promises/fs'], 'off');
210213
});
211214

212215
test('buildConfig: nodeVersion: false', t => {
213216
const config = manager.buildConfig({nodeVersion: false});
214217

215-
// Do not include any Node.js version specific rules
216-
t.is(config.rules['prefer-spread'], undefined);
217-
t.is(config.rules['prefer-rest-params'], undefined);
218-
t.is(config.rules['prefer-destructuring'], undefined);
219-
t.is(config.rules['promise/prefer-await-to-then'], undefined);
218+
// Override all the rules specific to Node.js version
219+
t.is(config.rules['prefer-object-spread'], 'off');
220+
t.is(config.rules['prefer-rest-params'], 'off');
221+
t.is(config.rules['prefer-destructuring'], 'off');
222+
t.is(config.rules['promise/prefer-await-to-then'], 'off');
223+
t.is(config.rules['unicorn/prefer-flat-map'], 'off');
224+
t.is(config.rules['node/prefer-promises/dns'], 'off');
225+
t.is(config.rules['node/prefer-promises/fs'], 'off');
220226
});
221227

222228
test('buildConfig: nodeVersion: invalid range', t => {
223229
const config = manager.buildConfig({nodeVersion: '4'});
224230

225-
// Do not include any Node.js version specific rules
226-
t.is(config.rules['prefer-spread'], undefined);
227-
t.is(config.rules['prefer-rest-params'], undefined);
228-
t.is(config.rules['prefer-destructuring'], undefined);
229-
t.is(config.rules['promise/prefer-await-to-then'], undefined);
231+
// Override all the rules specific to Node.js version
232+
t.is(config.rules['prefer-object-spread'], 'off');
233+
t.is(config.rules['prefer-rest-params'], 'off');
234+
t.is(config.rules['prefer-destructuring'], 'off');
235+
t.is(config.rules['promise/prefer-await-to-then'], 'off');
236+
t.is(config.rules['unicorn/prefer-flat-map'], 'off');
237+
t.is(config.rules['node/prefer-promises/dns'], 'off');
238+
t.is(config.rules['node/prefer-promises/fs'], 'off');
230239
});
231240

232-
// TODO: We need a new fixture. Help welcome.
233-
test.failing('buildConfig: nodeVersion: >=8', t => {
241+
test('buildConfig: nodeVersion: >=6', t => {
242+
const config = manager.buildConfig({nodeVersion: '>=6'});
243+
244+
// Turn off rule if we support Node.js below 7.6.0
245+
t.is(config.rules['promise/prefer-await-to-then'], 'off');
246+
});
247+
248+
test('buildConfig: nodeVersion: >=8', t => {
234249
const config = manager.buildConfig({nodeVersion: '>=8'});
235250

236-
// Include rules for Node.js 8 and above
237-
t.is(config.rules['promise/prefer-await-to-then'], 'error');
251+
// Do not turn off rule if we support only Node.js above 7.6.0
252+
t.is(config.rules['promise/prefer-await-to-then'], undefined);
238253
});
239254

240255
test('mergeWithPrettierConfig: use `singleQuote`, `trailingComma`, `bracketSpacing` and `jsxBracketSameLine` from `prettier` config if defined', t => {
@@ -327,7 +342,7 @@ test('mergeWithPrettierConfig: throw error is `space`/`tabWidth` conflicts', t =
327342

328343
test('buildConfig: rules', t => {
329344
const rules = {'object-curly-spacing': ['error', 'always']};
330-
const config = manager.buildConfig({rules});
345+
const config = manager.buildConfig({rules, nodeVersion: '12'});
331346
t.deepEqual(config.rules, rules);
332347
});
333348

0 commit comments

Comments
 (0)