eslint 8.3.0 → 8.6.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/README.md +6 -16
- package/conf/globals.js +144 -0
- package/lib/cli.js +1 -1
- package/lib/config/default-config.js +11 -2
- package/lib/config/flat-config-array.js +2 -2
- package/lib/config/flat-config-helpers.js +67 -0
- package/lib/config/flat-config-schema.js +13 -8
- package/lib/config/rule-validator.js +28 -27
- package/lib/eslint/eslint.js +11 -3
- package/lib/linter/apply-disable-directives.js +20 -16
- package/lib/linter/linter.js +463 -49
- package/lib/options.js +6 -6
- package/lib/rule-tester/rule-tester.js +14 -0
- package/lib/rules/accessor-pairs.js +1 -0
- package/lib/rules/array-bracket-newline.js +1 -0
- package/lib/rules/array-bracket-spacing.js +1 -0
- package/lib/rules/array-callback-return.js +1 -0
- package/lib/rules/array-element-newline.js +1 -0
- package/lib/rules/arrow-body-style.js +1 -0
- package/lib/rules/arrow-parens.js +1 -0
- package/lib/rules/arrow-spacing.js +1 -0
- package/lib/rules/block-scoped-var.js +1 -0
- package/lib/rules/block-spacing.js +1 -0
- package/lib/rules/brace-style.js +1 -0
- package/lib/rules/callback-return.js +1 -0
- package/lib/rules/camelcase.js +1 -0
- package/lib/rules/capitalized-comments.js +1 -0
- package/lib/rules/class-methods-use-this.js +1 -0
- package/lib/rules/comma-dangle.js +1 -0
- package/lib/rules/comma-spacing.js +1 -0
- package/lib/rules/comma-style.js +1 -0
- package/lib/rules/complexity.js +1 -0
- package/lib/rules/computed-property-spacing.js +1 -0
- package/lib/rules/consistent-return.js +1 -0
- package/lib/rules/consistent-this.js +1 -0
- package/lib/rules/constructor-super.js +1 -0
- package/lib/rules/curly.js +1 -0
- package/lib/rules/default-case-last.js +1 -0
- package/lib/rules/default-case.js +1 -0
- package/lib/rules/default-param-last.js +1 -0
- package/lib/rules/dot-location.js +1 -0
- package/lib/rules/dot-notation.js +1 -0
- package/lib/rules/eol-last.js +1 -0
- package/lib/rules/eqeqeq.js +1 -0
- package/lib/rules/for-direction.js +1 -0
- package/lib/rules/func-call-spacing.js +1 -0
- package/lib/rules/func-name-matching.js +1 -0
- package/lib/rules/func-names.js +1 -0
- package/lib/rules/func-style.js +1 -0
- package/lib/rules/function-call-argument-newline.js +1 -0
- package/lib/rules/function-paren-newline.js +1 -0
- package/lib/rules/generator-star-spacing.js +1 -0
- package/lib/rules/getter-return.js +1 -0
- package/lib/rules/global-require.js +1 -0
- package/lib/rules/grouped-accessor-pairs.js +1 -0
- package/lib/rules/guard-for-in.js +1 -0
- package/lib/rules/handle-callback-err.js +1 -0
- package/lib/rules/id-blacklist.js +1 -0
- package/lib/rules/id-denylist.js +1 -0
- package/lib/rules/id-length.js +1 -0
- package/lib/rules/id-match.js +35 -0
- package/lib/rules/implicit-arrow-linebreak.js +1 -0
- package/lib/rules/indent-legacy.js +1 -0
- package/lib/rules/indent.js +1 -0
- package/lib/rules/index.js +1 -0
- package/lib/rules/init-declarations.js +1 -0
- package/lib/rules/jsx-quotes.js +1 -0
- package/lib/rules/key-spacing.js +1 -0
- package/lib/rules/keyword-spacing.js +1 -0
- package/lib/rules/line-comment-position.js +1 -0
- package/lib/rules/linebreak-style.js +1 -0
- package/lib/rules/lines-around-comment.js +1 -0
- package/lib/rules/lines-around-directive.js +1 -0
- package/lib/rules/lines-between-class-members.js +1 -0
- package/lib/rules/max-classes-per-file.js +1 -0
- package/lib/rules/max-depth.js +1 -0
- package/lib/rules/max-len.js +1 -0
- package/lib/rules/max-lines-per-function.js +1 -0
- package/lib/rules/max-lines.js +1 -0
- package/lib/rules/max-nested-callbacks.js +1 -0
- package/lib/rules/max-params.js +1 -0
- package/lib/rules/max-statements-per-line.js +1 -0
- package/lib/rules/max-statements.js +1 -0
- package/lib/rules/multiline-comment-style.js +1 -0
- package/lib/rules/multiline-ternary.js +1 -0
- package/lib/rules/new-cap.js +1 -0
- package/lib/rules/new-parens.js +1 -0
- package/lib/rules/newline-after-var.js +1 -0
- package/lib/rules/newline-before-return.js +1 -0
- package/lib/rules/newline-per-chained-call.js +1 -0
- package/lib/rules/no-alert.js +1 -0
- package/lib/rules/no-array-constructor.js +1 -0
- package/lib/rules/no-async-promise-executor.js +1 -0
- package/lib/rules/no-await-in-loop.js +1 -0
- package/lib/rules/no-bitwise.js +1 -0
- package/lib/rules/no-buffer-constructor.js +1 -0
- package/lib/rules/no-caller.js +1 -0
- package/lib/rules/no-case-declarations.js +1 -0
- package/lib/rules/no-catch-shadow.js +1 -0
- package/lib/rules/no-class-assign.js +1 -0
- package/lib/rules/no-compare-neg-zero.js +1 -0
- package/lib/rules/no-cond-assign.js +1 -0
- package/lib/rules/no-confusing-arrow.js +1 -0
- package/lib/rules/no-console.js +1 -0
- package/lib/rules/no-const-assign.js +1 -0
- package/lib/rules/no-constant-condition.js +4 -1
- package/lib/rules/no-constructor-return.js +1 -0
- package/lib/rules/no-continue.js +1 -0
- package/lib/rules/no-control-regex.js +1 -0
- package/lib/rules/no-debugger.js +1 -0
- package/lib/rules/no-delete-var.js +1 -0
- package/lib/rules/no-div-regex.js +1 -0
- package/lib/rules/no-dupe-args.js +1 -0
- package/lib/rules/no-dupe-class-members.js +1 -0
- package/lib/rules/no-dupe-else-if.js +1 -0
- package/lib/rules/no-dupe-keys.js +1 -0
- package/lib/rules/no-duplicate-case.js +1 -0
- package/lib/rules/no-duplicate-imports.js +1 -0
- package/lib/rules/no-else-return.js +1 -0
- package/lib/rules/no-empty-character-class.js +1 -0
- package/lib/rules/no-empty-function.js +1 -0
- package/lib/rules/no-empty-pattern.js +1 -0
- package/lib/rules/no-empty.js +1 -0
- package/lib/rules/no-eq-null.js +1 -0
- package/lib/rules/no-eval.js +1 -0
- package/lib/rules/no-ex-assign.js +1 -0
- package/lib/rules/no-extend-native.js +1 -0
- package/lib/rules/no-extra-bind.js +1 -0
- package/lib/rules/no-extra-boolean-cast.js +1 -0
- package/lib/rules/no-extra-label.js +1 -0
- package/lib/rules/no-extra-parens.js +1 -0
- package/lib/rules/no-extra-semi.js +1 -0
- package/lib/rules/no-fallthrough.js +1 -0
- package/lib/rules/no-floating-decimal.js +1 -0
- package/lib/rules/no-func-assign.js +1 -0
- package/lib/rules/no-global-assign.js +1 -0
- package/lib/rules/no-implicit-coercion.js +1 -0
- package/lib/rules/no-implicit-globals.js +1 -0
- package/lib/rules/no-implied-eval.js +1 -0
- package/lib/rules/no-import-assign.js +1 -0
- package/lib/rules/no-inline-comments.js +1 -0
- package/lib/rules/no-inner-declarations.js +1 -0
- package/lib/rules/no-invalid-regexp.js +1 -0
- package/lib/rules/no-invalid-this.js +1 -0
- package/lib/rules/no-irregular-whitespace.js +1 -0
- package/lib/rules/no-iterator.js +1 -0
- package/lib/rules/no-label-var.js +1 -0
- package/lib/rules/no-labels.js +1 -0
- package/lib/rules/no-lone-blocks.js +1 -0
- package/lib/rules/no-lonely-if.js +1 -0
- package/lib/rules/no-loop-func.js +1 -0
- package/lib/rules/no-loss-of-precision.js +1 -0
- package/lib/rules/no-magic-numbers.js +1 -0
- package/lib/rules/no-misleading-character-class.js +1 -0
- package/lib/rules/no-mixed-operators.js +1 -0
- package/lib/rules/no-mixed-requires.js +1 -0
- package/lib/rules/no-mixed-spaces-and-tabs.js +1 -0
- package/lib/rules/no-multi-assign.js +1 -0
- package/lib/rules/no-multi-spaces.js +1 -0
- package/lib/rules/no-multi-str.js +1 -0
- package/lib/rules/no-multiple-empty-lines.js +1 -0
- package/lib/rules/no-native-reassign.js +1 -0
- package/lib/rules/no-negated-condition.js +1 -0
- package/lib/rules/no-negated-in-lhs.js +1 -0
- package/lib/rules/no-nested-ternary.js +1 -0
- package/lib/rules/no-new-func.js +1 -0
- package/lib/rules/no-new-object.js +1 -0
- package/lib/rules/no-new-require.js +1 -0
- package/lib/rules/no-new-symbol.js +1 -0
- package/lib/rules/no-new-wrappers.js +1 -0
- package/lib/rules/no-new.js +1 -0
- package/lib/rules/no-nonoctal-decimal-escape.js +1 -0
- package/lib/rules/no-obj-calls.js +1 -0
- package/lib/rules/no-octal-escape.js +1 -0
- package/lib/rules/no-octal.js +1 -0
- package/lib/rules/no-param-reassign.js +1 -0
- package/lib/rules/no-path-concat.js +1 -0
- package/lib/rules/no-plusplus.js +1 -0
- package/lib/rules/no-process-env.js +1 -0
- package/lib/rules/no-process-exit.js +1 -0
- package/lib/rules/no-promise-executor-return.js +1 -0
- package/lib/rules/no-proto.js +1 -0
- package/lib/rules/no-prototype-builtins.js +1 -0
- package/lib/rules/no-redeclare.js +1 -0
- package/lib/rules/no-regex-spaces.js +1 -0
- package/lib/rules/no-restricted-exports.js +1 -0
- package/lib/rules/no-restricted-globals.js +1 -0
- package/lib/rules/no-restricted-imports.js +1 -0
- package/lib/rules/no-restricted-modules.js +1 -0
- package/lib/rules/no-restricted-properties.js +1 -0
- package/lib/rules/no-restricted-syntax.js +1 -0
- package/lib/rules/no-return-assign.js +1 -0
- package/lib/rules/no-return-await.js +1 -0
- package/lib/rules/no-script-url.js +1 -0
- package/lib/rules/no-self-assign.js +2 -1
- package/lib/rules/no-self-compare.js +1 -0
- package/lib/rules/no-sequences.js +1 -0
- package/lib/rules/no-setter-return.js +1 -0
- package/lib/rules/no-shadow-restricted-names.js +1 -0
- package/lib/rules/no-shadow.js +1 -0
- package/lib/rules/no-spaced-func.js +1 -0
- package/lib/rules/no-sparse-arrays.js +1 -0
- package/lib/rules/no-sync.js +1 -0
- package/lib/rules/no-tabs.js +1 -0
- package/lib/rules/no-template-curly-in-string.js +1 -0
- package/lib/rules/no-ternary.js +1 -0
- package/lib/rules/no-this-before-super.js +1 -0
- package/lib/rules/no-throw-literal.js +1 -0
- package/lib/rules/no-trailing-spaces.js +1 -0
- package/lib/rules/no-undef-init.js +1 -0
- package/lib/rules/no-undef.js +1 -0
- package/lib/rules/no-undefined.js +1 -0
- package/lib/rules/no-underscore-dangle.js +1 -0
- package/lib/rules/no-unexpected-multiline.js +1 -0
- package/lib/rules/no-unmodified-loop-condition.js +1 -0
- package/lib/rules/no-unneeded-ternary.js +1 -0
- package/lib/rules/no-unreachable-loop.js +1 -0
- package/lib/rules/no-unreachable.js +1 -0
- package/lib/rules/no-unsafe-finally.js +1 -0
- package/lib/rules/no-unsafe-negation.js +1 -0
- package/lib/rules/no-unsafe-optional-chaining.js +1 -0
- package/lib/rules/no-unused-expressions.js +1 -0
- package/lib/rules/no-unused-labels.js +1 -0
- package/lib/rules/no-unused-private-class-members.js +1 -0
- package/lib/rules/no-unused-vars.js +1 -0
- package/lib/rules/no-use-before-define.js +1 -0
- package/lib/rules/no-useless-backreference.js +1 -0
- package/lib/rules/no-useless-call.js +1 -0
- package/lib/rules/no-useless-catch.js +1 -0
- package/lib/rules/no-useless-computed-key.js +1 -0
- package/lib/rules/no-useless-concat.js +1 -0
- package/lib/rules/no-useless-constructor.js +1 -0
- package/lib/rules/no-useless-escape.js +1 -0
- package/lib/rules/no-useless-rename.js +1 -0
- package/lib/rules/no-useless-return.js +1 -0
- package/lib/rules/no-var.js +1 -0
- package/lib/rules/no-void.js +1 -0
- package/lib/rules/no-warning-comments.js +1 -0
- package/lib/rules/no-whitespace-before-property.js +1 -0
- package/lib/rules/no-with.js +1 -0
- package/lib/rules/nonblock-statement-body-position.js +1 -0
- package/lib/rules/object-curly-newline.js +1 -0
- package/lib/rules/object-curly-spacing.js +1 -0
- package/lib/rules/object-property-newline.js +1 -0
- package/lib/rules/object-shorthand.js +1 -0
- package/lib/rules/one-var-declaration-per-line.js +1 -0
- package/lib/rules/one-var.js +1 -0
- package/lib/rules/operator-assignment.js +1 -0
- package/lib/rules/operator-linebreak.js +1 -0
- package/lib/rules/padded-blocks.js +1 -0
- package/lib/rules/padding-line-between-statements.js +1 -0
- package/lib/rules/prefer-arrow-callback.js +1 -0
- package/lib/rules/prefer-const.js +1 -0
- package/lib/rules/prefer-destructuring.js +1 -0
- package/lib/rules/prefer-exponentiation-operator.js +1 -0
- package/lib/rules/prefer-named-capture-group.js +1 -0
- package/lib/rules/prefer-numeric-literals.js +1 -0
- package/lib/rules/prefer-object-has-own.js +112 -0
- package/lib/rules/prefer-object-spread.js +1 -0
- package/lib/rules/prefer-promise-reject-errors.js +1 -0
- package/lib/rules/prefer-reflect.js +1 -0
- package/lib/rules/prefer-regex-literals.js +218 -1
- package/lib/rules/prefer-rest-params.js +1 -0
- package/lib/rules/prefer-spread.js +1 -0
- package/lib/rules/prefer-template.js +2 -1
- package/lib/rules/quote-props.js +1 -0
- package/lib/rules/quotes.js +1 -0
- package/lib/rules/radix.js +1 -0
- package/lib/rules/require-atomic-updates.js +1 -0
- package/lib/rules/require-await.js +1 -0
- package/lib/rules/require-jsdoc.js +1 -0
- package/lib/rules/require-unicode-regexp.js +1 -0
- package/lib/rules/require-yield.js +1 -0
- package/lib/rules/rest-spread-spacing.js +1 -0
- package/lib/rules/semi-spacing.js +1 -0
- package/lib/rules/semi-style.js +1 -0
- package/lib/rules/semi.js +1 -0
- package/lib/rules/sort-imports.js +1 -0
- package/lib/rules/sort-keys.js +1 -0
- package/lib/rules/sort-vars.js +1 -0
- package/lib/rules/space-before-blocks.js +1 -0
- package/lib/rules/space-before-function-paren.js +1 -0
- package/lib/rules/space-in-parens.js +1 -0
- package/lib/rules/space-infix-ops.js +1 -0
- package/lib/rules/space-unary-ops.js +1 -0
- package/lib/rules/spaced-comment.js +1 -0
- package/lib/rules/strict.js +1 -0
- package/lib/rules/switch-colon-spacing.js +1 -0
- package/lib/rules/symbol-description.js +1 -0
- package/lib/rules/template-curly-spacing.js +1 -0
- package/lib/rules/template-tag-spacing.js +1 -0
- package/lib/rules/unicode-bom.js +1 -0
- package/lib/rules/use-isnan.js +1 -0
- package/lib/rules/valid-jsdoc.js +1 -0
- package/lib/rules/valid-typeof.js +1 -0
- package/lib/rules/vars-on-top.js +1 -0
- package/lib/rules/wrap-iife.js +1 -0
- package/lib/rules/wrap-regex.js +1 -0
- package/lib/rules/yield-star-spacing.js +1 -0
- package/lib/rules/yoda.js +1 -0
- package/lib/shared/types.js +10 -0
- package/package.json +7 -6
package/lib/linter/linter.js
CHANGED
@@ -37,6 +37,8 @@ const
|
|
37
37
|
SourceCodeFixer = require("./source-code-fixer"),
|
38
38
|
timing = require("./timing"),
|
39
39
|
ruleReplacements = require("../../conf/replacements.json");
|
40
|
+
const { getRuleFromConfig } = require("../config/flat-config-helpers");
|
41
|
+
const { FlatConfigArray } = require("../config/flat-config-array");
|
40
42
|
|
41
43
|
const debug = require("debug")("eslint:linter");
|
42
44
|
const MAX_AUTOFIX_PASSES = 10;
|
@@ -45,6 +47,7 @@ const DEFAULT_ECMA_VERSION = 5;
|
|
45
47
|
const commentParser = new ConfigCommentParser();
|
46
48
|
const DEFAULT_ERROR_LOC = { start: { line: 1, column: 0 }, end: { line: 1, column: 1 } };
|
47
49
|
const parserSymbol = Symbol.for("eslint.RuleTester.parser");
|
50
|
+
const globals = require("../../conf/globals");
|
48
51
|
|
49
52
|
//------------------------------------------------------------------------------
|
50
53
|
// Typedefs
|
@@ -57,6 +60,7 @@ const parserSymbol = Symbol.for("eslint.RuleTester.parser");
|
|
57
60
|
/** @typedef {import("../shared/types").GlobalConf} GlobalConf */
|
58
61
|
/** @typedef {import("../shared/types").LintMessage} LintMessage */
|
59
62
|
/** @typedef {import("../shared/types").ParserOptions} ParserOptions */
|
63
|
+
/** @typedef {import("../shared/types").LanguageOptions} LanguageOptions */
|
60
64
|
/** @typedef {import("../shared/types").Processor} Processor */
|
61
65
|
/** @typedef {import("../shared/types").Rule} Rule */
|
62
66
|
|
@@ -126,6 +130,38 @@ const parserSymbol = Symbol.for("eslint.RuleTester.parser");
|
|
126
130
|
// Helpers
|
127
131
|
//------------------------------------------------------------------------------
|
128
132
|
|
133
|
+
/**
|
134
|
+
* Determines if a given object is Espree.
|
135
|
+
* @param {Object} parser The parser to check.
|
136
|
+
* @returns {boolean} True if the parser is Espree or false if not.
|
137
|
+
*/
|
138
|
+
function isEspree(parser) {
|
139
|
+
return !!(parser === espree || parser[parserSymbol] === espree);
|
140
|
+
}
|
141
|
+
|
142
|
+
/**
|
143
|
+
* Retrieves globals for the given ecmaVersion.
|
144
|
+
* @param {number} ecmaVersion The version to retrieve globals for.
|
145
|
+
* @returns {Object} The globals for the given ecmaVersion.
|
146
|
+
*/
|
147
|
+
function getGlobalsForEcmaVersion(ecmaVersion) {
|
148
|
+
|
149
|
+
switch (ecmaVersion) {
|
150
|
+
case 3:
|
151
|
+
return globals.es3;
|
152
|
+
|
153
|
+
case 5:
|
154
|
+
return globals.es5;
|
155
|
+
|
156
|
+
default:
|
157
|
+
if (ecmaVersion < 2015) {
|
158
|
+
return globals[`es${ecmaVersion + 2009}`];
|
159
|
+
}
|
160
|
+
|
161
|
+
return globals[`es${ecmaVersion}`];
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
129
165
|
/**
|
130
166
|
* Ensures that variables representing built-in properties of the Global Object,
|
131
167
|
* and any globals declared by special block comments, are present in the global
|
@@ -268,8 +304,12 @@ function createDisableDirectives(options) {
|
|
268
304
|
for (const ruleId of directiveRules) {
|
269
305
|
|
270
306
|
// push to directives, if the rule is defined(including null, e.g. /*eslint enable*/)
|
271
|
-
if (ruleId === null || ruleMapper(ruleId)
|
272
|
-
|
307
|
+
if (ruleId === null || !!ruleMapper(ruleId)) {
|
308
|
+
if (type === "disable-next-line") {
|
309
|
+
result.directives.push({ parentComment, type, line: commentToken.loc.end.line, column: commentToken.loc.end.column + 1, ruleId });
|
310
|
+
} else {
|
311
|
+
result.directives.push({ parentComment, type, line: commentToken.loc.start.line, column: commentToken.loc.start.column + 1, ruleId });
|
312
|
+
}
|
273
313
|
} else {
|
274
314
|
result.directiveProblems.push(createLintingProblem({ ruleId, loc: commentToken.loc }));
|
275
315
|
}
|
@@ -290,14 +330,13 @@ function stripDirectiveComment(value) {
|
|
290
330
|
* Parses comments in file to extract file-specific config of rules, globals
|
291
331
|
* and environments and merges them with global config; also code blocks
|
292
332
|
* where reporting is disabled or enabled and merges them with reporting config.
|
293
|
-
* @param {string} filename The file being checked.
|
294
333
|
* @param {ASTNode} ast The top node of the AST.
|
295
334
|
* @param {function(string): {create: Function}} ruleMapper A map from rule IDs to defined rules
|
296
335
|
* @param {string|null} warnInlineConfig If a string then it should warn directive comments as disabled. The string value is the config name what the setting came from.
|
297
336
|
* @returns {{configuredRules: Object, enabledGlobals: {value:string,comment:Token}[], exportedVariables: Object, problems: Problem[], disableDirectives: DisableDirective[]}}
|
298
337
|
* A collection of the directive comments that were found, along with any problems that occurred when parsing
|
299
338
|
*/
|
300
|
-
function getDirectiveComments(
|
339
|
+
function getDirectiveComments(ast, ruleMapper, warnInlineConfig) {
|
301
340
|
const configuredRules = {};
|
302
341
|
const enabledGlobals = Object.create(null);
|
303
342
|
const exportedVariables = {};
|
@@ -333,7 +372,7 @@ function getDirectiveComments(filename, ast, ruleMapper, warnInlineConfig) {
|
|
333
372
|
return;
|
334
373
|
}
|
335
374
|
|
336
|
-
if (
|
375
|
+
if (directiveText === "eslint-disable-line" && comment.loc.start.line !== comment.loc.end.line) {
|
337
376
|
const message = `${directiveText} comment should not span multiple lines.`;
|
338
377
|
|
339
378
|
problems.push(createLintingProblem({
|
@@ -400,7 +439,7 @@ function getDirectiveComments(filename, ast, ruleMapper, warnInlineConfig) {
|
|
400
439
|
const rule = ruleMapper(name);
|
401
440
|
const ruleValue = parseResult.config[name];
|
402
441
|
|
403
|
-
if (rule
|
442
|
+
if (!rule) {
|
404
443
|
problems.push(createLintingProblem({ ruleId: name, loc: comment.loc }));
|
405
444
|
return;
|
406
445
|
}
|
@@ -447,7 +486,8 @@ function getDirectiveComments(filename, ast, ruleMapper, warnInlineConfig) {
|
|
447
486
|
* @returns {number} normalized ECMAScript version
|
448
487
|
*/
|
449
488
|
function normalizeEcmaVersion(parser, ecmaVersion) {
|
450
|
-
|
489
|
+
|
490
|
+
if (isEspree(parser)) {
|
451
491
|
if (ecmaVersion === "latest") {
|
452
492
|
return espree.latestEcmaVersion;
|
453
493
|
}
|
@@ -460,6 +500,38 @@ function normalizeEcmaVersion(parser, ecmaVersion) {
|
|
460
500
|
return ecmaVersion >= 2015 ? ecmaVersion - 2009 : ecmaVersion;
|
461
501
|
}
|
462
502
|
|
503
|
+
/**
|
504
|
+
* Normalize ECMAScript version from the initial config into languageOptions (year)
|
505
|
+
* format.
|
506
|
+
* @param {any} [ecmaVersion] ECMAScript version from the initial config
|
507
|
+
* @returns {number} normalized ECMAScript version
|
508
|
+
*/
|
509
|
+
function normalizeEcmaVersionForLanguageOptions(ecmaVersion) {
|
510
|
+
|
511
|
+
switch (ecmaVersion) {
|
512
|
+
case 3:
|
513
|
+
return 3;
|
514
|
+
|
515
|
+
// void 0 = no ecmaVersion specified so use the default
|
516
|
+
case 5:
|
517
|
+
case void 0:
|
518
|
+
return 5;
|
519
|
+
|
520
|
+
default:
|
521
|
+
if (typeof ecmaVersion === "number") {
|
522
|
+
return ecmaVersion >= 2015 ? ecmaVersion : ecmaVersion + 2009;
|
523
|
+
}
|
524
|
+
}
|
525
|
+
|
526
|
+
/*
|
527
|
+
* We default to the latest supported ecmaVersion for everything else.
|
528
|
+
* Remember, this is for languageOptions.ecmaVersion, which sets the version
|
529
|
+
* that is used for a number of processes inside of ESLint. It's normally
|
530
|
+
* safe to assume people want the latest unless otherwise specified.
|
531
|
+
*/
|
532
|
+
return espree.latestEcmaVersion + 2009;
|
533
|
+
}
|
534
|
+
|
463
535
|
const eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)(?:\*\/|$)/gsu;
|
464
536
|
|
465
537
|
/**
|
@@ -511,7 +583,11 @@ function normalizeFilename(filename) {
|
|
511
583
|
* @returns {Required<VerifyOptions> & InternalOptions} Normalized options
|
512
584
|
*/
|
513
585
|
function normalizeVerifyOptions(providedOptions, config) {
|
514
|
-
|
586
|
+
|
587
|
+
const linterOptions = config.linterOptions || config;
|
588
|
+
|
589
|
+
// .noInlineConfig for eslintrc, .linterOptions.noInlineConfig for flat
|
590
|
+
const disableInlineConfig = linterOptions.noInlineConfig === true;
|
515
591
|
const ignoreInlineConfig = providedOptions.allowInlineConfig === false;
|
516
592
|
const configNameOfNoInlineConfig = config.configNameOfNoInlineConfig
|
517
593
|
? ` (${config.configNameOfNoInlineConfig})`
|
@@ -523,7 +599,9 @@ function normalizeVerifyOptions(providedOptions, config) {
|
|
523
599
|
reportUnusedDisableDirectives = reportUnusedDisableDirectives ? "error" : "off";
|
524
600
|
}
|
525
601
|
if (typeof reportUnusedDisableDirectives !== "string") {
|
526
|
-
reportUnusedDisableDirectives =
|
602
|
+
reportUnusedDisableDirectives =
|
603
|
+
linterOptions.reportUnusedDisableDirectives
|
604
|
+
? "warn" : "off";
|
527
605
|
}
|
528
606
|
|
529
607
|
return {
|
@@ -566,6 +644,30 @@ function resolveParserOptions(parser, providedOptions, enabledEnvironments) {
|
|
566
644
|
return mergedParserOptions;
|
567
645
|
}
|
568
646
|
|
647
|
+
/**
|
648
|
+
* Converts parserOptions to languageOptions for backwards compatibility with eslintrc.
|
649
|
+
* @param {ConfigData} config Config object.
|
650
|
+
* @param {Object} config.globals Global variable definitions.
|
651
|
+
* @param {Parser} config.parser The parser to use.
|
652
|
+
* @param {ParserOptions} config.parserOptions The parserOptions to use.
|
653
|
+
* @returns {LanguageOptions} The languageOptions equivalent.
|
654
|
+
*/
|
655
|
+
function createLanguageOptions({ globals: configuredGlobals, parser, parserOptions }) {
|
656
|
+
|
657
|
+
const {
|
658
|
+
ecmaVersion,
|
659
|
+
sourceType
|
660
|
+
} = parserOptions;
|
661
|
+
|
662
|
+
return {
|
663
|
+
globals: configuredGlobals,
|
664
|
+
ecmaVersion: normalizeEcmaVersionForLanguageOptions(ecmaVersion),
|
665
|
+
sourceType,
|
666
|
+
parser,
|
667
|
+
parserOptions
|
668
|
+
};
|
669
|
+
}
|
670
|
+
|
569
671
|
/**
|
570
672
|
* Combines the provided globals object with the globals from environments
|
571
673
|
* @param {Record<string, GlobalConf>} providedGlobals The 'globals' key in a config
|
@@ -614,20 +716,21 @@ function getRuleOptions(ruleConfig) {
|
|
614
716
|
/**
|
615
717
|
* Analyze scope of the given AST.
|
616
718
|
* @param {ASTNode} ast The `Program` node to analyze.
|
617
|
-
* @param {
|
719
|
+
* @param {LanguageOptions} languageOptions The parser options.
|
618
720
|
* @param {Record<string, string[]>} visitorKeys The visitor keys.
|
619
721
|
* @returns {ScopeManager} The analysis result.
|
620
722
|
*/
|
621
|
-
function analyzeScope(ast,
|
723
|
+
function analyzeScope(ast, languageOptions, visitorKeys) {
|
724
|
+
const parserOptions = languageOptions.parserOptions;
|
622
725
|
const ecmaFeatures = parserOptions.ecmaFeatures || {};
|
623
|
-
const ecmaVersion =
|
726
|
+
const ecmaVersion = languageOptions.ecmaVersion || DEFAULT_ECMA_VERSION;
|
624
727
|
|
625
728
|
return eslintScope.analyze(ast, {
|
626
729
|
ignoreEval: true,
|
627
730
|
nodejsScope: ecmaFeatures.globalReturn,
|
628
731
|
impliedStrict: ecmaFeatures.impliedStrict,
|
629
732
|
ecmaVersion: typeof ecmaVersion === "number" ? ecmaVersion : 6,
|
630
|
-
sourceType:
|
733
|
+
sourceType: languageOptions.sourceType || "script",
|
631
734
|
childVisitorKeys: visitorKeys || evk.KEYS,
|
632
735
|
fallback: Traverser.getKeys
|
633
736
|
});
|
@@ -638,25 +741,29 @@ function analyzeScope(ast, parserOptions, visitorKeys) {
|
|
638
741
|
* optimization of functions, so it's best to keep the try-catch as isolated
|
639
742
|
* as possible
|
640
743
|
* @param {string} text The text to parse.
|
641
|
-
* @param {
|
642
|
-
* @param {ParserOptions} providedParserOptions Options to pass to the parser
|
744
|
+
* @param {LanguageOptions} languageOptions Options to pass to the parser
|
643
745
|
* @param {string} filePath The path to the file being parsed.
|
644
746
|
* @returns {{success: false, error: Problem}|{success: true, sourceCode: SourceCode}}
|
645
747
|
* An object containing the AST and parser services if parsing was successful, or the error if parsing failed
|
646
748
|
* @private
|
647
749
|
*/
|
648
|
-
function parse(text,
|
750
|
+
function parse(text, languageOptions, filePath) {
|
649
751
|
const textToParse = stripUnicodeBOM(text).replace(astUtils.shebangPattern, (match, captured) => `//${captured}`);
|
650
|
-
const
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
752
|
+
const { ecmaVersion, sourceType, parser } = languageOptions;
|
753
|
+
const parserOptions = Object.assign(
|
754
|
+
{ ecmaVersion, sourceType },
|
755
|
+
languageOptions.parserOptions,
|
756
|
+
{
|
757
|
+
loc: true,
|
758
|
+
range: true,
|
759
|
+
raw: true,
|
760
|
+
tokens: true,
|
761
|
+
comment: true,
|
762
|
+
eslintVisitorKeys: true,
|
763
|
+
eslintScopeManager: true,
|
764
|
+
filePath
|
765
|
+
}
|
766
|
+
);
|
660
767
|
|
661
768
|
/*
|
662
769
|
* Check for parsing errors first. If there's a parsing error, nothing
|
@@ -671,7 +778,7 @@ function parse(text, parser, providedParserOptions, filePath) {
|
|
671
778
|
const ast = parseResult.ast;
|
672
779
|
const parserServices = parseResult.services || {};
|
673
780
|
const visitorKeys = parseResult.visitorKeys || evk.KEYS;
|
674
|
-
const scopeManager = parseResult.scopeManager || analyzeScope(ast,
|
781
|
+
const scopeManager = parseResult.scopeManager || analyzeScope(ast, languageOptions, visitorKeys);
|
675
782
|
|
676
783
|
return {
|
677
784
|
success: true,
|
@@ -740,13 +847,17 @@ function getScope(scopeManager, currentNode) {
|
|
740
847
|
* Marks a variable as used in the current scope
|
741
848
|
* @param {ScopeManager} scopeManager The scope manager for this AST. The scope may be mutated by this function.
|
742
849
|
* @param {ASTNode} currentNode The node currently being traversed
|
743
|
-
* @param {
|
850
|
+
* @param {LanguageOptions} languageOptions The options used to parse this text
|
744
851
|
* @param {string} name The name of the variable that should be marked as used.
|
745
852
|
* @returns {boolean} True if the variable was found and marked as used, false if not.
|
746
853
|
*/
|
747
|
-
function markVariableAsUsed(scopeManager, currentNode,
|
748
|
-
const
|
749
|
-
const
|
854
|
+
function markVariableAsUsed(scopeManager, currentNode, languageOptions, name) {
|
855
|
+
const parserOptions = languageOptions.parserOptions;
|
856
|
+
const sourceType = languageOptions.sourceType;
|
857
|
+
const hasGlobalReturn =
|
858
|
+
(parserOptions.ecmaFeatures && parserOptions.ecmaFeatures.globalReturn) ||
|
859
|
+
sourceType === "commonjs";
|
860
|
+
const specialScope = hasGlobalReturn || sourceType === "module";
|
750
861
|
const currentScope = getScope(scopeManager, currentNode);
|
751
862
|
|
752
863
|
// Special Node.js scope means we need to start one level deeper
|
@@ -837,8 +948,8 @@ const BASE_TRAVERSAL_CONTEXT = Object.freeze(
|
|
837
948
|
* @param {SourceCode} sourceCode A SourceCode object for the given text
|
838
949
|
* @param {Object} configuredRules The rules configuration
|
839
950
|
* @param {function(string): Rule} ruleMapper A mapper function from rule names to rules
|
840
|
-
* @param {
|
841
|
-
* @param {
|
951
|
+
* @param {string | undefined} parserName The name of the parser in the config
|
952
|
+
* @param {LanguageOptions} languageOptions The options for parsing the code.
|
842
953
|
* @param {Object} settings The settings that were enabled in the config
|
843
954
|
* @param {string} filename The reported filename of the code
|
844
955
|
* @param {boolean} disableFixes If true, it doesn't make `fix` properties.
|
@@ -846,7 +957,7 @@ const BASE_TRAVERSAL_CONTEXT = Object.freeze(
|
|
846
957
|
* @param {string} physicalFilename The full path of the file on disk without any code block information
|
847
958
|
* @returns {Problem[]} An array of reported problems
|
848
959
|
*/
|
849
|
-
function runRules(sourceCode, configuredRules, ruleMapper,
|
960
|
+
function runRules(sourceCode, configuredRules, ruleMapper, parserName, languageOptions, settings, filename, disableFixes, cwd, physicalFilename) {
|
850
961
|
const emitter = createEmitter();
|
851
962
|
const nodeQueue = [];
|
852
963
|
let currentNode = sourceCode.ast;
|
@@ -878,16 +989,18 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parser
|
|
878
989
|
getPhysicalFilename: () => physicalFilename || filename,
|
879
990
|
getScope: () => getScope(sourceCode.scopeManager, currentNode),
|
880
991
|
getSourceCode: () => sourceCode,
|
881
|
-
markVariableAsUsed: name => markVariableAsUsed(sourceCode.scopeManager, currentNode,
|
882
|
-
parserOptions
|
992
|
+
markVariableAsUsed: name => markVariableAsUsed(sourceCode.scopeManager, currentNode, languageOptions, name),
|
993
|
+
parserOptions: {
|
994
|
+
...languageOptions.parserOptions
|
995
|
+
},
|
883
996
|
parserPath: parserName,
|
997
|
+
languageOptions,
|
884
998
|
parserServices: sourceCode.parserServices,
|
885
999
|
settings
|
886
1000
|
}
|
887
1001
|
)
|
888
1002
|
);
|
889
1003
|
|
890
|
-
|
891
1004
|
const lintingProblems = [];
|
892
1005
|
|
893
1006
|
Object.keys(configuredRules).forEach(ruleId => {
|
@@ -900,7 +1013,7 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parser
|
|
900
1013
|
|
901
1014
|
const rule = ruleMapper(ruleId);
|
902
1015
|
|
903
|
-
if (rule
|
1016
|
+
if (!rule) {
|
904
1017
|
lintingProblems.push(createLintingProblem({ ruleId }));
|
905
1018
|
return;
|
906
1019
|
}
|
@@ -1074,13 +1187,28 @@ function normalizeCwd(cwd) {
|
|
1074
1187
|
*/
|
1075
1188
|
const internalSlotsMap = new WeakMap();
|
1076
1189
|
|
1190
|
+
/**
|
1191
|
+
* Throws an error when the given linter is in flat config mode.
|
1192
|
+
* @param {Linter} linter The linter to check.
|
1193
|
+
* @returns {void}
|
1194
|
+
* @throws {Error} If the linter is in flat config mode.
|
1195
|
+
*/
|
1196
|
+
function assertEslintrcConfig(linter) {
|
1197
|
+
const { configType } = internalSlotsMap.get(linter);
|
1198
|
+
|
1199
|
+
if (configType === "flat") {
|
1200
|
+
throw new Error("This method cannot be used with flat config. Add your entries directly into the config array.");
|
1201
|
+
}
|
1202
|
+
}
|
1203
|
+
|
1204
|
+
|
1077
1205
|
//------------------------------------------------------------------------------
|
1078
1206
|
// Public Interface
|
1079
1207
|
//------------------------------------------------------------------------------
|
1080
1208
|
|
1081
1209
|
/**
|
1082
1210
|
* Object that is responsible for verifying JavaScript text
|
1083
|
-
* @name
|
1211
|
+
* @name Linter
|
1084
1212
|
*/
|
1085
1213
|
class Linter {
|
1086
1214
|
|
@@ -1088,12 +1216,14 @@ class Linter {
|
|
1088
1216
|
* Initialize the Linter.
|
1089
1217
|
* @param {Object} [config] the config object
|
1090
1218
|
* @param {string} [config.cwd] path to a directory that should be considered as the current working directory, can be undefined.
|
1219
|
+
* @param {"flat"|"eslintrc"} [config.configType="eslintrc"] the type of config used.
|
1091
1220
|
*/
|
1092
|
-
constructor({ cwd } = {}) {
|
1221
|
+
constructor({ cwd, configType } = {}) {
|
1093
1222
|
internalSlotsMap.set(this, {
|
1094
1223
|
cwd: normalizeCwd(cwd),
|
1095
1224
|
lastConfigArray: null,
|
1096
1225
|
lastSourceCode: null,
|
1226
|
+
configType, // TODO: Remove after flat config conversion
|
1097
1227
|
parserMap: new Map([["espree", espree]]),
|
1098
1228
|
ruleMap: new Rules()
|
1099
1229
|
});
|
@@ -1168,12 +1298,16 @@ class Linter {
|
|
1168
1298
|
const parserOptions = resolveParserOptions(parser, config.parserOptions || {}, enabledEnvs);
|
1169
1299
|
const configuredGlobals = resolveGlobals(config.globals || {}, enabledEnvs);
|
1170
1300
|
const settings = config.settings || {};
|
1301
|
+
const languageOptions = createLanguageOptions({
|
1302
|
+
globals: config.globals,
|
1303
|
+
parser,
|
1304
|
+
parserOptions
|
1305
|
+
});
|
1171
1306
|
|
1172
1307
|
if (!slots.lastSourceCode) {
|
1173
1308
|
const parseResult = parse(
|
1174
1309
|
text,
|
1175
|
-
|
1176
|
-
parserOptions,
|
1310
|
+
languageOptions,
|
1177
1311
|
options.filename
|
1178
1312
|
);
|
1179
1313
|
|
@@ -1194,14 +1328,14 @@ class Linter {
|
|
1194
1328
|
ast: slots.lastSourceCode.ast,
|
1195
1329
|
parserServices: slots.lastSourceCode.parserServices,
|
1196
1330
|
visitorKeys: slots.lastSourceCode.visitorKeys,
|
1197
|
-
scopeManager: analyzeScope(slots.lastSourceCode.ast,
|
1331
|
+
scopeManager: analyzeScope(slots.lastSourceCode.ast, languageOptions)
|
1198
1332
|
});
|
1199
1333
|
}
|
1200
1334
|
}
|
1201
1335
|
|
1202
1336
|
const sourceCode = slots.lastSourceCode;
|
1203
1337
|
const commentDirectives = options.allowInlineConfig
|
1204
|
-
? getDirectiveComments(
|
1338
|
+
? getDirectiveComments(sourceCode.ast, ruleId => getRule(slots, ruleId), options.warnInlineConfig)
|
1205
1339
|
: { configuredRules: {}, enabledGlobals: {}, exportedVariables: {}, problems: [], disableDirectives: [] };
|
1206
1340
|
|
1207
1341
|
// augment global scope with declared global variables
|
@@ -1220,8 +1354,8 @@ class Linter {
|
|
1220
1354
|
sourceCode,
|
1221
1355
|
configuredRules,
|
1222
1356
|
ruleId => getRule(slots, ruleId),
|
1223
|
-
parserOptions,
|
1224
1357
|
parserName,
|
1358
|
+
languageOptions,
|
1225
1359
|
settings,
|
1226
1360
|
options.filename,
|
1227
1361
|
options.disableFixes,
|
@@ -1270,15 +1404,43 @@ class Linter {
|
|
1270
1404
|
*/
|
1271
1405
|
verify(textOrSourceCode, config, filenameOrOptions) {
|
1272
1406
|
debug("Verify");
|
1407
|
+
|
1408
|
+
const { configType } = internalSlotsMap.get(this);
|
1409
|
+
|
1273
1410
|
const options = typeof filenameOrOptions === "string"
|
1274
1411
|
? { filename: filenameOrOptions }
|
1275
1412
|
: filenameOrOptions || {};
|
1276
1413
|
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1414
|
+
if (config) {
|
1415
|
+
if (configType === "flat") {
|
1416
|
+
|
1417
|
+
/*
|
1418
|
+
* Because of how Webpack packages up the files, we can't
|
1419
|
+
* compare directly to `FlatConfigArray` using `instanceof`
|
1420
|
+
* because it's not the same `FlatConfigArray` as in the tests.
|
1421
|
+
* So, we work around it by assuming an array is, in fact, a
|
1422
|
+
* `FlatConfigArray` if it has a `getConfig()` method.
|
1423
|
+
*/
|
1424
|
+
let configArray = config;
|
1425
|
+
|
1426
|
+
if (!Array.isArray(config) || typeof config.getConfig !== "function") {
|
1427
|
+
configArray = new FlatConfigArray(config);
|
1428
|
+
configArray.normalizeSync();
|
1429
|
+
}
|
1430
|
+
|
1431
|
+
return this._verifyWithFlatConfigArray(textOrSourceCode, configArray, options, true);
|
1432
|
+
}
|
1433
|
+
|
1434
|
+
if (typeof config.extractConfig === "function") {
|
1435
|
+
return this._verifyWithConfigArray(textOrSourceCode, config, options);
|
1436
|
+
}
|
1280
1437
|
}
|
1281
1438
|
|
1439
|
+
/*
|
1440
|
+
* If we get to here, it means `config` is just an object rather
|
1441
|
+
* than a config array so we can go right into linting.
|
1442
|
+
*/
|
1443
|
+
|
1282
1444
|
/*
|
1283
1445
|
* `Linter` doesn't support `overrides` property in configuration.
|
1284
1446
|
* So we cannot apply multiple processors.
|
@@ -1289,6 +1451,213 @@ class Linter {
|
|
1289
1451
|
return this._verifyWithoutProcessors(textOrSourceCode, config, options);
|
1290
1452
|
}
|
1291
1453
|
|
1454
|
+
/**
|
1455
|
+
* Verify with a processor.
|
1456
|
+
* @param {string|SourceCode} textOrSourceCode The source code.
|
1457
|
+
* @param {FlatConfig} config The config array.
|
1458
|
+
* @param {VerifyOptions&ProcessorOptions} options The options.
|
1459
|
+
* @param {FlatConfigArray} [configForRecursive] The `ConfigArray` object to apply multiple processors recursively.
|
1460
|
+
* @returns {LintMessage[]} The found problems.
|
1461
|
+
*/
|
1462
|
+
_verifyWithFlatConfigArrayAndProcessor(textOrSourceCode, config, options, configForRecursive) {
|
1463
|
+
const filename = options.filename || "<input>";
|
1464
|
+
const filenameToExpose = normalizeFilename(filename);
|
1465
|
+
const physicalFilename = options.physicalFilename || filenameToExpose;
|
1466
|
+
const text = ensureText(textOrSourceCode);
|
1467
|
+
const preprocess = options.preprocess || (rawText => [rawText]);
|
1468
|
+
const postprocess = options.postprocess || (messagesList => messagesList.flat());
|
1469
|
+
const filterCodeBlock =
|
1470
|
+
options.filterCodeBlock ||
|
1471
|
+
(blockFilename => blockFilename.endsWith(".js"));
|
1472
|
+
const originalExtname = path.extname(filename);
|
1473
|
+
const messageLists = preprocess(text, filenameToExpose).map((block, i) => {
|
1474
|
+
debug("A code block was found: %o", block.filename || "(unnamed)");
|
1475
|
+
|
1476
|
+
// Keep the legacy behavior.
|
1477
|
+
if (typeof block === "string") {
|
1478
|
+
return this._verifyWithFlatConfigArrayAndWithoutProcessors(block, config, options);
|
1479
|
+
}
|
1480
|
+
|
1481
|
+
const blockText = block.text;
|
1482
|
+
const blockName = path.join(filename, `${i}_${block.filename}`);
|
1483
|
+
|
1484
|
+
// Skip this block if filtered.
|
1485
|
+
if (!filterCodeBlock(blockName, blockText)) {
|
1486
|
+
debug("This code block was skipped.");
|
1487
|
+
return [];
|
1488
|
+
}
|
1489
|
+
|
1490
|
+
// Resolve configuration again if the file content or extension was changed.
|
1491
|
+
if (configForRecursive && (text !== blockText || path.extname(blockName) !== originalExtname)) {
|
1492
|
+
debug("Resolving configuration again because the file content or extension was changed.");
|
1493
|
+
return this._verifyWithFlatConfigArray(
|
1494
|
+
blockText,
|
1495
|
+
configForRecursive,
|
1496
|
+
{ ...options, filename: blockName, physicalFilename }
|
1497
|
+
);
|
1498
|
+
}
|
1499
|
+
|
1500
|
+
// Does lint.
|
1501
|
+
return this._verifyWithFlatConfigArrayAndWithoutProcessors(
|
1502
|
+
blockText,
|
1503
|
+
config,
|
1504
|
+
{ ...options, filename: blockName, physicalFilename }
|
1505
|
+
);
|
1506
|
+
});
|
1507
|
+
|
1508
|
+
return postprocess(messageLists, filenameToExpose);
|
1509
|
+
}
|
1510
|
+
|
1511
|
+
/**
|
1512
|
+
* Same as linter.verify, except without support for processors.
|
1513
|
+
* @param {string|SourceCode} textOrSourceCode The text to parse or a SourceCode object.
|
1514
|
+
* @param {FlatConfig} providedConfig An ESLintConfig instance to configure everything.
|
1515
|
+
* @param {VerifyOptions} [providedOptions] The optional filename of the file being checked.
|
1516
|
+
* @throws {Error} If during rule execution.
|
1517
|
+
* @returns {LintMessage[]} The results as an array of messages or an empty array if no messages.
|
1518
|
+
*/
|
1519
|
+
_verifyWithFlatConfigArrayAndWithoutProcessors(textOrSourceCode, providedConfig, providedOptions) {
|
1520
|
+
const slots = internalSlotsMap.get(this);
|
1521
|
+
const config = providedConfig || {};
|
1522
|
+
const options = normalizeVerifyOptions(providedOptions, config);
|
1523
|
+
let text;
|
1524
|
+
|
1525
|
+
// evaluate arguments
|
1526
|
+
if (typeof textOrSourceCode === "string") {
|
1527
|
+
slots.lastSourceCode = null;
|
1528
|
+
text = textOrSourceCode;
|
1529
|
+
} else {
|
1530
|
+
slots.lastSourceCode = textOrSourceCode;
|
1531
|
+
text = textOrSourceCode.text;
|
1532
|
+
}
|
1533
|
+
|
1534
|
+
const languageOptions = config.languageOptions;
|
1535
|
+
|
1536
|
+
languageOptions.ecmaVersion = normalizeEcmaVersionForLanguageOptions(
|
1537
|
+
languageOptions.ecmaVersion
|
1538
|
+
);
|
1539
|
+
|
1540
|
+
// add configured globals and language globals
|
1541
|
+
const configuredGlobals = {
|
1542
|
+
...(getGlobalsForEcmaVersion(languageOptions.ecmaVersion)),
|
1543
|
+
...(languageOptions.sourceType === "commonjs" ? globals.commonjs : void 0),
|
1544
|
+
...languageOptions.globals
|
1545
|
+
};
|
1546
|
+
|
1547
|
+
// Espree expects this information to be passed in
|
1548
|
+
if (isEspree(languageOptions.parser)) {
|
1549
|
+
const parserOptions = languageOptions.parserOptions;
|
1550
|
+
|
1551
|
+
if (languageOptions.sourceType) {
|
1552
|
+
|
1553
|
+
parserOptions.sourceType = languageOptions.sourceType;
|
1554
|
+
|
1555
|
+
if (
|
1556
|
+
parserOptions.sourceType === "module" &&
|
1557
|
+
parserOptions.ecmaFeatures &&
|
1558
|
+
parserOptions.ecmaFeatures.globalReturn
|
1559
|
+
) {
|
1560
|
+
parserOptions.ecmaFeatures.globalReturn = false;
|
1561
|
+
}
|
1562
|
+
}
|
1563
|
+
}
|
1564
|
+
|
1565
|
+
const settings = config.settings || {};
|
1566
|
+
|
1567
|
+
if (!slots.lastSourceCode) {
|
1568
|
+
const parseResult = parse(
|
1569
|
+
text,
|
1570
|
+
languageOptions,
|
1571
|
+
options.filename
|
1572
|
+
);
|
1573
|
+
|
1574
|
+
if (!parseResult.success) {
|
1575
|
+
return [parseResult.error];
|
1576
|
+
}
|
1577
|
+
|
1578
|
+
slots.lastSourceCode = parseResult.sourceCode;
|
1579
|
+
} else {
|
1580
|
+
|
1581
|
+
/*
|
1582
|
+
* If the given source code object as the first argument does not have scopeManager, analyze the scope.
|
1583
|
+
* This is for backward compatibility (SourceCode is frozen so it cannot rebind).
|
1584
|
+
*/
|
1585
|
+
if (!slots.lastSourceCode.scopeManager) {
|
1586
|
+
slots.lastSourceCode = new SourceCode({
|
1587
|
+
text: slots.lastSourceCode.text,
|
1588
|
+
ast: slots.lastSourceCode.ast,
|
1589
|
+
parserServices: slots.lastSourceCode.parserServices,
|
1590
|
+
visitorKeys: slots.lastSourceCode.visitorKeys,
|
1591
|
+
scopeManager: analyzeScope(slots.lastSourceCode.ast, languageOptions)
|
1592
|
+
});
|
1593
|
+
}
|
1594
|
+
}
|
1595
|
+
|
1596
|
+
const sourceCode = slots.lastSourceCode;
|
1597
|
+
const commentDirectives = options.allowInlineConfig
|
1598
|
+
? getDirectiveComments(
|
1599
|
+
sourceCode.ast,
|
1600
|
+
ruleId => getRuleFromConfig(ruleId, config),
|
1601
|
+
options.warnInlineConfig
|
1602
|
+
)
|
1603
|
+
: { configuredRules: {}, enabledGlobals: {}, exportedVariables: {}, problems: [], disableDirectives: [] };
|
1604
|
+
|
1605
|
+
// augment global scope with declared global variables
|
1606
|
+
addDeclaredGlobals(
|
1607
|
+
sourceCode.scopeManager.scopes[0],
|
1608
|
+
configuredGlobals,
|
1609
|
+
{ exportedVariables: commentDirectives.exportedVariables, enabledGlobals: commentDirectives.enabledGlobals }
|
1610
|
+
);
|
1611
|
+
|
1612
|
+
const configuredRules = Object.assign({}, config.rules, commentDirectives.configuredRules);
|
1613
|
+
|
1614
|
+
let lintingProblems;
|
1615
|
+
|
1616
|
+
try {
|
1617
|
+
lintingProblems = runRules(
|
1618
|
+
sourceCode,
|
1619
|
+
configuredRules,
|
1620
|
+
ruleId => getRuleFromConfig(ruleId, config),
|
1621
|
+
void 0,
|
1622
|
+
languageOptions,
|
1623
|
+
settings,
|
1624
|
+
options.filename,
|
1625
|
+
options.disableFixes,
|
1626
|
+
slots.cwd,
|
1627
|
+
providedOptions.physicalFilename
|
1628
|
+
);
|
1629
|
+
} catch (err) {
|
1630
|
+
err.message += `\nOccurred while linting ${options.filename}`;
|
1631
|
+
debug("An error occurred while traversing");
|
1632
|
+
debug("Filename:", options.filename);
|
1633
|
+
if (err.currentNode) {
|
1634
|
+
const { line } = err.currentNode.loc.start;
|
1635
|
+
|
1636
|
+
debug("Line:", line);
|
1637
|
+
err.message += `:${line}`;
|
1638
|
+
}
|
1639
|
+
debug("Parser Options:", languageOptions.parserOptions);
|
1640
|
+
|
1641
|
+
// debug("Parser Path:", parserName);
|
1642
|
+
debug("Settings:", settings);
|
1643
|
+
|
1644
|
+
if (err.ruleId) {
|
1645
|
+
err.message += `\nRule: "${err.ruleId}"`;
|
1646
|
+
}
|
1647
|
+
|
1648
|
+
throw err;
|
1649
|
+
}
|
1650
|
+
|
1651
|
+
return applyDisableDirectives({
|
1652
|
+
directives: commentDirectives.disableDirectives,
|
1653
|
+
disableFixes: options.disableFixes,
|
1654
|
+
problems: lintingProblems
|
1655
|
+
.concat(commentDirectives.problems)
|
1656
|
+
.sort((problemA, problemB) => problemA.line - problemB.line || problemA.column - problemB.column),
|
1657
|
+
reportUnusedDisableDirectives: options.reportUnusedDisableDirectives
|
1658
|
+
});
|
1659
|
+
}
|
1660
|
+
|
1292
1661
|
/**
|
1293
1662
|
* Verify a given code with `ConfigArray`.
|
1294
1663
|
* @param {string|SourceCode} textOrSourceCode The source code.
|
@@ -1324,6 +1693,47 @@ class Linter {
|
|
1324
1693
|
return this._verifyWithoutProcessors(textOrSourceCode, config, options);
|
1325
1694
|
}
|
1326
1695
|
|
1696
|
+
/**
|
1697
|
+
* Verify a given code with a flat config.
|
1698
|
+
* @param {string|SourceCode} textOrSourceCode The source code.
|
1699
|
+
* @param {FlatConfigArray} configArray The config array.
|
1700
|
+
* @param {VerifyOptions&ProcessorOptions} options The options.
|
1701
|
+
* @param {boolean} [firstCall=false] Indicates if this is being called directly
|
1702
|
+
* from verify(). (TODO: Remove once eslintrc is removed.)
|
1703
|
+
* @returns {LintMessage[]} The found problems.
|
1704
|
+
*/
|
1705
|
+
_verifyWithFlatConfigArray(textOrSourceCode, configArray, options, firstCall = false) {
|
1706
|
+
debug("With flat config: %s", options.filename);
|
1707
|
+
|
1708
|
+
// we need a filename to match configs against
|
1709
|
+
const filename = options.filename || "<input>";
|
1710
|
+
|
1711
|
+
// Store the config array in order to get plugin envs and rules later.
|
1712
|
+
internalSlotsMap.get(this).lastConfigArray = configArray;
|
1713
|
+
const config = configArray.getConfig(filename);
|
1714
|
+
|
1715
|
+
// Verify.
|
1716
|
+
if (config.processor) {
|
1717
|
+
debug("Apply the processor: %o", config.processor);
|
1718
|
+
const { preprocess, postprocess, supportsAutofix } = config.processor;
|
1719
|
+
const disableFixes = options.disableFixes || !supportsAutofix;
|
1720
|
+
|
1721
|
+
return this._verifyWithFlatConfigArrayAndProcessor(
|
1722
|
+
textOrSourceCode,
|
1723
|
+
config,
|
1724
|
+
{ ...options, filename, disableFixes, postprocess, preprocess },
|
1725
|
+
configArray
|
1726
|
+
);
|
1727
|
+
}
|
1728
|
+
|
1729
|
+
// check for options-based processing
|
1730
|
+
if (firstCall && (options.preprocess || options.postprocess)) {
|
1731
|
+
return this._verifyWithFlatConfigArrayAndProcessor(textOrSourceCode, config, options);
|
1732
|
+
}
|
1733
|
+
|
1734
|
+
return this._verifyWithFlatConfigArrayAndWithoutProcessors(textOrSourceCode, config, options);
|
1735
|
+
}
|
1736
|
+
|
1327
1737
|
/**
|
1328
1738
|
* Verify with a processor.
|
1329
1739
|
* @param {string|SourceCode} textOrSourceCode The source code.
|
@@ -1397,6 +1807,7 @@ class Linter {
|
|
1397
1807
|
* @returns {void}
|
1398
1808
|
*/
|
1399
1809
|
defineRule(ruleId, ruleModule) {
|
1810
|
+
assertEslintrcConfig(this);
|
1400
1811
|
internalSlotsMap.get(this).ruleMap.define(ruleId, ruleModule);
|
1401
1812
|
}
|
1402
1813
|
|
@@ -1406,6 +1817,7 @@ class Linter {
|
|
1406
1817
|
* @returns {void}
|
1407
1818
|
*/
|
1408
1819
|
defineRules(rulesToDefine) {
|
1820
|
+
assertEslintrcConfig(this);
|
1409
1821
|
Object.getOwnPropertyNames(rulesToDefine).forEach(ruleId => {
|
1410
1822
|
this.defineRule(ruleId, rulesToDefine[ruleId]);
|
1411
1823
|
});
|
@@ -1416,6 +1828,7 @@ class Linter {
|
|
1416
1828
|
* @returns {Map<string, Rule>} All loaded rules
|
1417
1829
|
*/
|
1418
1830
|
getRules() {
|
1831
|
+
assertEslintrcConfig(this);
|
1419
1832
|
const { lastConfigArray, ruleMap } = internalSlotsMap.get(this);
|
1420
1833
|
|
1421
1834
|
return new Map(function *() {
|
@@ -1434,6 +1847,7 @@ class Linter {
|
|
1434
1847
|
* @returns {void}
|
1435
1848
|
*/
|
1436
1849
|
defineParser(parserId, parserModule) {
|
1850
|
+
assertEslintrcConfig(this);
|
1437
1851
|
internalSlotsMap.get(this).parserMap.set(parserId, parserModule);
|
1438
1852
|
}
|
1439
1853
|
|
@@ -1441,7 +1855,7 @@ class Linter {
|
|
1441
1855
|
* Performs multiple autofix passes over the text until as many fixes as possible
|
1442
1856
|
* have been applied.
|
1443
1857
|
* @param {string} text The source text to apply fixes to.
|
1444
|
-
* @param {ConfigData|ConfigArray} config The ESLint config object to use.
|
1858
|
+
* @param {ConfigData|ConfigArray|FlatConfigArray} config The ESLint config object to use.
|
1445
1859
|
* @param {VerifyOptions&ProcessorOptions&FixOptions} options The ESLint options object to use.
|
1446
1860
|
* @returns {{fixed:boolean,messages:LintMessage[],output:string}} The result of the fix operation as returned from the
|
1447
1861
|
* SourceCodeFixer.
|