eslint 7.0.0-alpha.1 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +329 -0
- package/README.md +7 -7
- package/bin/eslint.js +115 -77
- package/conf/category-list.json +2 -3
- package/conf/environments.js +2 -1
- package/conf/eslint-recommended.js +3 -0
- package/lib/api.js +2 -0
- package/lib/cli-engine/cascading-config-array-factory.js +16 -2
- package/lib/cli-engine/cli-engine.js +53 -47
- package/lib/cli-engine/config-array/config-array.js +30 -1
- package/lib/cli-engine/config-array/ignore-pattern.js +7 -1
- package/lib/cli-engine/config-array-factory.js +244 -235
- package/lib/cli.js +181 -95
- package/lib/eslint/eslint.js +656 -0
- package/lib/eslint/index.js +7 -0
- package/lib/init/autoconfig.js +4 -4
- package/lib/init/config-file.js +2 -2
- package/lib/init/config-initializer.js +2 -4
- package/lib/init/source-code-utils.js +2 -2
- package/lib/linter/node-event-generator.js +2 -2
- package/lib/options.js +0 -1
- package/lib/rule-tester/rule-tester.js +178 -23
- package/lib/rules/accessor-pairs.js +2 -2
- package/lib/rules/array-callback-return.js +3 -18
- package/lib/rules/arrow-body-style.js +26 -15
- package/lib/rules/callback-return.js +4 -0
- package/lib/rules/camelcase.js +38 -1
- package/lib/rules/comma-style.js +3 -8
- package/lib/rules/computed-property-spacing.js +2 -2
- package/lib/rules/curly.js +124 -40
- package/lib/rules/func-call-spacing.js +4 -3
- package/lib/rules/func-names.js +31 -24
- package/lib/rules/getter-return.js +2 -12
- package/lib/rules/global-require.js +4 -0
- package/lib/rules/handle-callback-err.js +4 -0
- package/lib/rules/id-blacklist.js +140 -64
- package/lib/rules/id-length.js +14 -4
- package/lib/rules/indent-legacy.js +0 -16
- package/lib/rules/key-spacing.js +1 -1
- package/lib/rules/new-cap.js +1 -1
- package/lib/rules/newline-per-chained-call.js +6 -3
- package/lib/rules/no-alert.js +5 -3
- package/lib/rules/no-buffer-constructor.js +4 -0
- package/lib/rules/no-dupe-else-if.js +1 -1
- package/lib/rules/no-empty-function.js +4 -2
- package/lib/rules/no-eval.js +3 -2
- package/lib/rules/no-extra-bind.js +1 -1
- package/lib/rules/no-extra-boolean-cast.js +168 -38
- package/lib/rules/no-extra-parens.js +9 -5
- package/lib/rules/no-implied-eval.js +83 -101
- package/lib/rules/no-import-assign.js +1 -1
- package/lib/rules/no-inner-declarations.js +31 -39
- package/lib/rules/no-lone-blocks.js +1 -1
- package/lib/rules/no-magic-numbers.js +72 -37
- package/lib/rules/no-mixed-requires.js +4 -0
- package/lib/rules/no-new-object.js +15 -3
- package/lib/rules/no-new-require.js +4 -0
- package/lib/rules/no-new-wrappers.js +1 -1
- package/lib/rules/no-obj-calls.js +24 -5
- package/lib/rules/no-path-concat.js +4 -0
- package/lib/rules/no-plusplus.js +39 -3
- package/lib/rules/no-process-env.js +4 -0
- package/lib/rules/no-process-exit.js +4 -0
- package/lib/rules/no-prototype-builtins.js +1 -1
- package/lib/rules/no-restricted-modules.js +52 -18
- package/lib/rules/no-setter-return.js +1 -1
- package/lib/rules/no-sync.js +4 -0
- package/lib/rules/no-underscore-dangle.js +1 -1
- package/lib/rules/no-unexpected-multiline.js +22 -12
- package/lib/rules/no-useless-concat.js +1 -1
- package/lib/rules/operator-assignment.js +3 -3
- package/lib/rules/operator-linebreak.js +4 -16
- package/lib/rules/prefer-numeric-literals.js +3 -3
- package/lib/rules/prefer-object-spread.js +2 -2
- package/lib/rules/require-await.js +1 -1
- package/lib/rules/space-before-function-paren.js +5 -2
- package/lib/rules/template-curly-spacing.js +59 -42
- package/lib/rules/utils/ast-utils.js +65 -4
- package/lib/rules/wrap-iife.js +54 -17
- package/lib/rules/yoda.js +101 -51
- package/lib/shared/relative-module-resolver.js +1 -0
- package/lib/shared/types.js +9 -2
- package/messages/plugin-conflict.txt +7 -0
- package/package.json +27 -26
package/lib/cli.js
CHANGED
@@ -17,105 +17,176 @@
|
|
17
17
|
|
18
18
|
const fs = require("fs"),
|
19
19
|
path = require("path"),
|
20
|
-
{
|
21
|
-
|
20
|
+
{ promisify } = require("util"),
|
21
|
+
{ ESLint } = require("./eslint"),
|
22
|
+
CLIOptions = require("./options"),
|
22
23
|
log = require("./shared/logging"),
|
23
24
|
RuntimeInfo = require("./shared/runtime-info");
|
24
25
|
|
25
26
|
const debug = require("debug")("eslint:cli");
|
26
27
|
|
28
|
+
//------------------------------------------------------------------------------
|
29
|
+
// Types
|
30
|
+
//------------------------------------------------------------------------------
|
31
|
+
|
32
|
+
/** @typedef {import("./eslint/eslint").ESLintOptions} ESLintOptions */
|
33
|
+
/** @typedef {import("./eslint/eslint").LintMessage} LintMessage */
|
34
|
+
/** @typedef {import("./eslint/eslint").LintResult} LintResult */
|
35
|
+
|
27
36
|
//------------------------------------------------------------------------------
|
28
37
|
// Helpers
|
29
38
|
//------------------------------------------------------------------------------
|
30
39
|
|
40
|
+
const mkdir = promisify(fs.mkdir);
|
41
|
+
const stat = promisify(fs.stat);
|
42
|
+
const writeFile = promisify(fs.writeFile);
|
43
|
+
|
31
44
|
/**
|
32
45
|
* Predicate function for whether or not to apply fixes in quiet mode.
|
33
46
|
* If a message is a warning, do not apply a fix.
|
34
|
-
* @param {
|
47
|
+
* @param {LintMessage} message The lint result.
|
35
48
|
* @returns {boolean} True if the lint message is an error (and thus should be
|
36
49
|
* autofixed), false otherwise.
|
37
50
|
*/
|
38
|
-
function quietFixPredicate(
|
39
|
-
return
|
51
|
+
function quietFixPredicate(message) {
|
52
|
+
return message.severity === 2;
|
40
53
|
}
|
41
54
|
|
42
55
|
/**
|
43
56
|
* Translates the CLI options into the options expected by the CLIEngine.
|
44
57
|
* @param {Object} cliOptions The CLI options to translate.
|
45
|
-
* @returns {
|
58
|
+
* @returns {ESLintOptions} The options object for the CLIEngine.
|
46
59
|
* @private
|
47
60
|
*/
|
48
|
-
function translateOptions(
|
61
|
+
function translateOptions({
|
62
|
+
cache,
|
63
|
+
cacheFile,
|
64
|
+
cacheLocation,
|
65
|
+
config,
|
66
|
+
env,
|
67
|
+
errorOnUnmatchedPattern,
|
68
|
+
eslintrc,
|
69
|
+
ext,
|
70
|
+
fix,
|
71
|
+
fixDryRun,
|
72
|
+
fixType,
|
73
|
+
global,
|
74
|
+
ignore,
|
75
|
+
ignorePath,
|
76
|
+
ignorePattern,
|
77
|
+
inlineConfig,
|
78
|
+
parser,
|
79
|
+
parserOptions,
|
80
|
+
plugin,
|
81
|
+
quiet,
|
82
|
+
reportUnusedDisableDirectives,
|
83
|
+
resolvePluginsRelativeTo,
|
84
|
+
rule,
|
85
|
+
rulesdir
|
86
|
+
}) {
|
49
87
|
return {
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
88
|
+
allowInlineConfig: inlineConfig,
|
89
|
+
cache,
|
90
|
+
cacheLocation: cacheLocation || cacheFile,
|
91
|
+
errorOnUnmatchedPattern,
|
92
|
+
extensions: ext,
|
93
|
+
fix: (fix || fixDryRun) && (quiet ? quietFixPredicate : true),
|
94
|
+
fixTypes: fixType,
|
95
|
+
ignore,
|
96
|
+
ignorePath,
|
97
|
+
overrideConfig: {
|
98
|
+
env: env && env.reduce((obj, name) => {
|
99
|
+
obj[name] = true;
|
100
|
+
return obj;
|
101
|
+
}, {}),
|
102
|
+
globals: global && global.reduce((obj, name) => {
|
103
|
+
if (name.endsWith(":true")) {
|
104
|
+
obj[name.slice(0, -5)] = "writable";
|
105
|
+
} else {
|
106
|
+
obj[name] = "readonly";
|
107
|
+
}
|
108
|
+
return obj;
|
109
|
+
}, {}),
|
110
|
+
ignorePatterns: ignorePattern,
|
111
|
+
parser,
|
112
|
+
parserOptions,
|
113
|
+
plugins: plugin,
|
114
|
+
rules: rule
|
115
|
+
},
|
116
|
+
overrideConfigFile: config,
|
117
|
+
reportUnusedDisableDirectives: reportUnusedDisableDirectives ? "error" : void 0,
|
118
|
+
resolvePluginsRelativeTo,
|
119
|
+
rulePaths: rulesdir,
|
120
|
+
useEslintrc: eslintrc
|
72
121
|
};
|
73
122
|
}
|
74
123
|
|
124
|
+
/**
|
125
|
+
* Count error messages.
|
126
|
+
* @param {LintResult[]} results The lint results.
|
127
|
+
* @returns {{errorCount:number;warningCount:number}} The number of error messages.
|
128
|
+
*/
|
129
|
+
function countErrors(results) {
|
130
|
+
let errorCount = 0;
|
131
|
+
let warningCount = 0;
|
132
|
+
|
133
|
+
for (const result of results) {
|
134
|
+
errorCount += result.errorCount;
|
135
|
+
warningCount += result.warningCount;
|
136
|
+
}
|
137
|
+
|
138
|
+
return { errorCount, warningCount };
|
139
|
+
}
|
140
|
+
|
141
|
+
/**
|
142
|
+
* Check if a given file path is a directory or not.
|
143
|
+
* @param {string} filePath The path to a file to check.
|
144
|
+
* @returns {Promise<boolean>} `true` if the given path is a directory.
|
145
|
+
*/
|
146
|
+
async function isDirectory(filePath) {
|
147
|
+
try {
|
148
|
+
return (await stat(filePath)).isDirectory();
|
149
|
+
} catch (error) {
|
150
|
+
if (error.code === "ENOENT" || error.code === "ENOTDIR") {
|
151
|
+
return false;
|
152
|
+
}
|
153
|
+
throw error;
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|
75
157
|
/**
|
76
158
|
* Outputs the results of the linting.
|
77
|
-
* @param {
|
159
|
+
* @param {ESLint} engine The ESLint instance to use.
|
78
160
|
* @param {LintResult[]} results The results to print.
|
79
161
|
* @param {string} format The name of the formatter to use or the path to the formatter.
|
80
162
|
* @param {string} outputFile The path for the output file.
|
81
|
-
* @returns {boolean} True if the printing succeeds, false if not.
|
163
|
+
* @returns {Promise<boolean>} True if the printing succeeds, false if not.
|
82
164
|
* @private
|
83
165
|
*/
|
84
|
-
function printResults(engine, results, format, outputFile) {
|
166
|
+
async function printResults(engine, results, format, outputFile) {
|
85
167
|
let formatter;
|
86
|
-
let rulesMeta;
|
87
168
|
|
88
169
|
try {
|
89
|
-
formatter = engine.
|
170
|
+
formatter = await engine.loadFormatter(format);
|
90
171
|
} catch (e) {
|
91
172
|
log.error(e.message);
|
92
173
|
return false;
|
93
174
|
}
|
94
175
|
|
95
|
-
const output = formatter(results
|
96
|
-
get rulesMeta() {
|
97
|
-
if (!rulesMeta) {
|
98
|
-
rulesMeta = {};
|
99
|
-
for (const [ruleId, rule] of engine.getRules()) {
|
100
|
-
rulesMeta[ruleId] = rule.meta;
|
101
|
-
}
|
102
|
-
}
|
103
|
-
return rulesMeta;
|
104
|
-
}
|
105
|
-
});
|
176
|
+
const output = formatter.format(results);
|
106
177
|
|
107
178
|
if (output) {
|
108
179
|
if (outputFile) {
|
109
180
|
const filePath = path.resolve(process.cwd(), outputFile);
|
110
181
|
|
111
|
-
if (
|
182
|
+
if (await isDirectory(filePath)) {
|
112
183
|
log.error("Cannot write to output file path, it is a directory: %s", outputFile);
|
113
184
|
return false;
|
114
185
|
}
|
115
186
|
|
116
187
|
try {
|
117
|
-
|
118
|
-
|
188
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
189
|
+
await writeFile(filePath, output);
|
119
190
|
} catch (ex) {
|
120
191
|
log.error("There was a problem writing the output file:\n%s", ex);
|
121
192
|
return false;
|
@@ -126,7 +197,6 @@ function printResults(engine, results, format, outputFile) {
|
|
126
197
|
}
|
127
198
|
|
128
199
|
return true;
|
129
|
-
|
130
200
|
}
|
131
201
|
|
132
202
|
//------------------------------------------------------------------------------
|
@@ -143,28 +213,33 @@ const cli = {
|
|
143
213
|
* Executes the CLI based on an array of arguments that is passed in.
|
144
214
|
* @param {string|Array|Object} args The arguments to process.
|
145
215
|
* @param {string} [text] The text to lint (used for TTY).
|
146
|
-
* @returns {
|
216
|
+
* @returns {Promise<number>} The exit code for the operation.
|
147
217
|
*/
|
148
|
-
execute(args, text) {
|
218
|
+
async execute(args, text) {
|
149
219
|
if (Array.isArray(args)) {
|
150
220
|
debug("CLI args: %o", args.slice(2));
|
151
221
|
}
|
152
|
-
|
153
|
-
let currentOptions;
|
222
|
+
let options;
|
154
223
|
|
155
224
|
try {
|
156
|
-
|
225
|
+
options = CLIOptions.parse(args);
|
157
226
|
} catch (error) {
|
158
227
|
log.error(error.message);
|
159
228
|
return 2;
|
160
229
|
}
|
161
230
|
|
162
|
-
const files =
|
231
|
+
const files = options._;
|
163
232
|
const useStdin = typeof text === "string";
|
164
233
|
|
165
|
-
if (
|
234
|
+
if (options.help) {
|
235
|
+
log.info(CLIOptions.generateHelp());
|
236
|
+
return 0;
|
237
|
+
}
|
238
|
+
if (options.version) {
|
166
239
|
log.info(RuntimeInfo.version());
|
167
|
-
|
240
|
+
return 0;
|
241
|
+
}
|
242
|
+
if (options.envInfo) {
|
168
243
|
try {
|
169
244
|
log.info(RuntimeInfo.environment());
|
170
245
|
return 0;
|
@@ -172,7 +247,9 @@ const cli = {
|
|
172
247
|
log.error(err.message);
|
173
248
|
return 2;
|
174
249
|
}
|
175
|
-
}
|
250
|
+
}
|
251
|
+
|
252
|
+
if (options.printConfig) {
|
176
253
|
if (files.length) {
|
177
254
|
log.error("The --print-config option must be used with exactly one file name.");
|
178
255
|
return 2;
|
@@ -182,58 +259,67 @@ const cli = {
|
|
182
259
|
return 2;
|
183
260
|
}
|
184
261
|
|
185
|
-
const engine = new
|
186
|
-
const fileConfig =
|
262
|
+
const engine = new ESLint(translateOptions(options));
|
263
|
+
const fileConfig =
|
264
|
+
await engine.calculateConfigForFile(options.printConfig);
|
187
265
|
|
188
266
|
log.info(JSON.stringify(fileConfig, null, " "));
|
189
267
|
return 0;
|
190
|
-
}
|
191
|
-
log.info(options.generateHelp());
|
192
|
-
} else {
|
193
|
-
debug(`Running on ${useStdin ? "text" : "files"}`);
|
194
|
-
|
195
|
-
if (currentOptions.fix && currentOptions.fixDryRun) {
|
196
|
-
log.error("The --fix option and the --fix-dry-run option cannot be used together.");
|
197
|
-
return 2;
|
198
|
-
}
|
268
|
+
}
|
199
269
|
|
200
|
-
|
201
|
-
log.error("The --fix option is not available for piped-in code; use --fix-dry-run instead.");
|
202
|
-
return 2;
|
203
|
-
}
|
270
|
+
debug(`Running on ${useStdin ? "text" : "files"}`);
|
204
271
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
272
|
+
if (options.fix && options.fixDryRun) {
|
273
|
+
log.error("The --fix option and the --fix-dry-run option cannot be used together.");
|
274
|
+
return 2;
|
275
|
+
}
|
276
|
+
if (useStdin && options.fix) {
|
277
|
+
log.error("The --fix option is not available for piped-in code; use --fix-dry-run instead.");
|
278
|
+
return 2;
|
279
|
+
}
|
280
|
+
if (options.fixType && !options.fix && !options.fixDryRun) {
|
281
|
+
log.error("The --fix-type option requires either --fix or --fix-dry-run.");
|
282
|
+
return 2;
|
283
|
+
}
|
209
284
|
|
210
|
-
|
211
|
-
|
285
|
+
const engine = new ESLint(translateOptions(options));
|
286
|
+
let results;
|
212
287
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
288
|
+
if (useStdin) {
|
289
|
+
results = await engine.lintText(text, {
|
290
|
+
filePath: options.stdinFilename,
|
291
|
+
warnIgnored: true
|
292
|
+
});
|
293
|
+
} else {
|
294
|
+
results = await engine.lintFiles(files);
|
295
|
+
}
|
217
296
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
297
|
+
if (options.fix) {
|
298
|
+
debug("Fix mode enabled - applying fixes");
|
299
|
+
await ESLint.outputFixes(results);
|
300
|
+
}
|
222
301
|
|
223
|
-
|
224
|
-
|
302
|
+
if (options.quiet) {
|
303
|
+
debug("Quiet mode enabled - filtering out warnings");
|
304
|
+
results = ESLint.getErrorResults(results);
|
305
|
+
}
|
225
306
|
|
226
|
-
|
227
|
-
|
228
|
-
|
307
|
+
if (await printResults(engine, results, options.format, options.outputFile)) {
|
308
|
+
const { errorCount, warningCount } = countErrors(results);
|
309
|
+
const tooManyWarnings =
|
310
|
+
options.maxWarnings >= 0 && warningCount > options.maxWarnings;
|
229
311
|
|
230
|
-
|
312
|
+
if (!errorCount && tooManyWarnings) {
|
313
|
+
log.error(
|
314
|
+
"ESLint found too many warnings (maximum: %s).",
|
315
|
+
options.maxWarnings
|
316
|
+
);
|
231
317
|
}
|
232
318
|
|
233
|
-
return
|
319
|
+
return (errorCount || tooManyWarnings) ? 1 : 0;
|
234
320
|
}
|
235
321
|
|
236
|
-
return
|
322
|
+
return 2;
|
237
323
|
}
|
238
324
|
};
|
239
325
|
|