Skip to content

Commit 0480d80

Browse files
authored
Move from deprecated ESLint.CLIEngine to ESLint (#534)
1 parent 9934b84 commit 0480d80

8 files changed

Lines changed: 443 additions & 293 deletions

File tree

cli-main.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,8 @@ if (process.env.GITHUB_ACTIONS && !options.fix && !options.reporter) {
149149
options.quiet = true;
150150
}
151151

152-
const log = report => {
153-
const reporter = options.reporter || process.env.GITHUB_ACTIONS ? xo.getFormatter(options.reporter || 'compact') : formatterPretty;
152+
const log = async report => {
153+
const reporter = options.reporter || process.env.GITHUB_ACTIONS ? await xo.getFormatter(options.reporter || 'compact') : formatterPretty;
154154
process.stdout.write(reporter(report.results));
155155
process.exitCode = report.errorCount === 0 ? 0 : 1;
156156
};
@@ -186,18 +186,18 @@ if (options.nodeVersion) {
186186
process.exit(1);
187187
}
188188

189-
options.filename = options.printConfig;
190-
const config = xo.getConfig(options);
189+
options.filePath = options.printConfig;
190+
const config = await xo.getConfig(options);
191191
console.log(JSON.stringify(config, undefined, '\t'));
192192
} else if (options.stdin) {
193193
const stdin = await getStdin();
194194

195195
if (options.stdinFilename) {
196-
options.filename = options.stdinFilename;
196+
options.filePath = options.stdinFilename;
197197
}
198198

199199
if (options.fix) {
200-
const result = xo.lintText(stdin, options).results[0];
200+
const {results: [result]} = await xo.lintText(stdin, options);
201201
// If there is no output, pass the stdin back out
202202
process.stdout.write((result && result.output) || stdin);
203203
return;
@@ -208,18 +208,18 @@ if (options.nodeVersion) {
208208
process.exit(1);
209209
}
210210

211-
log(xo.lintText(stdin, options));
211+
await log(await xo.lintText(stdin, options));
212212
} else {
213213
const report = await xo.lintFiles(input, options);
214214

215215
if (options.fix) {
216-
xo.outputFixes(report);
216+
await xo.outputFixes(report);
217217
}
218218

219219
if (options.open) {
220220
openReport(report);
221221
}
222222

223-
log(report);
223+
await log(report);
224224
}
225225
})();

index.js

Lines changed: 99 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
'use strict';
22
const path = require('path');
3-
const eslint = require('eslint');
3+
const {ESLint} = require('eslint');
44
const globby = require('globby');
55
const isEqual = require('lodash/isEqual');
66
const uniq = require('lodash/uniq');
7+
const pick = require('lodash/pick');
8+
const omit = require('lodash/omit');
79
const micromatch = require('micromatch');
810
const arrify = require('arrify');
911
const pReduce = require('p-reduce');
12+
const pMap = require('p-map');
1013
const {cosmiconfig, defaultLoaders} = require('cosmiconfig');
11-
const {CONFIG_FILES, MODULE_NAME, DEFAULT_IGNORES} = require('./lib/constants');
14+
const defineLazyProperty = require('define-lazy-prop');
15+
const pFilter = require('p-filter');
16+
const {CONFIG_FILES, MODULE_NAME, DEFAULT_IGNORES, LINT_METHOD_OPTIONS} = require('./lib/constants');
1217
const {
1318
normalizeOptions,
1419
getIgnores,
@@ -37,18 +42,68 @@ const mergeReports = reports => {
3742
};
3843
};
3944

40-
const processReport = (report, options) => {
41-
report.results = options.quiet ? eslint.CLIEngine.getErrorResults(report.results) : report.results;
42-
return report;
45+
const getReportStatistics = results => {
46+
let errorCount = 0;
47+
let warningCount = 0;
48+
let fixableErrorCount = 0;
49+
let fixableWarningCount = 0;
50+
51+
for (const {
52+
errorCount: currentErrorCount,
53+
warningCount: currentWarningCount,
54+
fixableErrorCount: currentFixableErrorCount,
55+
fixableWarningCount: currentFixableWarningCount
56+
} of results) {
57+
errorCount += currentErrorCount;
58+
warningCount += currentWarningCount;
59+
fixableErrorCount += currentFixableErrorCount;
60+
fixableWarningCount += currentFixableWarningCount;
61+
}
62+
63+
return {
64+
errorCount,
65+
warningCount,
66+
fixableErrorCount,
67+
fixableWarningCount
68+
};
69+
};
70+
71+
const processReport = (report, {isQuiet = false} = {}) => {
72+
if (isQuiet) {
73+
report = ESLint.getErrorResults(report);
74+
}
75+
76+
const result = {
77+
results: report,
78+
...getReportStatistics(report)
79+
};
80+
81+
defineLazyProperty(result, 'usedDeprecatedRules', () => {
82+
const seenRules = new Set();
83+
const rules = [];
84+
85+
for (const {usedDeprecatedRules} of report) {
86+
for (const rule of usedDeprecatedRules) {
87+
if (seenRules.has(rule.ruleId)) {
88+
continue;
89+
}
90+
91+
seenRules.add(rule.ruleId);
92+
rules.push(rule);
93+
}
94+
}
95+
96+
return rules;
97+
});
98+
99+
return result;
43100
};
44101

45-
const runEslint = (paths, options) => {
46-
const engine = new eslint.CLIEngine(options);
47-
const report = engine.executeOnFiles(
48-
paths.filter(path => !engine.isPathIgnored(path)),
49-
options
50-
);
51-
return processReport(report, options);
102+
const runEslint = async (paths, options, processorOptions) => {
103+
const engine = new ESLint(options);
104+
105+
const report = await engine.lintFiles(await pFilter(paths, async path => !(await engine.isPathIgnored(path))));
106+
return processReport(report, processorOptions);
52107
};
53108

54109
const globFiles = async (patterns, {ignores, extensions, cwd}) => (
@@ -57,30 +112,30 @@ const globFiles = async (patterns, {ignores, extensions, cwd}) => (
57112
{ignore: ignores, gitignore: true, cwd}
58113
)).filter(file => extensions.includes(path.extname(file).slice(1))).map(file => path.resolve(cwd, file));
59114

60-
const getConfig = options => {
115+
const getConfig = async options => {
61116
const {options: foundOptions, prettierOptions} = mergeWithFileConfig(normalizeOptions(options));
62117
options = buildConfig(foundOptions, prettierOptions);
63-
const engine = new eslint.CLIEngine(options);
64-
return engine.getConfigForFile(options.filename);
118+
const engine = new ESLint(omit(options, LINT_METHOD_OPTIONS));
119+
return engine.calculateConfigForFile(options.filePath);
65120
};
66121

67-
const lintText = (string, options) => {
68-
const {options: foundOptions, prettierOptions} = mergeWithFileConfig(normalizeOptions(options));
69-
options = buildConfig(foundOptions, prettierOptions);
122+
const lintText = async (string, inputOptions = {}) => {
123+
const {options: foundOptions, prettierOptions} = mergeWithFileConfig(normalizeOptions(inputOptions));
124+
const options = buildConfig(foundOptions, prettierOptions);
70125

71-
if (options.ignores && !isEqual(getIgnores({}), options.ignores) && typeof options.filename !== 'string') {
72-
throw new Error('The `ignores` option requires the `filename` option to be defined.');
126+
if (options.baseConfig.ignorePatterns && !isEqual(getIgnores({}), options.baseConfig.ignorePatterns) && typeof options.filePath !== 'string') {
127+
throw new Error('The `ignores` option requires the `filePath` option to be defined.');
73128
}
74129

75-
const engine = new eslint.CLIEngine(options);
130+
const engine = new ESLint(omit(options, LINT_METHOD_OPTIONS));
76131

77-
if (options.filename) {
78-
const filename = path.relative(options.cwd, options.filename);
132+
if (options.filePath) {
133+
const filename = path.relative(options.cwd, options.filePath);
79134

80135
if (
81-
micromatch.isMatch(filename, options.ignores) ||
82-
globby.gitignore.sync({cwd: options.cwd, ignore: options.ignores})(options.filename) ||
83-
engine.isPathIgnored(options.filename)
136+
micromatch.isMatch(filename, options.baseConfig.ignorePatterns) ||
137+
globby.gitignore.sync({cwd: options.cwd, ignore: options.baseConfig.ignorePatterns})(options.filePath) ||
138+
await engine.isPathIgnored(options.filePath)
84139
) {
85140
return {
86141
errorCount: 0,
@@ -95,39 +150,42 @@ const lintText = (string, options) => {
95150
}
96151
}
97152

98-
const report = engine.executeOnText(string, options.filename);
153+
const report = await engine.lintText(string, pick(options, LINT_METHOD_OPTIONS));
99154

100-
return processReport(report, options);
155+
return processReport(report, {isQuiet: inputOptions.quiet});
101156
};
102157

103-
const lintFiles = async (patterns, options = {}) => {
104-
options.cwd = path.resolve(options.cwd || process.cwd());
105-
const configExplorer = cosmiconfig(MODULE_NAME, {searchPlaces: CONFIG_FILES, loaders: {noExt: defaultLoaders['.json']}, stopDir: options.cwd});
158+
const lintFiles = async (patterns, inputOptions = {}) => {
159+
inputOptions.cwd = path.resolve(inputOptions.cwd || process.cwd());
160+
const configExplorer = cosmiconfig(MODULE_NAME, {searchPlaces: CONFIG_FILES, loaders: {noExt: defaultLoaders['.json']}, stopDir: inputOptions.cwd});
106161

107162
const configFiles = (await Promise.all(
108163
(await globby(
109164
CONFIG_FILES.map(configFile => `**/${configFile}`),
110-
{ignore: DEFAULT_IGNORES, gitignore: true, cwd: options.cwd}
111-
)).map(async configFile => configExplorer.load(path.resolve(options.cwd, configFile)))
165+
{ignore: DEFAULT_IGNORES, gitignore: true, cwd: inputOptions.cwd}
166+
)).map(async configFile => configExplorer.load(path.resolve(inputOptions.cwd, configFile)))
112167
)).filter(Boolean);
113168

114169
const paths = configFiles.length > 0 ?
115170
await pReduce(
116171
configFiles,
117172
async (paths, {filepath, config}) =>
118-
[...paths, ...(await globFiles(patterns, {...mergeOptions(options, config), cwd: path.dirname(filepath)}))],
173+
[...paths, ...(await globFiles(patterns, {...mergeOptions(inputOptions, config), cwd: path.dirname(filepath)}))],
119174
[]) :
120-
await globFiles(patterns, mergeOptions(options));
175+
await globFiles(patterns, mergeOptions(inputOptions));
176+
177+
return mergeReports(await pMap(await mergeWithFileConfigs(uniq(paths), inputOptions, configFiles), async ({files, options, prettierOptions}) => runEslint(files, buildConfig(options, prettierOptions), {isQuiet: options.quiet})));
178+
};
121179

122-
return mergeReports((await mergeWithFileConfigs(uniq(paths), options, configFiles)).map(
123-
({files, options, prettierOptions}) => runEslint(files, buildConfig(options, prettierOptions)))
124-
);
180+
const getFormatter = async name => {
181+
const {format} = await new ESLint().loadFormatter(name);
182+
return format;
125183
};
126184

127185
module.exports = {
128-
getFormatter: eslint.CLIEngine.getFormatter,
129-
getErrorResults: eslint.CLIEngine.getErrorResults,
130-
outputFixes: eslint.CLIEngine.outputFixes,
186+
getFormatter,
187+
getErrorResults: ESLint.getErrorResults,
188+
outputFixes: async ({results}) => ESLint.outputFixes(results),
131189
getConfig,
132190
lintText,
133191
lintFiles

lib/constants.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ const TSCONFIG_DEFFAULTS = {
137137

138138
const CACHE_DIR_NAME = 'xo-linter';
139139

140+
const LINT_METHOD_OPTIONS = ['filePath', 'warnIgnored'];
141+
140142
module.exports = {
141143
DEFAULT_IGNORES,
142144
DEFAULT_EXTENSION,
@@ -147,5 +149,6 @@ module.exports = {
147149
CONFIG_FILES,
148150
MERGE_OPTIONS_CONCAT,
149151
TSCONFIG_DEFFAULTS,
150-
CACHE_DIR_NAME
152+
CACHE_DIR_NAME,
153+
LINT_METHOD_OPTIONS
151154
};

0 commit comments

Comments
 (0)