eslint 4.16.0 → 4.18.2
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 +46 -0
- package/conf/environments.js +3 -1
- package/conf/eslint-recommended.js +0 -0
- package/lib/linter.js +368 -366
- package/lib/rules/accessor-pairs.js +7 -3
- package/lib/rules/array-bracket-newline.js +11 -5
- package/lib/rules/array-bracket-spacing.js +11 -5
- package/lib/rules/array-callback-return.js +11 -5
- package/lib/rules/array-element-newline.js +8 -3
- package/lib/rules/arrow-body-style.js +16 -8
- package/lib/rules/arrow-parens.js +13 -9
- package/lib/rules/arrow-spacing.js +13 -5
- package/lib/rules/block-scoped-var.js +6 -2
- package/lib/rules/block-spacing.js +13 -6
- package/lib/rules/brace-style.js +16 -14
- package/lib/rules/callback-return.js +6 -2
- package/lib/rules/camelcase.js +6 -2
- package/lib/rules/capitalized-comments.js +11 -8
- package/lib/rules/class-methods-use-this.js +7 -3
- package/lib/rules/comma-dangle.js +7 -4
- package/lib/rules/comma-spacing.js +13 -10
- package/lib/rules/comma-style.js +9 -4
- package/lib/rules/complexity.js +6 -2
- package/lib/rules/computed-property-spacing.js +13 -5
- package/lib/rules/consistent-return.js +12 -7
- package/lib/rules/consistent-this.js +9 -4
- package/lib/rules/constructor-super.js +17 -8
- package/lib/rules/curly.js +59 -80
- package/lib/rules/default-case.js +6 -2
- package/lib/rules/dot-location.js +8 -3
- package/lib/rules/dot-notation.js +10 -5
- package/lib/rules/eol-last.js +7 -3
- package/lib/rules/eqeqeq.js +6 -2
- package/lib/rules/indent.js +0 -1
- package/lib/rules/key-spacing.js +3 -2
- package/lib/rules/keyword-spacing.js +6 -1
- package/lib/rules/max-len.js +2 -1
- package/lib/rules/no-alert.js +19 -18
- package/lib/rules/no-array-constructor.js +6 -2
- package/lib/rules/no-await-in-loop.js +75 -57
- package/lib/rules/no-bitwise.js +6 -2
- package/lib/rules/no-buffer-constructor.js +6 -3
- package/lib/rules/no-caller.js +6 -2
- package/lib/rules/no-case-declarations.js +6 -2
- package/lib/rules/no-catch-shadow.js +6 -2
- package/lib/rules/no-class-assign.js +6 -2
- package/lib/rules/no-compare-neg-zero.js +5 -2
- package/lib/rules/no-cond-assign.js +10 -4
- package/lib/rules/no-confusing-arrow.js +6 -2
- package/lib/rules/no-console.js +6 -2
- package/lib/rules/no-const-assign.js +6 -2
- package/lib/rules/no-constant-condition.js +6 -3
- package/lib/rules/no-continue.js +6 -2
- package/lib/rules/no-control-regex.js +7 -3
- package/lib/rules/no-debugger.js +5 -2
- package/lib/rules/no-delete-var.js +6 -2
- package/lib/rules/no-div-regex.js +6 -2
- package/lib/rules/no-dupe-args.js +6 -2
- package/lib/rules/no-dupe-class-members.js +6 -2
- package/lib/rules/no-dupe-keys.js +6 -2
- package/lib/rules/no-duplicate-case.js +6 -2
- package/lib/rules/no-else-return.js +7 -2
- package/lib/rules/no-empty-character-class.js +6 -2
- package/lib/rules/no-empty-function.js +6 -2
- package/lib/rules/no-empty-pattern.js +7 -3
- package/lib/rules/no-empty.js +7 -3
- package/lib/rules/no-eq-null.js +6 -2
- package/lib/rules/no-eval.js +6 -2
- package/lib/rules/no-ex-assign.js +6 -2
- package/lib/rules/no-extend-native.js +6 -2
- package/lib/rules/no-extra-bind.js +6 -2
- package/lib/rules/no-extra-boolean-cast.js +8 -3
- package/lib/rules/no-extra-label.js +6 -2
- package/lib/rules/no-extra-parens.js +5 -1
- package/lib/rules/no-extra-semi.js +6 -2
- package/lib/rules/no-self-assign.js +3 -1
- package/lib/rules/no-unused-vars.js +1 -1
- package/lib/rules/object-curly-newline.js +67 -19
- package/lib/rules/object-shorthand.js +9 -7
- package/lib/rules/padding-line-between-statements.js +6 -0
- package/lib/rules/require-await.js +5 -0
- package/lib/rules/rest-spread-spacing.js +6 -0
- package/lib/rules/space-unary-ops.js +1 -10
- package/lib/rules/template-tag-spacing.js +0 -0
- package/lib/util/glob-util.js +17 -4
- package/lib/util/interpolate.js +5 -1
- package/lib/util/npm-util.js +1 -1
- package/package.json +2 -2
- package/conf/default-config-options.js +0 -29
package/lib/linter.js
CHANGED
@@ -14,7 +14,6 @@ const eslintScope = require("eslint-scope"),
|
|
14
14
|
levn = require("levn"),
|
15
15
|
lodash = require("lodash"),
|
16
16
|
blankScriptAST = require("../conf/blank-script.json"),
|
17
|
-
defaultConfig = require("../conf/default-config-options.js"),
|
18
17
|
CodePathAnalyzer = require("./code-path-analysis/code-path-analyzer"),
|
19
18
|
ConfigOps = require("./config/config-ops"),
|
20
19
|
validator = require("./config/config-validator"),
|
@@ -33,6 +32,7 @@ const eslintScope = require("eslint-scope"),
|
|
33
32
|
|
34
33
|
const debug = require("debug")("eslint:linter");
|
35
34
|
const MAX_AUTOFIX_PASSES = 10;
|
35
|
+
const DEFAULT_PARSER_NAME = "espree";
|
36
36
|
|
37
37
|
//------------------------------------------------------------------------------
|
38
38
|
// Typedefs
|
@@ -178,32 +178,12 @@ function parseListConfig(string) {
|
|
178
178
|
* and any globals declared by special block comments, are present in the global
|
179
179
|
* scope.
|
180
180
|
* @param {Scope} globalScope The global scope.
|
181
|
-
* @param {Object}
|
182
|
-
* @param {
|
181
|
+
* @param {Object} configGlobals The globals declared in configuration
|
182
|
+
* @param {{exportedVariables: Object, enabledGlobals: Object}} commentDirectives Directives from comment configuration
|
183
183
|
* @returns {void}
|
184
184
|
*/
|
185
|
-
function addDeclaredGlobals(globalScope,
|
186
|
-
|
187
|
-
exportedGlobals = {},
|
188
|
-
explicitGlobals = {},
|
189
|
-
builtin = envContext.get("builtin");
|
190
|
-
|
191
|
-
Object.assign(declaredGlobals, builtin);
|
192
|
-
|
193
|
-
Object.keys(config.env).filter(name => config.env[name]).forEach(name => {
|
194
|
-
const env = envContext.get(name),
|
195
|
-
environmentGlobals = env && env.globals;
|
196
|
-
|
197
|
-
if (environmentGlobals) {
|
198
|
-
Object.assign(declaredGlobals, environmentGlobals);
|
199
|
-
}
|
200
|
-
});
|
201
|
-
|
202
|
-
Object.assign(exportedGlobals, config.exported);
|
203
|
-
Object.assign(declaredGlobals, config.globals);
|
204
|
-
Object.assign(explicitGlobals, config.astGlobals);
|
205
|
-
|
206
|
-
Object.keys(declaredGlobals).forEach(name => {
|
185
|
+
function addDeclaredGlobals(globalScope, configGlobals, commentDirectives) {
|
186
|
+
Object.keys(configGlobals).forEach(name => {
|
207
187
|
let variable = globalScope.set.get(name);
|
208
188
|
|
209
189
|
if (!variable) {
|
@@ -212,24 +192,24 @@ function addDeclaredGlobals(globalScope, config, envContext) {
|
|
212
192
|
globalScope.variables.push(variable);
|
213
193
|
globalScope.set.set(name, variable);
|
214
194
|
}
|
215
|
-
variable.writeable =
|
195
|
+
variable.writeable = configGlobals[name];
|
216
196
|
});
|
217
197
|
|
218
|
-
Object.keys(
|
198
|
+
Object.keys(commentDirectives.enabledGlobals).forEach(name => {
|
219
199
|
let variable = globalScope.set.get(name);
|
220
200
|
|
221
201
|
if (!variable) {
|
222
202
|
variable = new eslintScope.Variable(name, globalScope);
|
223
203
|
variable.eslintExplicitGlobal = true;
|
224
|
-
variable.eslintExplicitGlobalComment =
|
204
|
+
variable.eslintExplicitGlobalComment = commentDirectives.enabledGlobals[name].comment;
|
225
205
|
globalScope.variables.push(variable);
|
226
206
|
globalScope.set.set(name, variable);
|
227
207
|
}
|
228
|
-
variable.writeable =
|
208
|
+
variable.writeable = commentDirectives.enabledGlobals[name].value;
|
229
209
|
});
|
230
210
|
|
231
211
|
// mark all exported variables as such
|
232
|
-
Object.keys(
|
212
|
+
Object.keys(commentDirectives.exportedVariables).forEach(name => {
|
233
213
|
const variable = globalScope.set.get(name);
|
234
214
|
|
235
215
|
if (variable) {
|
@@ -283,97 +263,90 @@ function createDisableDirectives(type, loc, value) {
|
|
283
263
|
* where reporting is disabled or enabled and merges them with reporting config.
|
284
264
|
* @param {string} filename The file being checked.
|
285
265
|
* @param {ASTNode} ast The top node of the AST.
|
286
|
-
* @param {Object} config The existing configuration data.
|
287
266
|
* @param {function(string): {create: Function}} ruleMapper A map from rule IDs to defined rules
|
288
|
-
* @returns {{
|
289
|
-
*
|
267
|
+
* @returns {{configuredRules: Object, enabledGlobals: Object, exportedVariables: Object, problems: Problem[], disableDirectives: DisableDirective[]}}
|
268
|
+
* A collection of the directive comments that were found, along with any problems that occurred when parsing
|
290
269
|
*/
|
291
|
-
function
|
292
|
-
|
293
|
-
const
|
294
|
-
|
295
|
-
astGlobals: {},
|
296
|
-
rules: {},
|
297
|
-
env: {}
|
298
|
-
};
|
299
|
-
const commentRules = {};
|
270
|
+
function getDirectiveComments(filename, ast, ruleMapper) {
|
271
|
+
const configuredRules = {};
|
272
|
+
const enabledGlobals = {};
|
273
|
+
const exportedVariables = {};
|
300
274
|
const problems = [];
|
301
275
|
const disableDirectives = [];
|
302
276
|
|
303
277
|
ast.comments.filter(token => token.type !== "Shebang").forEach(comment => {
|
278
|
+
const trimmedCommentText = comment.value.trim();
|
279
|
+
const match = /^(eslint(-\w+){0,3}|exported|globals?)(\s|$)/.exec(trimmedCommentText);
|
304
280
|
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
if (match) {
|
309
|
-
value = value.slice(match.index + match[1].length);
|
310
|
-
|
311
|
-
if (comment.type === "Block") {
|
312
|
-
switch (match[1]) {
|
313
|
-
case "exported":
|
314
|
-
Object.assign(commentConfig.exported, parseBooleanConfig(value, comment));
|
315
|
-
break;
|
316
|
-
|
317
|
-
case "globals":
|
318
|
-
case "global":
|
319
|
-
Object.assign(commentConfig.astGlobals, parseBooleanConfig(value, comment));
|
320
|
-
break;
|
321
|
-
|
322
|
-
case "eslint-disable":
|
323
|
-
[].push.apply(disableDirectives, createDisableDirectives("disable", comment.loc.start, value));
|
324
|
-
break;
|
325
|
-
|
326
|
-
case "eslint-enable":
|
327
|
-
[].push.apply(disableDirectives, createDisableDirectives("enable", comment.loc.start, value));
|
328
|
-
break;
|
329
|
-
|
330
|
-
case "eslint": {
|
331
|
-
const parseResult = parseJsonConfig(value, comment.loc);
|
332
|
-
|
333
|
-
if (parseResult.success) {
|
334
|
-
Object.keys(parseResult.config).forEach(name => {
|
335
|
-
const ruleValue = parseResult.config[name];
|
336
|
-
|
337
|
-
try {
|
338
|
-
validator.validateRuleOptions(ruleMapper(name), name, ruleValue);
|
339
|
-
} catch (err) {
|
340
|
-
problems.push({
|
341
|
-
ruleId: name,
|
342
|
-
severity: 2,
|
343
|
-
source: null,
|
344
|
-
message: err.message,
|
345
|
-
line: comment.loc.start.line,
|
346
|
-
column: comment.loc.start.column + 1,
|
347
|
-
endLine: comment.loc.end.line,
|
348
|
-
endColumn: comment.loc.end.column + 1,
|
349
|
-
nodeType: null
|
350
|
-
});
|
351
|
-
}
|
352
|
-
commentRules[name] = ruleValue;
|
353
|
-
});
|
354
|
-
} else {
|
355
|
-
problems.push(parseResult.error);
|
356
|
-
}
|
281
|
+
if (!match) {
|
282
|
+
return;
|
283
|
+
}
|
357
284
|
|
358
|
-
|
285
|
+
const directiveValue = trimmedCommentText.slice(match.index + match[1].length);
|
286
|
+
|
287
|
+
if (/^eslint-disable-(next-)?line$/.test(match[1]) && comment.loc.start.line === comment.loc.end.line) {
|
288
|
+
const directiveType = match[1].slice("eslint-".length);
|
289
|
+
|
290
|
+
[].push.apply(disableDirectives, createDisableDirectives(directiveType, comment.loc.start, directiveValue));
|
291
|
+
} else if (comment.type === "Block") {
|
292
|
+
switch (match[1]) {
|
293
|
+
case "exported":
|
294
|
+
Object.assign(exportedVariables, parseBooleanConfig(directiveValue, comment));
|
295
|
+
break;
|
296
|
+
|
297
|
+
case "globals":
|
298
|
+
case "global":
|
299
|
+
Object.assign(enabledGlobals, parseBooleanConfig(directiveValue, comment));
|
300
|
+
break;
|
301
|
+
|
302
|
+
case "eslint-disable":
|
303
|
+
[].push.apply(disableDirectives, createDisableDirectives("disable", comment.loc.start, directiveValue));
|
304
|
+
break;
|
305
|
+
|
306
|
+
case "eslint-enable":
|
307
|
+
[].push.apply(disableDirectives, createDisableDirectives("enable", comment.loc.start, directiveValue));
|
308
|
+
break;
|
309
|
+
|
310
|
+
case "eslint": {
|
311
|
+
const parseResult = parseJsonConfig(directiveValue, comment.loc);
|
312
|
+
|
313
|
+
if (parseResult.success) {
|
314
|
+
Object.keys(parseResult.config).forEach(name => {
|
315
|
+
const ruleValue = parseResult.config[name];
|
316
|
+
|
317
|
+
try {
|
318
|
+
validator.validateRuleOptions(ruleMapper(name), name, ruleValue);
|
319
|
+
} catch (err) {
|
320
|
+
problems.push({
|
321
|
+
ruleId: name,
|
322
|
+
severity: 2,
|
323
|
+
source: null,
|
324
|
+
message: err.message,
|
325
|
+
line: comment.loc.start.line,
|
326
|
+
column: comment.loc.start.column + 1,
|
327
|
+
endLine: comment.loc.end.line,
|
328
|
+
endColumn: comment.loc.end.column + 1,
|
329
|
+
nodeType: null
|
330
|
+
});
|
331
|
+
}
|
332
|
+
configuredRules[name] = ruleValue;
|
333
|
+
});
|
334
|
+
} else {
|
335
|
+
problems.push(parseResult.error);
|
359
336
|
}
|
360
337
|
|
361
|
-
|
362
|
-
}
|
363
|
-
} else { // comment.type === "Line"
|
364
|
-
if (match[1] === "eslint-disable-line") {
|
365
|
-
[].push.apply(disableDirectives, createDisableDirectives("disable-line", comment.loc.start, value));
|
366
|
-
} else if (match[1] === "eslint-disable-next-line") {
|
367
|
-
[].push.apply(disableDirectives, createDisableDirectives("disable-next-line", comment.loc.start, value));
|
338
|
+
break;
|
368
339
|
}
|
340
|
+
|
341
|
+
// no default
|
369
342
|
}
|
370
343
|
}
|
371
344
|
});
|
372
345
|
|
373
|
-
Object.assign(commentConfig.rules, commentRules);
|
374
|
-
|
375
346
|
return {
|
376
|
-
|
347
|
+
configuredRules,
|
348
|
+
enabledGlobals,
|
349
|
+
exportedVariables,
|
377
350
|
problems,
|
378
351
|
disableDirectives
|
379
352
|
};
|
@@ -403,81 +376,81 @@ function normalizeEcmaVersion(ecmaVersion, isModule) {
|
|
403
376
|
return ecmaVersion;
|
404
377
|
}
|
405
378
|
|
379
|
+
const eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)\*\//g;
|
380
|
+
|
406
381
|
/**
|
407
|
-
*
|
408
|
-
* @param
|
409
|
-
* @
|
410
|
-
* @returns {Object} Processed config
|
382
|
+
* Checks whether or not there is a comment which has "eslint-env *" in a given text.
|
383
|
+
* @param {string} text - A source code text to check.
|
384
|
+
* @returns {Object|null} A result of parseListConfig() with "eslint-env *" comment.
|
411
385
|
*/
|
412
|
-
function
|
413
|
-
|
414
|
-
const copiedRules = {};
|
415
|
-
let parserOptions = {};
|
386
|
+
function findEslintEnv(text) {
|
387
|
+
let match, retv;
|
416
388
|
|
417
|
-
|
418
|
-
Object.keys(config.rules).forEach(k => {
|
419
|
-
const rule = config.rules[k];
|
389
|
+
eslintEnvPattern.lastIndex = 0;
|
420
390
|
|
421
|
-
|
422
|
-
|
423
|
-
}
|
424
|
-
if (Array.isArray(rule)) {
|
425
|
-
copiedRules[k] = rule.slice();
|
426
|
-
} else {
|
427
|
-
copiedRules[k] = rule;
|
428
|
-
}
|
429
|
-
});
|
391
|
+
while ((match = eslintEnvPattern.exec(text))) {
|
392
|
+
retv = Object.assign(retv || {}, parseListConfig(match[1]));
|
430
393
|
}
|
431
394
|
|
432
|
-
|
433
|
-
|
434
|
-
Object.keys(config.env).forEach(envName => {
|
435
|
-
const env = envContext.get(envName);
|
395
|
+
return retv;
|
396
|
+
}
|
436
397
|
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
398
|
+
/**
|
399
|
+
* Normalizes the possible options for `linter.verify` and `linter.verifyAndFix` to a
|
400
|
+
* consistent shape.
|
401
|
+
* @param {(string|{reportUnusedDisableDirectives: boolean, filename: string, allowInlineConfig: boolean})} providedOptions Options
|
402
|
+
* @returns {{reportUnusedDisableDirectives: boolean, filename: string, allowInlineConfig: boolean}} Normalized options
|
403
|
+
*/
|
404
|
+
function normalizeVerifyOptions(providedOptions) {
|
405
|
+
const isObjectOptions = typeof providedOptions === "object";
|
406
|
+
const providedFilename = isObjectOptions ? providedOptions.filename : providedOptions;
|
442
407
|
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
env: ConfigOps.merge(defaultConfig.env, config.env || {}),
|
448
|
-
settings: ConfigOps.merge(defaultConfig.settings, config.settings || {}),
|
449
|
-
parserOptions: ConfigOps.merge(parserOptions, config.parserOptions || {})
|
408
|
+
return {
|
409
|
+
filename: typeof providedFilename === "string" ? providedFilename : "<input>",
|
410
|
+
allowInlineConfig: !isObjectOptions || providedOptions.allowInlineConfig !== false,
|
411
|
+
reportUnusedDisableDirectives: isObjectOptions && !!providedOptions.reportUnusedDisableDirectives
|
450
412
|
};
|
451
|
-
|
413
|
+
}
|
414
|
+
|
415
|
+
/**
|
416
|
+
* Combines the provided parserOptions with the options from environments
|
417
|
+
* @param {Object} providedOptions The provided 'parserOptions' key in a config
|
418
|
+
* @param {Environment[]} enabledEnvironments The environments enabled in configuration and with inline comments
|
419
|
+
* @returns {Object} Resulting parser options after merge
|
420
|
+
*/
|
421
|
+
function resolveParserOptions(providedOptions, enabledEnvironments) {
|
422
|
+
const parserOptionsFromEnv = enabledEnvironments
|
423
|
+
.filter(env => env.parserOptions)
|
424
|
+
.reduce((parserOptions, env) => ConfigOps.merge(parserOptions, env.parserOptions), {});
|
425
|
+
|
426
|
+
const mergedParserOptions = ConfigOps.merge(parserOptionsFromEnv, providedOptions || {});
|
427
|
+
|
428
|
+
const isModule = mergedParserOptions.sourceType === "module";
|
452
429
|
|
453
430
|
if (isModule) {
|
454
431
|
|
455
432
|
// can't have global return inside of modules
|
456
|
-
|
433
|
+
mergedParserOptions.ecmaFeatures = Object.assign({}, mergedParserOptions.ecmaFeatures, { globalReturn: false });
|
457
434
|
}
|
458
435
|
|
459
|
-
|
436
|
+
mergedParserOptions.ecmaVersion = normalizeEcmaVersion(mergedParserOptions.ecmaVersion, isModule);
|
460
437
|
|
461
|
-
return
|
438
|
+
return mergedParserOptions;
|
462
439
|
}
|
463
440
|
|
464
|
-
const eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)\*\//g;
|
465
|
-
|
466
441
|
/**
|
467
|
-
*
|
468
|
-
* @param {
|
469
|
-
* @
|
442
|
+
* Combines the provided globals object with the globals from environments
|
443
|
+
* @param {Object} providedGlobals The 'globals' key in a config
|
444
|
+
* @param {Environments[]} enabledEnvironments The environments enabled in configuration and with inline comments
|
445
|
+
* @returns {Object} The resolved globals object
|
470
446
|
*/
|
471
|
-
function
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
}
|
479
|
-
|
480
|
-
return retv;
|
447
|
+
function resolveGlobals(providedGlobals, enabledEnvironments) {
|
448
|
+
return Object.assign.apply(
|
449
|
+
null,
|
450
|
+
[{}]
|
451
|
+
.concat(enabledEnvironments.filter(env => env.globals).map(env => env.globals))
|
452
|
+
.concat(providedGlobals)
|
453
|
+
);
|
481
454
|
}
|
482
455
|
|
483
456
|
/**
|
@@ -540,13 +513,16 @@ function analyzeScope(ast, parserOptions, visitorKeys) {
|
|
540
513
|
* as possible
|
541
514
|
* @param {string} text The text to parse.
|
542
515
|
* @param {Object} providedParserOptions Options to pass to the parser
|
543
|
-
* @param {
|
516
|
+
* @param {string} parserName The name of the parser
|
517
|
+
* @param {Map<string, Object>} parserMap A map from names to loaded parsers
|
544
518
|
* @param {string} filePath The path to the file being parsed.
|
545
519
|
* @returns {{success: false, error: Problem}|{success: true, sourceCode: SourceCode}}
|
546
520
|
* An object containing the AST and parser services if parsing was successful, or the error if parsing failed
|
547
521
|
* @private
|
548
522
|
*/
|
549
|
-
function parse(text, providedParserOptions,
|
523
|
+
function parse(text, providedParserOptions, parserName, parserMap, filePath) {
|
524
|
+
|
525
|
+
|
550
526
|
const textToParse = stripUnicodeBOM(text).replace(astUtils.SHEBANG_MATCHER, (match, captured) => `//${captured}`);
|
551
527
|
const parserOptions = Object.assign({}, providedParserOptions, {
|
552
528
|
loc: true,
|
@@ -559,6 +535,25 @@ function parse(text, providedParserOptions, parser, filePath) {
|
|
559
535
|
filePath
|
560
536
|
});
|
561
537
|
|
538
|
+
let parser;
|
539
|
+
|
540
|
+
try {
|
541
|
+
parser = parserMap.get(parserName) || require(parserName);
|
542
|
+
} catch (ex) {
|
543
|
+
return {
|
544
|
+
success: false,
|
545
|
+
error: {
|
546
|
+
ruleId: null,
|
547
|
+
fatal: true,
|
548
|
+
severity: 2,
|
549
|
+
source: null,
|
550
|
+
message: ex.message,
|
551
|
+
line: 0,
|
552
|
+
column: 0
|
553
|
+
}
|
554
|
+
};
|
555
|
+
}
|
556
|
+
|
562
557
|
/*
|
563
558
|
* Check for parsing errors first. If there's a parsing error, nothing
|
564
559
|
* else can happen. However, a parsing error does not throw an error
|
@@ -677,6 +672,21 @@ function markVariableAsUsed(scopeManager, currentNode, parserOptions, name) {
|
|
677
672
|
return false;
|
678
673
|
}
|
679
674
|
|
675
|
+
/**
|
676
|
+
* Runs a rule, and gets its listeners
|
677
|
+
* @param {Rule} rule A normalized rule with a `create` method
|
678
|
+
* @param {Context} ruleContext The context that should be passed to the rule
|
679
|
+
* @returns {Object} A map of selector listeners provided by the rule
|
680
|
+
*/
|
681
|
+
function createRuleListeners(rule, ruleContext) {
|
682
|
+
try {
|
683
|
+
return rule.create(ruleContext);
|
684
|
+
} catch (ex) {
|
685
|
+
ex.message = `Error while loading rule '${ruleContext.id}': ${ex.message}`;
|
686
|
+
throw ex;
|
687
|
+
}
|
688
|
+
}
|
689
|
+
|
680
690
|
// methods that exist on SourceCode object
|
681
691
|
const DEPRECATED_SOURCECODE_PASSTHROUGHS = {
|
682
692
|
getSource: "getText",
|
@@ -715,7 +725,157 @@ const BASE_TRAVERSAL_CONTEXT = Object.freeze(
|
|
715
725
|
)
|
716
726
|
);
|
717
727
|
|
728
|
+
/**
|
729
|
+
* Runs the given rules on the given SourceCode object
|
730
|
+
* @param {SourceCode} sourceCode A SourceCode object for the given text
|
731
|
+
* @param {Object} configuredRules The rules configuration
|
732
|
+
* @param {function(string): Rule} ruleMapper A mapper function from rule names to rules
|
733
|
+
* @param {Object} parserOptions The options that were passed to the parser
|
734
|
+
* @param {string} parserName The name of the parser in the config
|
735
|
+
* @param {Object} settings The settings that were enabled in the config
|
736
|
+
* @param {string} filename The reported filename of the code
|
737
|
+
* @returns {Problem[]} An array of reported problems
|
738
|
+
*/
|
739
|
+
function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parserName, settings, filename) {
|
740
|
+
const emitter = createEmitter();
|
741
|
+
const traverser = new Traverser();
|
742
|
+
|
743
|
+
/*
|
744
|
+
* Create a frozen object with the ruleContext properties and methods that are shared by all rules.
|
745
|
+
* All rule contexts will inherit from this object. This avoids the performance penalty of copying all the
|
746
|
+
* properties once for each rule.
|
747
|
+
*/
|
748
|
+
const sharedTraversalContext = Object.freeze(
|
749
|
+
Object.assign(
|
750
|
+
Object.create(BASE_TRAVERSAL_CONTEXT),
|
751
|
+
{
|
752
|
+
getAncestors: () => traverser.parents(),
|
753
|
+
getDeclaredVariables: sourceCode.scopeManager.getDeclaredVariables.bind(sourceCode.scopeManager),
|
754
|
+
getFilename: () => filename,
|
755
|
+
getScope: () => getScope(sourceCode.scopeManager, traverser.current(), parserOptions.ecmaVersion),
|
756
|
+
getSourceCode: () => sourceCode,
|
757
|
+
markVariableAsUsed: name => markVariableAsUsed(sourceCode.scopeManager, traverser.current(), parserOptions, name),
|
758
|
+
parserOptions,
|
759
|
+
parserPath: parserName,
|
760
|
+
parserServices: sourceCode.parserServices,
|
761
|
+
settings,
|
762
|
+
|
763
|
+
/**
|
764
|
+
* This is used to avoid breaking rules that used to monkeypatch the `Linter#report` method
|
765
|
+
* by using the `_linter` property on rule contexts.
|
766
|
+
*
|
767
|
+
* This should be removed in a major release after we create a better way to
|
768
|
+
* lint for unused disable comments.
|
769
|
+
* https://github.com/eslint/eslint/issues/9193
|
770
|
+
*/
|
771
|
+
_linter: {
|
772
|
+
report() {},
|
773
|
+
on: emitter.on
|
774
|
+
}
|
775
|
+
}
|
776
|
+
)
|
777
|
+
);
|
778
|
+
|
779
|
+
|
780
|
+
const lintingProblems = [];
|
781
|
+
|
782
|
+
Object.keys(configuredRules).forEach(ruleId => {
|
783
|
+
const severity = ConfigOps.getRuleSeverity(configuredRules[ruleId]);
|
784
|
+
|
785
|
+
if (severity === 0) {
|
786
|
+
return;
|
787
|
+
}
|
788
|
+
|
789
|
+
const rule = ruleMapper(ruleId);
|
790
|
+
const messageIds = rule.meta && rule.meta.messages;
|
791
|
+
let reportTranslator = null;
|
792
|
+
const ruleContext = Object.freeze(
|
793
|
+
Object.assign(
|
794
|
+
Object.create(sharedTraversalContext),
|
795
|
+
{
|
796
|
+
id: ruleId,
|
797
|
+
options: getRuleOptions(configuredRules[ruleId]),
|
798
|
+
report() {
|
799
|
+
|
800
|
+
/*
|
801
|
+
* Create a report translator lazily.
|
802
|
+
* In a vast majority of cases, any given rule reports zero errors on a given
|
803
|
+
* piece of code. Creating a translator lazily avoids the performance cost of
|
804
|
+
* creating a new translator function for each rule that usually doesn't get
|
805
|
+
* called.
|
806
|
+
*
|
807
|
+
* Using lazy report translators improves end-to-end performance by about 3%
|
808
|
+
* with Node 8.4.0.
|
809
|
+
*/
|
810
|
+
if (reportTranslator === null) {
|
811
|
+
reportTranslator = createReportTranslator({ ruleId, severity, sourceCode, messageIds });
|
812
|
+
}
|
813
|
+
const problem = reportTranslator.apply(null, arguments);
|
814
|
+
|
815
|
+
if (problem.fix && rule.meta && !rule.meta.fixable) {
|
816
|
+
throw new Error("Fixable rules should export a `meta.fixable` property.");
|
817
|
+
}
|
818
|
+
lintingProblems.push(problem);
|
819
|
+
|
820
|
+
/*
|
821
|
+
* This is used to avoid breaking rules that used monkeypatch Linter, and relied on
|
822
|
+
* `linter.report` getting called with report info every time a rule reports a problem.
|
823
|
+
* To continue to support this, make sure that `context._linter.report` is called every
|
824
|
+
* time a problem is reported by a rule, even though `context._linter` is no longer a
|
825
|
+
* `Linter` instance.
|
826
|
+
*
|
827
|
+
* This should be removed in a major release after we create a better way to
|
828
|
+
* lint for unused disable comments.
|
829
|
+
* https://github.com/eslint/eslint/issues/9193
|
830
|
+
*/
|
831
|
+
sharedTraversalContext._linter.report( // eslint-disable-line no-underscore-dangle
|
832
|
+
problem.ruleId,
|
833
|
+
problem.severity,
|
834
|
+
{ loc: { start: { line: problem.line, column: problem.column - 1 } } },
|
835
|
+
problem.message
|
836
|
+
);
|
837
|
+
}
|
838
|
+
}
|
839
|
+
)
|
840
|
+
);
|
841
|
+
|
842
|
+
const ruleListeners = createRuleListeners(rule, ruleContext);
|
843
|
+
|
844
|
+
// add all the selectors from the rule as listeners
|
845
|
+
Object.keys(ruleListeners).forEach(selector => {
|
846
|
+
emitter.on(
|
847
|
+
selector,
|
848
|
+
timing.enabled
|
849
|
+
? timing.time(ruleId, ruleListeners[selector])
|
850
|
+
: ruleListeners[selector]
|
851
|
+
);
|
852
|
+
});
|
853
|
+
});
|
854
|
+
|
855
|
+
const eventGenerator = new CodePathAnalyzer(new NodeEventGenerator(emitter));
|
856
|
+
|
857
|
+
/*
|
858
|
+
* Each node has a type property. Whenever a particular type of
|
859
|
+
* node is found, an event is fired. This allows any listeners to
|
860
|
+
* automatically be informed that this type of node has been found
|
861
|
+
* and react accordingly.
|
862
|
+
*/
|
863
|
+
traverser.traverse(sourceCode.ast, {
|
864
|
+
enter(node, parent) {
|
865
|
+
node.parent = parent;
|
866
|
+
eventGenerator.enterNode(node);
|
867
|
+
},
|
868
|
+
leave(node) {
|
869
|
+
eventGenerator.leaveNode(node);
|
870
|
+
},
|
871
|
+
visitorKeys: sourceCode.visitorKeys
|
872
|
+
});
|
873
|
+
|
874
|
+
return lintingProblems;
|
875
|
+
}
|
876
|
+
|
718
877
|
const lastSourceCodes = new WeakMap();
|
878
|
+
const loadedParserMaps = new WeakMap();
|
719
879
|
|
720
880
|
//------------------------------------------------------------------------------
|
721
881
|
// Public Interface
|
@@ -729,10 +889,10 @@ module.exports = class Linter {
|
|
729
889
|
|
730
890
|
constructor() {
|
731
891
|
lastSourceCodes.set(this, null);
|
892
|
+
loadedParserMaps.set(this, new Map());
|
732
893
|
this.version = pkg.version;
|
733
894
|
|
734
895
|
this.rules = new Rules();
|
735
|
-
this._parsers = new Map();
|
736
896
|
this.environments = new Environments();
|
737
897
|
}
|
738
898
|
|
@@ -750,7 +910,7 @@ module.exports = class Linter {
|
|
750
910
|
/**
|
751
911
|
* Same as linter.verify, except without support for processors.
|
752
912
|
* @param {string|SourceCode} textOrSourceCode The text to parse or a SourceCode object.
|
753
|
-
* @param {ESLintConfig}
|
913
|
+
* @param {ESLintConfig} providedConfig An ESLintConfig instance to configure everything.
|
754
914
|
* @param {(string|Object)} [filenameOrOptions] The optional filename of the file being checked.
|
755
915
|
* If this is not set, the filename will default to '<input>' in the rule context. If
|
756
916
|
* an object, then it has "filename", "saveState", and "allowInlineConfig" properties.
|
@@ -758,23 +918,14 @@ module.exports = class Linter {
|
|
758
918
|
* Useful if you want to validate JS without comments overriding rules.
|
759
919
|
* @param {boolean} [filenameOrOptions.reportUnusedDisableDirectives=false] Adds reported errors for unused
|
760
920
|
* eslint-disable directives
|
761
|
-
* @returns {Object[]} The results as an array of messages or
|
921
|
+
* @returns {Object[]} The results as an array of messages or an empty array if no messages.
|
762
922
|
*/
|
763
|
-
_verifyWithoutProcessors(textOrSourceCode,
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
reportUnusedDisableDirectives;
|
923
|
+
_verifyWithoutProcessors(textOrSourceCode, providedConfig, filenameOrOptions) {
|
924
|
+
const config = providedConfig || {};
|
925
|
+
const options = normalizeVerifyOptions(filenameOrOptions);
|
926
|
+
let text;
|
768
927
|
|
769
928
|
// evaluate arguments
|
770
|
-
if (typeof filenameOrOptions === "object") {
|
771
|
-
providedFilename = filenameOrOptions.filename;
|
772
|
-
allowInlineConfig = filenameOrOptions.allowInlineConfig;
|
773
|
-
reportUnusedDisableDirectives = filenameOrOptions.reportUnusedDisableDirectives;
|
774
|
-
} else {
|
775
|
-
providedFilename = filenameOrOptions;
|
776
|
-
}
|
777
|
-
|
778
929
|
if (typeof textOrSourceCode === "string") {
|
779
930
|
lastSourceCodes.set(this, null);
|
780
931
|
text = textOrSourceCode;
|
@@ -783,23 +934,18 @@ module.exports = class Linter {
|
|
783
934
|
text = textOrSourceCode.text;
|
784
935
|
}
|
785
936
|
|
786
|
-
const filename = typeof providedFilename === "string" ? providedFilename : "<input>";
|
787
|
-
|
788
937
|
// search and apply "eslint-env *".
|
789
938
|
const envInFile = findEslintEnv(text);
|
939
|
+
const resolvedEnvConfig = Object.assign({ builtin: true }, config.env, envInFile);
|
940
|
+
const enabledEnvs = Object.keys(resolvedEnvConfig)
|
941
|
+
.filter(envName => resolvedEnvConfig[envName])
|
942
|
+
.map(envName => this.environments.get(envName))
|
943
|
+
.filter(env => env);
|
790
944
|
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
config.env = Object.assign({}, config.env, envInFile);
|
796
|
-
} else {
|
797
|
-
config.env = envInFile;
|
798
|
-
}
|
799
|
-
}
|
800
|
-
|
801
|
-
// process initial config to make it safe to extend
|
802
|
-
config = prepareConfig(config, this.environments);
|
945
|
+
const parserOptions = resolveParserOptions(config.parserOptions || {}, enabledEnvs);
|
946
|
+
const configuredGlobals = resolveGlobals(config.globals || {}, enabledEnvs);
|
947
|
+
const parserName = config.parser || DEFAULT_PARSER_NAME;
|
948
|
+
const settings = config.settings || {};
|
803
949
|
|
804
950
|
if (!lastSourceCodes.get(this)) {
|
805
951
|
|
@@ -809,26 +955,12 @@ module.exports = class Linter {
|
|
809
955
|
return [];
|
810
956
|
}
|
811
957
|
|
812
|
-
let parser;
|
813
|
-
|
814
|
-
try {
|
815
|
-
parser = this._parsers.get(config.parser) || require(config.parser);
|
816
|
-
} catch (ex) {
|
817
|
-
return [{
|
818
|
-
ruleId: null,
|
819
|
-
fatal: true,
|
820
|
-
severity: 2,
|
821
|
-
source: null,
|
822
|
-
message: ex.message,
|
823
|
-
line: 0,
|
824
|
-
column: 0
|
825
|
-
}];
|
826
|
-
}
|
827
958
|
const parseResult = parse(
|
828
959
|
text,
|
829
|
-
|
830
|
-
|
831
|
-
|
960
|
+
parserOptions,
|
961
|
+
parserName,
|
962
|
+
loadedParserMaps.get(this),
|
963
|
+
options.filename
|
832
964
|
);
|
833
965
|
|
834
966
|
if (!parseResult.success) {
|
@@ -850,171 +982,41 @@ module.exports = class Linter {
|
|
850
982
|
ast: lastSourceCode.ast,
|
851
983
|
parserServices: lastSourceCode.parserServices,
|
852
984
|
visitorKeys: lastSourceCode.visitorKeys,
|
853
|
-
scopeManager: analyzeScope(lastSourceCode.ast,
|
985
|
+
scopeManager: analyzeScope(lastSourceCode.ast, parserOptions)
|
854
986
|
}));
|
855
987
|
}
|
856
988
|
}
|
857
989
|
|
858
|
-
const problems = [];
|
859
990
|
const sourceCode = lastSourceCodes.get(this);
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
if (allowInlineConfig !== false) {
|
864
|
-
const modifyConfigResult = modifyConfigsFromComments(filename, sourceCode.ast, config, ruleId => this.rules.get(ruleId));
|
865
|
-
|
866
|
-
config = modifyConfigResult.config;
|
867
|
-
modifyConfigResult.problems.forEach(problem => problems.push(problem));
|
868
|
-
disableDirectives = modifyConfigResult.disableDirectives;
|
869
|
-
} else {
|
870
|
-
disableDirectives = [];
|
871
|
-
}
|
872
|
-
|
873
|
-
const emitter = createEmitter();
|
874
|
-
const traverser = new Traverser();
|
875
|
-
const scopeManager = sourceCode.scopeManager;
|
876
|
-
|
877
|
-
/*
|
878
|
-
* Create a frozen object with the ruleContext properties and methods that are shared by all rules.
|
879
|
-
* All rule contexts will inherit from this object. This avoids the performance penalty of copying all the
|
880
|
-
* properties once for each rule.
|
881
|
-
*/
|
882
|
-
const sharedTraversalContext = Object.freeze(
|
883
|
-
Object.assign(
|
884
|
-
Object.create(BASE_TRAVERSAL_CONTEXT),
|
885
|
-
{
|
886
|
-
getAncestors: () => traverser.parents(),
|
887
|
-
getDeclaredVariables: scopeManager.getDeclaredVariables.bind(scopeManager),
|
888
|
-
getFilename: () => filename,
|
889
|
-
getScope: () => getScope(scopeManager, traverser.current(), config.parserOptions.ecmaVersion),
|
890
|
-
getSourceCode: () => sourceCode,
|
891
|
-
markVariableAsUsed: name => markVariableAsUsed(scopeManager, traverser.current(), config.parserOptions, name),
|
892
|
-
parserOptions: config.parserOptions,
|
893
|
-
parserPath: config.parser,
|
894
|
-
parserServices: sourceCode.parserServices,
|
895
|
-
settings: config.settings,
|
896
|
-
|
897
|
-
/**
|
898
|
-
* This is used to avoid breaking rules that used to monkeypatch the `Linter#report` method
|
899
|
-
* by using the `_linter` property on rule contexts.
|
900
|
-
*
|
901
|
-
* This should be removed in a major release after we create a better way to
|
902
|
-
* lint for unused disable comments.
|
903
|
-
* https://github.com/eslint/eslint/issues/9193
|
904
|
-
*/
|
905
|
-
_linter: {
|
906
|
-
report() {},
|
907
|
-
on: emitter.on
|
908
|
-
}
|
909
|
-
}
|
910
|
-
)
|
911
|
-
);
|
912
|
-
|
913
|
-
// enable appropriate rules
|
914
|
-
Object.keys(config.rules).forEach(ruleId => {
|
915
|
-
const severity = ConfigOps.getRuleSeverity(config.rules[ruleId]);
|
916
|
-
|
917
|
-
if (severity === 0) {
|
918
|
-
return;
|
919
|
-
}
|
920
|
-
|
921
|
-
const rule = this.rules.get(ruleId);
|
922
|
-
const messageIds = rule && rule.meta && rule.meta.messages;
|
923
|
-
let reportTranslator = null;
|
924
|
-
const ruleContext = Object.freeze(
|
925
|
-
Object.assign(
|
926
|
-
Object.create(sharedTraversalContext),
|
927
|
-
{
|
928
|
-
id: ruleId,
|
929
|
-
options: getRuleOptions(config.rules[ruleId]),
|
930
|
-
report() {
|
931
|
-
|
932
|
-
/*
|
933
|
-
* Create a report translator lazily.
|
934
|
-
* In a vast majority of cases, any given rule reports zero errors on a given
|
935
|
-
* piece of code. Creating a translator lazily avoids the performance cost of
|
936
|
-
* creating a new translator function for each rule that usually doesn't get
|
937
|
-
* called.
|
938
|
-
*
|
939
|
-
* Using lazy report translators improves end-to-end performance by about 3%
|
940
|
-
* with Node 8.4.0.
|
941
|
-
*/
|
942
|
-
if (reportTranslator === null) {
|
943
|
-
reportTranslator = createReportTranslator({ ruleId, severity, sourceCode, messageIds });
|
944
|
-
}
|
945
|
-
const problem = reportTranslator.apply(null, arguments);
|
946
|
-
|
947
|
-
if (problem.fix && rule.meta && !rule.meta.fixable) {
|
948
|
-
throw new Error("Fixable rules should export a `meta.fixable` property.");
|
949
|
-
}
|
950
|
-
problems.push(problem);
|
951
|
-
|
952
|
-
/*
|
953
|
-
* This is used to avoid breaking rules that used monkeypatch Linter, and relied on
|
954
|
-
* `linter.report` getting called with report info every time a rule reports a problem.
|
955
|
-
* To continue to support this, make sure that `context._linter.report` is called every
|
956
|
-
* time a problem is reported by a rule, even though `context._linter` is no longer a
|
957
|
-
* `Linter` instance.
|
958
|
-
*
|
959
|
-
* This should be removed in a major release after we create a better way to
|
960
|
-
* lint for unused disable comments.
|
961
|
-
* https://github.com/eslint/eslint/issues/9193
|
962
|
-
*/
|
963
|
-
sharedTraversalContext._linter.report( // eslint-disable-line no-underscore-dangle
|
964
|
-
problem.ruleId,
|
965
|
-
problem.severity,
|
966
|
-
{ loc: { start: { line: problem.line, column: problem.column - 1 } } },
|
967
|
-
problem.message
|
968
|
-
);
|
969
|
-
}
|
970
|
-
}
|
971
|
-
)
|
972
|
-
);
|
973
|
-
|
974
|
-
try {
|
975
|
-
const ruleListeners = rule.create(ruleContext);
|
976
|
-
|
977
|
-
// add all the selectors from the rule as listeners
|
978
|
-
Object.keys(ruleListeners).forEach(selector => {
|
979
|
-
emitter.on(
|
980
|
-
selector,
|
981
|
-
timing.enabled
|
982
|
-
? timing.time(ruleId, ruleListeners[selector])
|
983
|
-
: ruleListeners[selector]
|
984
|
-
);
|
985
|
-
});
|
986
|
-
} catch (ex) {
|
987
|
-
ex.message = `Error while loading rule '${ruleId}': ${ex.message}`;
|
988
|
-
throw ex;
|
989
|
-
}
|
990
|
-
});
|
991
|
+
const commentDirectives = options.allowInlineConfig
|
992
|
+
? getDirectiveComments(options.filename, sourceCode.ast, ruleId => this.rules.get(ruleId))
|
993
|
+
: { configuredRules: {}, enabledGlobals: {}, exportedVariables: {}, problems: [], disableDirectives: [] };
|
991
994
|
|
992
995
|
// augment global scope with declared global variables
|
993
|
-
addDeclaredGlobals(
|
996
|
+
addDeclaredGlobals(
|
997
|
+
sourceCode.scopeManager.scopes[0],
|
998
|
+
configuredGlobals,
|
999
|
+
{ exportedVariables: commentDirectives.exportedVariables, enabledGlobals: commentDirectives.enabledGlobals }
|
1000
|
+
);
|
994
1001
|
|
995
|
-
const
|
1002
|
+
const configuredRules = Object.assign({}, config.rules, commentDirectives.configuredRules);
|
996
1003
|
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
eventGenerator.enterNode(node);
|
1007
|
-
},
|
1008
|
-
leave(node) {
|
1009
|
-
eventGenerator.leaveNode(node);
|
1010
|
-
},
|
1011
|
-
visitorKeys: sourceCode.visitorKeys
|
1012
|
-
});
|
1004
|
+
const lintingProblems = runRules(
|
1005
|
+
sourceCode,
|
1006
|
+
configuredRules,
|
1007
|
+
ruleId => this.rules.get(ruleId),
|
1008
|
+
parserOptions,
|
1009
|
+
parserName,
|
1010
|
+
settings,
|
1011
|
+
options.filename
|
1012
|
+
);
|
1013
1013
|
|
1014
1014
|
return applyDisableDirectives({
|
1015
|
-
directives: disableDirectives,
|
1016
|
-
problems:
|
1017
|
-
|
1015
|
+
directives: commentDirectives.disableDirectives,
|
1016
|
+
problems: lintingProblems
|
1017
|
+
.concat(commentDirectives.problems)
|
1018
|
+
.sort((problemA, problemB) => problemA.line - problemB.line || problemA.column - problemB.column),
|
1019
|
+
reportUnusedDisableDirectives: options.reportUnusedDisableDirectives
|
1018
1020
|
});
|
1019
1021
|
}
|
1020
1022
|
|
@@ -1034,7 +1036,7 @@ module.exports = class Linter {
|
|
1034
1036
|
* @param {function(Array<Object[]>): Object[]} [filenameOrOptions.postprocess] postprocessor for report messages. If provided,
|
1035
1037
|
* this should accept an array of the message lists for each code block returned from the preprocessor,
|
1036
1038
|
* apply a mapping to the messages as appropriate, and return a one-dimensional array of messages
|
1037
|
-
* @returns {Object[]} The results as an array of messages or
|
1039
|
+
* @returns {Object[]} The results as an array of messages or an empty array if no messages.
|
1038
1040
|
*/
|
1039
1041
|
verify(textOrSourceCode, config, filenameOrOptions) {
|
1040
1042
|
const preprocess = filenameOrOptions && filenameOrOptions.preprocess || (rawText => [rawText]);
|
@@ -1091,7 +1093,7 @@ module.exports = class Linter {
|
|
1091
1093
|
* @returns {void}
|
1092
1094
|
*/
|
1093
1095
|
defineParser(parserId, parserModule) {
|
1094
|
-
this.
|
1096
|
+
loadedParserMaps.get(this).set(parserId, parserModule);
|
1095
1097
|
}
|
1096
1098
|
|
1097
1099
|
/**
|