Skip to content

Commit 3e4b251

Browse files
committed
feature(putout) add recursive read of config
1 parent 458d3f7 commit 3e4b251

File tree

8 files changed

+171
-34
lines changed

8 files changed

+171
-34
lines changed

.putout.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
{
2+
"match": {
3+
"**/packages/plugin-*": {
4+
"putout": "on"
5+
}
6+
},
27
"rules": {
3-
"putout": "on",
48
"remove-useless-spread/object": ["on", {
59
"exclude": "module.exports.rules = __"
610
}]

packages/plugin-extract-object-properties/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ const {isIdentifier} = a.types;
3737

3838
```js
3939
const {
40-
operate,
40+
operator,
4141
types,
4242
} = a;
4343

44-
const {replaceWith} = operate;
44+
const {replaceWith} = operator;
4545
const {isIdentifier} = types;
4646
```
4747

packages/plugin-regexp/.putout.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
{
2+
"rules": {
3+
"putout": "off"
4+
},
25
"match": {
36
"*.md": {
47
"regexp": "off"

packages/putout/lib/parse-options/index.js

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ const {readdirSync} = require('fs');
55
const {
66
dirname,
77
join,
8-
relative,
98
} = require('path');
109

1110
const once = require('once');
@@ -15,9 +14,9 @@ const findUp = require('find-up');
1514
const parseMatch = require('./parse-match');
1615
const defaultOptions = require('../../putout.json');
1716
const merge = require('../merge');
17+
const recursiveRead = require('./recursive-read');
1818

1919
const home = homedir();
20-
const cwd = process.cwd();
2120

2221
module.exports = (info = {}) => {
2322
const {
@@ -29,29 +28,33 @@ module.exports = (info = {}) => {
2928
readCodeMods = _readCodeMods,
3029
} = info;
3130

32-
const [dir, customOptions] = readOptions(dirname(name));
31+
const [dir, customOptions] = readOptions(name);
3332
const homeOptions = readHomeOptions();
34-
const relativeName = relative(cwd, name);
33+
const defaultMatch = parseMatch(name, defaultOptions.match);
3534

36-
const defaultMatch = parseMatch(relativeName, defaultOptions.match);
37-
const mergedOptions = merge(
35+
const optionsList = [
3836
defaultOptions,
3937
homeOptions,
4038
defaultMatch,
4139
customOptions,
4240
options,
41+
];
42+
43+
const mergedOptions = merge(...optionsList);
44+
const mergedDefaultsMatch = merge(
45+
mergedOptions,
46+
parseMatch(name, mergedOptions.match),
47+
options,
4348
);
4449

45-
const mergedMatch = parseMatch(relativeName, mergedOptions.match);
46-
const customMatch = parseMatch(relativeName, options.match);
50+
const mergedMatch = merge(customOptions, options, parseMatch(name, options.match));
4751

4852
const resultOptions = merge(
4953
readCodeMods(),
5054
readRules(dir, rulesdir),
5155
mergedOptions,
56+
mergedDefaultsMatch,
5257
mergedMatch,
53-
options,
54-
customMatch,
5558
);
5659

5760
return {
@@ -60,17 +63,13 @@ module.exports = (info = {}) => {
6063
};
6164
};
6265

63-
function _readOptions(cwd) {
64-
const putoutPath = findUp.sync('.putout.json', {
65-
cwd,
66-
});
66+
function _readOptions(name) {
67+
const [dir, options] = recursiveRead(name, '.putout.json');
6768

68-
if (putoutPath)
69-
return [
70-
dirname(putoutPath),
71-
require(putoutPath),
72-
];
69+
if (dir)
70+
return [dir, options];
7371

72+
const cwd = dirname(name);
7473
const packagePath = findUp.sync('package.json', {
7574
cwd,
7675
});
@@ -79,6 +78,7 @@ function _readOptions(cwd) {
7978
return [
8079
dirname(packagePath),
8180
require(packagePath).putout || {},
81+
{},
8282
];
8383

8484
return [

packages/putout/lib/parse-options/index.spec.js

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -426,15 +426,14 @@ test('putout: parseOptions: read rules: error', (t) => {
426426
t.end();
427427
});
428428

429-
test('putout: parseOptions: readOptions: error', (t) => {
429+
test('putout: parseOptions: readOptions: do not returns dir, load rules can not read', (t) => {
430430
const empty = {};
431431

432432
const readHomeOptions = stub().returns(empty);
433433
const readCodeMods = stub().returns(empty);
434-
const sync = stub();
434+
const readOptions = stub().returns(['', empty]);
435435

436436
mockRequire('../../putout.json', empty);
437-
mockRequire('find-up', {sync});
438437

439438
const {readdirSync} = fs;
440439
fs.readdirSync = () => {
@@ -459,6 +458,7 @@ test('putout: parseOptions: readOptions: error', (t) => {
459458
options,
460459
readHomeOptions,
461460
readCodeMods,
461+
readOptions,
462462
rulesdir: '.',
463463
});
464464

@@ -486,6 +486,7 @@ test('putout: parseOptions: readOptions: .putout.json', (t) => {
486486

487487
const readHomeOptions = stub().returns(empty);
488488
const readCodeMods = stub().returns(empty);
489+
const readOptions = stub().returns(['../..', {}]);
489490
const sync = (a) => {
490491
if (a === '.putout.json')
491492
return '../../putout.json';
@@ -519,6 +520,7 @@ test('putout: parseOptions: readOptions: .putout.json', (t) => {
519520
options,
520521
readHomeOptions,
521522
readCodeMods,
523+
readOptions,
522524
rulesdir: '.',
523525
});
524526

@@ -541,21 +543,14 @@ test('putout: parseOptions: readOptions: .putout.json', (t) => {
541543
t.end();
542544
});
543545

544-
test('putout: parseOptions: readOptions: package.json', (t) => {
546+
test('putout: parseOptions: can not readd dir', (t) => {
545547
const empty = {};
546548

547549
const readHomeOptions = stub().returns(empty);
548550
const readCodeMods = stub().returns(empty);
549-
const sync = (a) => {
550-
if (a === 'package.json')
551-
return './package.json';
552-
553-
return null;
554-
};
551+
const readOptions = stub().returns(['.', empty]);
555552

556553
mockRequire('../../putout.json', empty);
557-
mockRequire('./package.json', empty);
558-
mockRequire('find-up', {sync});
559554

560555
const {readdirSync} = fs;
561556
fs.readdirSync = () => {
@@ -580,6 +575,7 @@ test('putout: parseOptions: readOptions: package.json', (t) => {
580575
options,
581576
readHomeOptions,
582577
readCodeMods,
578+
readOptions,
583579
rulesdir: '.',
584580
});
585581

@@ -671,10 +667,12 @@ test('putout: parseOptions: readHomeOptions', (t) => {
671667
test('putout: parseOptions: no args', (t) => {
672668
const empty = {};
673669
const {homedir} = os;
670+
const read = stub().returns(['', {}]);
674671
const sync = stub();
675672

676673
os.homedir = stub().returns('/');
677674

675+
mockRequire('./recursive-read', read);
678676
mockRequire('./package.json', empty);
679677
mockRequire('../../putout.json', empty);
680678
mockRequire('find-up', {
@@ -696,3 +694,52 @@ test('putout: parseOptions: no args', (t) => {
696694
t.deepEqual(result, expected);
697695
t.end();
698696
});
697+
698+
test('putout: parseOptions: readOptions: package.json', (t) => {
699+
const empty = {};
700+
701+
const readHomeOptions = stub().returns(empty);
702+
const readCodeMods = stub().returns(empty);
703+
const read = stub().returns(['', {}]);
704+
705+
mockRequire('../../putout.json', empty);
706+
mockRequire('./recursive-read', read);
707+
708+
const parseOptions = reRequire('.');
709+
710+
const options = {
711+
rules: {
712+
'remove-only': 'off',
713+
},
714+
match: {
715+
'*.spec.js': {
716+
'remove-only': 'on',
717+
},
718+
},
719+
};
720+
721+
const result = parseOptions({
722+
name: 'parse-options.spec.js',
723+
options,
724+
readHomeOptions,
725+
readCodeMods,
726+
});
727+
728+
delete result.dir;
729+
730+
const expected = {
731+
match: {
732+
'*.spec.js': {
733+
'remove-only': 'on',
734+
},
735+
},
736+
rules: {
737+
'remove-only': 'on',
738+
},
739+
};
740+
741+
stopAll();
742+
743+
t.deepEqual(result, expected);
744+
t.end();
745+
});

packages/putout/lib/parse-options/parse-match.spec.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,3 +206,25 @@ test('putout: parse-match: extension: long path', (t) => {
206206
t.end();
207207
});
208208

209+
test('putout: parse-match: similar matches', (t) => {
210+
const match = {
211+
'packages/plugin-*': {
212+
putout: 'on',
213+
},
214+
'packages/plugin-putout/README.md': {
215+
putout: 'off',
216+
},
217+
};
218+
219+
const expected = {
220+
rules: {
221+
putout: 'off',
222+
},
223+
};
224+
225+
const result = parseMatch('packages/plugin-putout/README.md', match);
226+
227+
t.deepEqual(result, expected, 'should equal');
228+
t.end();
229+
});
230+
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
'use strict';
2+
3+
const {join, dirname} = require('path');
4+
const tryCatch = require('try-catch');
5+
6+
const merge = require('../merge');
7+
const parseMatch = require('./parse-match');
8+
9+
module.exports = (name, configName) => {
10+
let mainDir;
11+
12+
let dir = name;
13+
const optionsList = [];
14+
15+
while (dir !== '/' && dir !== '.') {
16+
const path = join(dir, configName);
17+
const [, nextResult] = tryCatch(require, path);
18+
19+
if (nextResult) {
20+
mainDir = mainDir || dir;
21+
optionsList.push(nextResult);
22+
}
23+
24+
dir = dirname(dir);
25+
}
26+
27+
let mergedOptions = merge(...optionsList);
28+
29+
for (const currentOptions of optionsList.reverse())
30+
mergedOptions = merge(
31+
mergedOptions,
32+
currentOptions,
33+
parseMatch(
34+
name,
35+
currentOptions.match,
36+
),
37+
);
38+
39+
return [mainDir, mergedOptions];
40+
};
41+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
'use strict';
2+
3+
const {join} = require('path');
4+
5+
const test = require('supertape');
6+
const read = require('./recursive-read');
7+
8+
test('putout: parse-options: recursive read: dir', (t) => {
9+
const [dir] = read(__filename, '.putout.json');
10+
11+
t.equal(dir, join(__dirname, '../..'));
12+
t.end();
13+
});
14+
15+
test('putout: parse-options: called from eslint', (t) => {
16+
const [dir] = read('<input>', '.putout.json');
17+
18+
t.notOk(dir);
19+
t.end();
20+
});

0 commit comments

Comments
 (0)