Skip to content

Commit 98dee9a

Browse files
pvdlgsindresorhus
authored andcommitted
Respect nodeVersion option set in override block (#345)
1 parent e783704 commit 98dee9a

File tree

9 files changed

+116
-23
lines changed

9 files changed

+116
-23
lines changed

lib/options-manager.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ const mergeWithPkgConf = opts => {
121121
opts.cwd = path.resolve(opts.cwd);
122122
const conf = pkgConf.sync('xo', {cwd: opts.cwd, skipOnFalse: true});
123123
const engines = pkgConf.sync('engines', {cwd: opts.cwd});
124-
return Object.assign({}, conf, {engines}, opts);
124+
return Object.assign({}, conf, {nodeVersion: engines && engines.node && semver.validRange(engines.node)}, opts);
125125
};
126126

127127
const normalizeSpaces = opts => typeof opts.space === 'number' ? opts.space : 2;
@@ -176,11 +176,11 @@ const buildConfig = opts => {
176176
);
177177
const spaces = normalizeSpaces(opts);
178178

179-
if (opts.engines && opts.engines.node && semver.validRange(opts.engines.node)) {
179+
if (opts.nodeVersion) {
180180
for (const rule of Object.keys(ENGINE_RULES)) {
181181
// Use the rule value for the highest version that is lower or equal to the oldest version of Node.js supported
182182
for (const minVersion of Object.keys(ENGINE_RULES[rule]).sort(semver.compare)) {
183-
if (!semver.intersects(opts.engines.node, `<${minVersion}`)) {
183+
if (!semver.intersects(opts.nodeVersion, `<${minVersion}`)) {
184184
config.rules[rule] = ENGINE_RULES[rule][minVersion];
185185
}
186186
}

main.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,8 @@ if (input[0] === '-') {
129129

130130
if (opts.nodeVersion) {
131131
if (opts.nodeVersion === 'false') {
132-
opts.engines = false;
133-
} else if (semver.validRange(opts.nodeVersion)) {
134-
opts.engines = {node: opts.nodeVersion};
135-
} else {
132+
opts.nodeVersion = false;
133+
} else if (!semver.validRange(opts.nodeVersion)) {
136134
console.error('The `node-engine` option must be a valid semver range (for example `>=6`)');
137135
process.exit(1);
138136
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "application-name",
3+
"version": "0.0.1",
4+
"engines": {
5+
"node": ">=6.0.0"
6+
},
7+
"xo": {
8+
"overrides": [
9+
{
10+
"files": "*-transpile.js",
11+
"nodeVersion": ">=8.0.0"
12+
}
13+
]
14+
}
15+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const promise = new Promise(resolve => {
2+
resolve('test');
3+
});
4+
5+
function example() {
6+
return promise.then(console.log);
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const promise = new Promise(resolve => {
2+
resolve('test');
3+
});
4+
5+
function example() {
6+
return promise.then(console.log);
7+
}

test/fixtures/engines/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
"name": "application-name",
33
"version": "0.0.1",
44
"engines": {
5-
"node": ">=6"
5+
"node": ">=6.0.0"
66
}
77
}

test/lint-files.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ import fn from '..';
44

55
process.chdir(__dirname);
66

7+
const hasRule = (results, filePath, ruleId) => {
8+
const result = results.find(x => x.filePath === filePath);
9+
return result ? result.messages.some(x => x.ruleId === ruleId) : false;
10+
};
11+
712
test('only accepts whitelisted extensions', async t => {
813
// Markdown files will always produce linter errors and will not be going away
914
const mdGlob = path.join(__dirname, '..', '*.md');
@@ -94,3 +99,24 @@ test('multiple negative patterns should act as positive patterns', async t => {
9499

95100
t.deepEqual(paths, ['!!unicorn.js', '!unicorn.js']);
96101
});
102+
103+
test('enable rules based on nodeVersion', async t => {
104+
const {results} = await fn.lintFiles('**/*', {cwd: 'fixtures/engines-overrides'});
105+
106+
// The transpiled file (as specified in `overrides`) should use `await`
107+
t.true(
108+
hasRule(
109+
results,
110+
path.resolve('fixtures/engines-overrides/promise-then-transpile.js'),
111+
'promise/prefer-await-to-then'
112+
)
113+
);
114+
// The non transpiled files can use `.then`
115+
t.false(
116+
hasRule(
117+
results,
118+
path.resolve('fixtures/engines-overrides/promise-then.js'),
119+
'promise/prefer-await-to-then'
120+
)
121+
);
122+
});

test/lint-text.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,3 +196,43 @@ test('lint negatively gitignored files', async t => {
196196

197197
t.true(results[0].errorCount > 0);
198198
});
199+
200+
test('enable rules based on nodeVersion', async t => {
201+
const cwd = path.join(__dirname, 'fixtures', 'engines-overrides');
202+
const filename = path.join(cwd, 'promise-then.js');
203+
const text = await readFile(filename, 'utf-8');
204+
205+
let {results} = fn.lintText(text, {nodeVersion: '>=8.0.0'});
206+
t.true(hasRule(results, 'promise/prefer-await-to-then'));
207+
208+
({results} = fn.lintText(text, {nodeVersion: '>=6.0.0'}));
209+
t.false(hasRule(results, 'promise/prefer-await-to-then'));
210+
});
211+
212+
test('enable rules based on nodeVersion in override', async t => {
213+
const cwd = path.join(__dirname, 'fixtures', 'engines-overrides');
214+
const filename = path.join(cwd, 'promise-then.js');
215+
const text = await readFile(filename, 'utf-8');
216+
217+
let {results} = fn.lintText(text, {
218+
nodeVersion: '>=8.0.0',
219+
filename: 'promise-then.js',
220+
overrides: [
221+
{
222+
files: 'promise-*.js',
223+
nodeVersion: '>=6.0.0'
224+
}
225+
]});
226+
t.false(hasRule(results, 'promise/prefer-await-to-then'));
227+
228+
({results} = fn.lintText(text, {
229+
nodeVersion: '>=6.0.0',
230+
filename: 'promise-then.js',
231+
overrides: [
232+
{
233+
files: 'promise-*.js',
234+
nodeVersion: '>=8.0.0'
235+
}
236+
]}));
237+
t.true(hasRule(results, 'promise/prefer-await-to-then'));
238+
});

test/options-manager.js

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,8 @@ test('buildConfig: engines: undefined', t => {
207207
t.is(config.rules['promise/prefer-await-to-then'], undefined);
208208
});
209209

210-
test('buildConfig: engines: false', t => {
211-
const config = manager.buildConfig({engines: false});
210+
test('buildConfig: nodeVersion: false', t => {
211+
const config = manager.buildConfig({nodeVersion: false});
212212

213213
// Do not include any Node.js version specific rules
214214
t.is(config.rules['prefer-spread'], undefined);
@@ -217,8 +217,8 @@ test('buildConfig: engines: false', t => {
217217
t.is(config.rules['promise/prefer-await-to-then'], undefined);
218218
});
219219

220-
test('buildConfig: engines: invalid range', t => {
221-
const config = manager.buildConfig({engines: {node: '4'}});
220+
test('buildConfig: nodeVersion: invalid range', t => {
221+
const config = manager.buildConfig({nodeVersion: '4'});
222222

223223
// Do not include any Node.js version specific rules
224224
t.is(config.rules['prefer-spread'], undefined);
@@ -227,8 +227,8 @@ test('buildConfig: engines: invalid range', t => {
227227
t.is(config.rules['promise/prefer-await-to-then'], undefined);
228228
});
229229

230-
test('buildConfig: engines: >=8', t => {
231-
const config = manager.buildConfig({engines: {node: '>=8'}});
230+
test('buildConfig: nodeVersion: >=8', t => {
231+
const config = manager.buildConfig({nodeVersion: '>=8'});
232232

233233
// Include rules for Node.js 8 and above
234234
t.is(config.rules['promise/prefer-await-to-then'], 'error');
@@ -400,47 +400,47 @@ test('groupConfigs', t => {
400400
test('mergeWithPkgConf: use child if closest', t => {
401401
const cwd = path.resolve('fixtures', 'nested', 'child');
402402
const result = manager.mergeWithPkgConf({cwd});
403-
const expected = Object.assign({}, childConfig.xo, {cwd}, {engines: {}});
403+
const expected = Object.assign({}, childConfig.xo, {cwd, nodeVersion: undefined});
404404
t.deepEqual(result, expected);
405405
});
406406

407407
test('mergeWithPkgConf: use parent if closest', t => {
408408
const cwd = path.resolve('fixtures', 'nested');
409409
const result = manager.mergeWithPkgConf({cwd});
410-
const expected = Object.assign({}, parentConfig.xo, {cwd}, {engines: {}});
410+
const expected = Object.assign({}, parentConfig.xo, {cwd, nodeVersion: undefined});
411411
t.deepEqual(result, expected);
412412
});
413413

414414
test('mergeWithPkgConf: use parent if child is ignored', t => {
415415
const cwd = path.resolve('fixtures', 'nested', 'child-ignore');
416416
const result = manager.mergeWithPkgConf({cwd});
417-
const expected = Object.assign({}, parentConfig.xo, {cwd}, {engines: {}});
417+
const expected = Object.assign({}, parentConfig.xo, {cwd, nodeVersion: undefined});
418418
t.deepEqual(result, expected);
419419
});
420420

421421
test('mergeWithPkgConf: use child if child is empty', t => {
422422
const cwd = path.resolve('fixtures', 'nested', 'child-empty');
423423
const result = manager.mergeWithPkgConf({cwd});
424-
t.deepEqual(result, {cwd, engines: {}});
424+
t.deepEqual(result, {nodeVersion: undefined, cwd});
425425
});
426426

427427
test('mergeWithPkgConf: read engines from package.json', t => {
428428
const cwd = path.resolve('fixtures', 'engines');
429429
const result = manager.mergeWithPkgConf({cwd});
430-
const expected = Object.assign({}, {engines: enginesConfig.engines}, {cwd});
430+
const expected = {nodeVersion: enginesConfig.engines.node, cwd};
431431
t.deepEqual(result, expected);
432432
});
433433

434434
test('mergeWithPkgConf: XO engine options supersede package.json\'s', t => {
435435
const cwd = path.resolve('fixtures', 'engines');
436-
const result = manager.mergeWithPkgConf({cwd, engines: {node: '>=8'}});
437-
const expected = Object.assign({}, {engines: {node: '>=8'}}, {cwd});
436+
const result = manager.mergeWithPkgConf({cwd, nodeVersion: '>=8'});
437+
const expected = {nodeVersion: '>=8', cwd};
438438
t.deepEqual(result, expected);
439439
});
440440

441441
test('mergeWithPkgConf: XO engine options false supersede package.json\'s', t => {
442442
const cwd = path.resolve('fixtures', 'engines');
443-
const result = manager.mergeWithPkgConf({cwd, engines: false});
444-
const expected = Object.assign({}, {engines: false}, {cwd});
443+
const result = manager.mergeWithPkgConf({cwd, nodeVersion: false});
444+
const expected = {nodeVersion: false, cwd};
445445
t.deepEqual(result, expected);
446446
});

0 commit comments

Comments
 (0)