eslint 8.2.0 → 8.5.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 +7 -11
- 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/code-path-analysis/code-path-analyzer.js +6 -1
- package/lib/linter/code-path-analysis/code-path.js +1 -1
- package/lib/linter/linter.js +457 -45
- 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 +3 -0
- package/lib/rules/block-spacing.js +11 -3
- package/lib/rules/brace-style.js +7 -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 +11 -1
- 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 +15 -6
- 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 +24 -0
- package/lib/rules/implicit-arrow-linebreak.js +1 -0
- package/lib/rules/indent-legacy.js +1 -0
- package/lib/rules/indent.js +22 -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 +2 -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 +55 -7
- 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 +3 -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 +11 -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 +3 -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 +2 -1
- 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 +27 -4
- package/lib/rules/no-invalid-regexp.js +1 -0
- package/lib/rules/no-invalid-this.js +5 -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 +9 -2
- 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 +3 -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 +1 -0
- 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 +7 -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 +33 -9
- 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 +6 -1
- package/lib/rules/operator-assignment.js +1 -0
- package/lib/rules/operator-linebreak.js +1 -0
- package/lib/rules/padded-blocks.js +9 -0
- package/lib/rules/padding-line-between-statements.js +3 -0
- package/lib/rules/prefer-arrow-callback.js +1 -0
- package/lib/rules/prefer-const.js +2 -1
- 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 +15 -2
- 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 +9 -2
- package/lib/rules/semi.js +19 -9
- 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/utils/ast-utils.js +15 -3
- package/lib/rules/valid-jsdoc.js +1 -0
- package/lib/rules/valid-typeof.js +1 -0
- package/lib/rules/vars-on-top.js +26 -12
- 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 +8 -8
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,7 +304,7 @@ 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)
|
307
|
+
if (ruleId === null || !!ruleMapper(ruleId)) {
|
272
308
|
result.directives.push({ parentComment, type, line: commentToken.loc.start.line, column: commentToken.loc.start.column + 1, ruleId });
|
273
309
|
} else {
|
274
310
|
result.directiveProblems.push(createLintingProblem({ ruleId, loc: commentToken.loc }));
|
@@ -400,7 +436,7 @@ function getDirectiveComments(filename, ast, ruleMapper, warnInlineConfig) {
|
|
400
436
|
const rule = ruleMapper(name);
|
401
437
|
const ruleValue = parseResult.config[name];
|
402
438
|
|
403
|
-
if (rule
|
439
|
+
if (!rule) {
|
404
440
|
problems.push(createLintingProblem({ ruleId: name, loc: comment.loc }));
|
405
441
|
return;
|
406
442
|
}
|
@@ -447,7 +483,8 @@ function getDirectiveComments(filename, ast, ruleMapper, warnInlineConfig) {
|
|
447
483
|
* @returns {number} normalized ECMAScript version
|
448
484
|
*/
|
449
485
|
function normalizeEcmaVersion(parser, ecmaVersion) {
|
450
|
-
|
486
|
+
|
487
|
+
if (isEspree(parser)) {
|
451
488
|
if (ecmaVersion === "latest") {
|
452
489
|
return espree.latestEcmaVersion;
|
453
490
|
}
|
@@ -460,6 +497,38 @@ function normalizeEcmaVersion(parser, ecmaVersion) {
|
|
460
497
|
return ecmaVersion >= 2015 ? ecmaVersion - 2009 : ecmaVersion;
|
461
498
|
}
|
462
499
|
|
500
|
+
/**
|
501
|
+
* Normalize ECMAScript version from the initial config into languageOptions (year)
|
502
|
+
* format.
|
503
|
+
* @param {any} [ecmaVersion] ECMAScript version from the initial config
|
504
|
+
* @returns {number} normalized ECMAScript version
|
505
|
+
*/
|
506
|
+
function normalizeEcmaVersionForLanguageOptions(ecmaVersion) {
|
507
|
+
|
508
|
+
switch (ecmaVersion) {
|
509
|
+
case 3:
|
510
|
+
return 3;
|
511
|
+
|
512
|
+
// void 0 = no ecmaVersion specified so use the default
|
513
|
+
case 5:
|
514
|
+
case void 0:
|
515
|
+
return 5;
|
516
|
+
|
517
|
+
default:
|
518
|
+
if (typeof ecmaVersion === "number") {
|
519
|
+
return ecmaVersion >= 2015 ? ecmaVersion : ecmaVersion + 2009;
|
520
|
+
}
|
521
|
+
}
|
522
|
+
|
523
|
+
/*
|
524
|
+
* We default to the latest supported ecmaVersion for everything else.
|
525
|
+
* Remember, this is for languageOptions.ecmaVersion, which sets the version
|
526
|
+
* that is used for a number of processes inside of ESLint. It's normally
|
527
|
+
* safe to assume people want the latest unless otherwise specified.
|
528
|
+
*/
|
529
|
+
return espree.latestEcmaVersion + 2009;
|
530
|
+
}
|
531
|
+
|
463
532
|
const eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)(?:\*\/|$)/gsu;
|
464
533
|
|
465
534
|
/**
|
@@ -511,7 +580,11 @@ function normalizeFilename(filename) {
|
|
511
580
|
* @returns {Required<VerifyOptions> & InternalOptions} Normalized options
|
512
581
|
*/
|
513
582
|
function normalizeVerifyOptions(providedOptions, config) {
|
514
|
-
|
583
|
+
|
584
|
+
const linterOptions = config.linterOptions || config;
|
585
|
+
|
586
|
+
// .noInlineConfig for eslintrc, .linterOptions.noInlineConfig for flat
|
587
|
+
const disableInlineConfig = linterOptions.noInlineConfig === true;
|
515
588
|
const ignoreInlineConfig = providedOptions.allowInlineConfig === false;
|
516
589
|
const configNameOfNoInlineConfig = config.configNameOfNoInlineConfig
|
517
590
|
? ` (${config.configNameOfNoInlineConfig})`
|
@@ -523,7 +596,9 @@ function normalizeVerifyOptions(providedOptions, config) {
|
|
523
596
|
reportUnusedDisableDirectives = reportUnusedDisableDirectives ? "error" : "off";
|
524
597
|
}
|
525
598
|
if (typeof reportUnusedDisableDirectives !== "string") {
|
526
|
-
reportUnusedDisableDirectives =
|
599
|
+
reportUnusedDisableDirectives =
|
600
|
+
linterOptions.reportUnusedDisableDirectives
|
601
|
+
? "warn" : "off";
|
527
602
|
}
|
528
603
|
|
529
604
|
return {
|
@@ -566,6 +641,30 @@ function resolveParserOptions(parser, providedOptions, enabledEnvironments) {
|
|
566
641
|
return mergedParserOptions;
|
567
642
|
}
|
568
643
|
|
644
|
+
/**
|
645
|
+
* Converts parserOptions to languageOptions for backwards compatibility with eslintrc.
|
646
|
+
* @param {ConfigData} config Config object.
|
647
|
+
* @param {Object} config.globals Global variable definitions.
|
648
|
+
* @param {Parser} config.parser The parser to use.
|
649
|
+
* @param {ParserOptions} config.parserOptions The parserOptions to use.
|
650
|
+
* @returns {LanguageOptions} The languageOptions equivalent.
|
651
|
+
*/
|
652
|
+
function createLanguageOptions({ globals: configuredGlobals, parser, parserOptions }) {
|
653
|
+
|
654
|
+
const {
|
655
|
+
ecmaVersion,
|
656
|
+
sourceType
|
657
|
+
} = parserOptions;
|
658
|
+
|
659
|
+
return {
|
660
|
+
globals: configuredGlobals,
|
661
|
+
ecmaVersion: normalizeEcmaVersionForLanguageOptions(ecmaVersion),
|
662
|
+
sourceType,
|
663
|
+
parser,
|
664
|
+
parserOptions
|
665
|
+
};
|
666
|
+
}
|
667
|
+
|
569
668
|
/**
|
570
669
|
* Combines the provided globals object with the globals from environments
|
571
670
|
* @param {Record<string, GlobalConf>} providedGlobals The 'globals' key in a config
|
@@ -614,20 +713,21 @@ function getRuleOptions(ruleConfig) {
|
|
614
713
|
/**
|
615
714
|
* Analyze scope of the given AST.
|
616
715
|
* @param {ASTNode} ast The `Program` node to analyze.
|
617
|
-
* @param {
|
716
|
+
* @param {LanguageOptions} languageOptions The parser options.
|
618
717
|
* @param {Record<string, string[]>} visitorKeys The visitor keys.
|
619
718
|
* @returns {ScopeManager} The analysis result.
|
620
719
|
*/
|
621
|
-
function analyzeScope(ast,
|
720
|
+
function analyzeScope(ast, languageOptions, visitorKeys) {
|
721
|
+
const parserOptions = languageOptions.parserOptions;
|
622
722
|
const ecmaFeatures = parserOptions.ecmaFeatures || {};
|
623
|
-
const ecmaVersion =
|
723
|
+
const ecmaVersion = languageOptions.ecmaVersion || DEFAULT_ECMA_VERSION;
|
624
724
|
|
625
725
|
return eslintScope.analyze(ast, {
|
626
726
|
ignoreEval: true,
|
627
727
|
nodejsScope: ecmaFeatures.globalReturn,
|
628
728
|
impliedStrict: ecmaFeatures.impliedStrict,
|
629
|
-
ecmaVersion,
|
630
|
-
sourceType:
|
729
|
+
ecmaVersion: typeof ecmaVersion === "number" ? ecmaVersion : 6,
|
730
|
+
sourceType: languageOptions.sourceType || "script",
|
631
731
|
childVisitorKeys: visitorKeys || evk.KEYS,
|
632
732
|
fallback: Traverser.getKeys
|
633
733
|
});
|
@@ -638,25 +738,29 @@ function analyzeScope(ast, parserOptions, visitorKeys) {
|
|
638
738
|
* optimization of functions, so it's best to keep the try-catch as isolated
|
639
739
|
* as possible
|
640
740
|
* @param {string} text The text to parse.
|
641
|
-
* @param {
|
642
|
-
* @param {ParserOptions} providedParserOptions Options to pass to the parser
|
741
|
+
* @param {LanguageOptions} languageOptions Options to pass to the parser
|
643
742
|
* @param {string} filePath The path to the file being parsed.
|
644
743
|
* @returns {{success: false, error: Problem}|{success: true, sourceCode: SourceCode}}
|
645
744
|
* An object containing the AST and parser services if parsing was successful, or the error if parsing failed
|
646
745
|
* @private
|
647
746
|
*/
|
648
|
-
function parse(text,
|
747
|
+
function parse(text, languageOptions, filePath) {
|
649
748
|
const textToParse = stripUnicodeBOM(text).replace(astUtils.shebangPattern, (match, captured) => `//${captured}`);
|
650
|
-
const
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
749
|
+
const { ecmaVersion, sourceType, parser } = languageOptions;
|
750
|
+
const parserOptions = Object.assign(
|
751
|
+
{ ecmaVersion, sourceType },
|
752
|
+
languageOptions.parserOptions,
|
753
|
+
{
|
754
|
+
loc: true,
|
755
|
+
range: true,
|
756
|
+
raw: true,
|
757
|
+
tokens: true,
|
758
|
+
comment: true,
|
759
|
+
eslintVisitorKeys: true,
|
760
|
+
eslintScopeManager: true,
|
761
|
+
filePath
|
762
|
+
}
|
763
|
+
);
|
660
764
|
|
661
765
|
/*
|
662
766
|
* Check for parsing errors first. If there's a parsing error, nothing
|
@@ -671,7 +775,7 @@ function parse(text, parser, providedParserOptions, filePath) {
|
|
671
775
|
const ast = parseResult.ast;
|
672
776
|
const parserServices = parseResult.services || {};
|
673
777
|
const visitorKeys = parseResult.visitorKeys || evk.KEYS;
|
674
|
-
const scopeManager = parseResult.scopeManager || analyzeScope(ast,
|
778
|
+
const scopeManager = parseResult.scopeManager || analyzeScope(ast, languageOptions, visitorKeys);
|
675
779
|
|
676
780
|
return {
|
677
781
|
success: true,
|
@@ -740,13 +844,17 @@ function getScope(scopeManager, currentNode) {
|
|
740
844
|
* Marks a variable as used in the current scope
|
741
845
|
* @param {ScopeManager} scopeManager The scope manager for this AST. The scope may be mutated by this function.
|
742
846
|
* @param {ASTNode} currentNode The node currently being traversed
|
743
|
-
* @param {
|
847
|
+
* @param {LanguageOptions} languageOptions The options used to parse this text
|
744
848
|
* @param {string} name The name of the variable that should be marked as used.
|
745
849
|
* @returns {boolean} True if the variable was found and marked as used, false if not.
|
746
850
|
*/
|
747
|
-
function markVariableAsUsed(scopeManager, currentNode,
|
748
|
-
const
|
749
|
-
const
|
851
|
+
function markVariableAsUsed(scopeManager, currentNode, languageOptions, name) {
|
852
|
+
const parserOptions = languageOptions.parserOptions;
|
853
|
+
const sourceType = languageOptions.sourceType;
|
854
|
+
const hasGlobalReturn =
|
855
|
+
(parserOptions.ecmaFeatures && parserOptions.ecmaFeatures.globalReturn) ||
|
856
|
+
sourceType === "commonjs";
|
857
|
+
const specialScope = hasGlobalReturn || sourceType === "module";
|
750
858
|
const currentScope = getScope(scopeManager, currentNode);
|
751
859
|
|
752
860
|
// Special Node.js scope means we need to start one level deeper
|
@@ -837,8 +945,8 @@ const BASE_TRAVERSAL_CONTEXT = Object.freeze(
|
|
837
945
|
* @param {SourceCode} sourceCode A SourceCode object for the given text
|
838
946
|
* @param {Object} configuredRules The rules configuration
|
839
947
|
* @param {function(string): Rule} ruleMapper A mapper function from rule names to rules
|
840
|
-
* @param {
|
841
|
-
* @param {
|
948
|
+
* @param {string | undefined} parserName The name of the parser in the config
|
949
|
+
* @param {LanguageOptions} languageOptions The options for parsing the code.
|
842
950
|
* @param {Object} settings The settings that were enabled in the config
|
843
951
|
* @param {string} filename The reported filename of the code
|
844
952
|
* @param {boolean} disableFixes If true, it doesn't make `fix` properties.
|
@@ -846,7 +954,7 @@ const BASE_TRAVERSAL_CONTEXT = Object.freeze(
|
|
846
954
|
* @param {string} physicalFilename The full path of the file on disk without any code block information
|
847
955
|
* @returns {Problem[]} An array of reported problems
|
848
956
|
*/
|
849
|
-
function runRules(sourceCode, configuredRules, ruleMapper,
|
957
|
+
function runRules(sourceCode, configuredRules, ruleMapper, parserName, languageOptions, settings, filename, disableFixes, cwd, physicalFilename) {
|
850
958
|
const emitter = createEmitter();
|
851
959
|
const nodeQueue = [];
|
852
960
|
let currentNode = sourceCode.ast;
|
@@ -878,16 +986,18 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parser
|
|
878
986
|
getPhysicalFilename: () => physicalFilename || filename,
|
879
987
|
getScope: () => getScope(sourceCode.scopeManager, currentNode),
|
880
988
|
getSourceCode: () => sourceCode,
|
881
|
-
markVariableAsUsed: name => markVariableAsUsed(sourceCode.scopeManager, currentNode,
|
882
|
-
parserOptions
|
989
|
+
markVariableAsUsed: name => markVariableAsUsed(sourceCode.scopeManager, currentNode, languageOptions, name),
|
990
|
+
parserOptions: {
|
991
|
+
...languageOptions.parserOptions
|
992
|
+
},
|
883
993
|
parserPath: parserName,
|
994
|
+
languageOptions,
|
884
995
|
parserServices: sourceCode.parserServices,
|
885
996
|
settings
|
886
997
|
}
|
887
998
|
)
|
888
999
|
);
|
889
1000
|
|
890
|
-
|
891
1001
|
const lintingProblems = [];
|
892
1002
|
|
893
1003
|
Object.keys(configuredRules).forEach(ruleId => {
|
@@ -900,7 +1010,7 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parser
|
|
900
1010
|
|
901
1011
|
const rule = ruleMapper(ruleId);
|
902
1012
|
|
903
|
-
if (rule
|
1013
|
+
if (!rule) {
|
904
1014
|
lintingProblems.push(createLintingProblem({ ruleId }));
|
905
1015
|
return;
|
906
1016
|
}
|
@@ -1074,13 +1184,28 @@ function normalizeCwd(cwd) {
|
|
1074
1184
|
*/
|
1075
1185
|
const internalSlotsMap = new WeakMap();
|
1076
1186
|
|
1187
|
+
/**
|
1188
|
+
* Throws an error when the given linter is in flat config mode.
|
1189
|
+
* @param {Linter} linter The linter to check.
|
1190
|
+
* @returns {void}
|
1191
|
+
* @throws {Error} If the linter is in flat config mode.
|
1192
|
+
*/
|
1193
|
+
function assertEslintrcConfig(linter) {
|
1194
|
+
const { configType } = internalSlotsMap.get(linter);
|
1195
|
+
|
1196
|
+
if (configType === "flat") {
|
1197
|
+
throw new Error("This method cannot be used with flat config. Add your entries directly into the config array.");
|
1198
|
+
}
|
1199
|
+
}
|
1200
|
+
|
1201
|
+
|
1077
1202
|
//------------------------------------------------------------------------------
|
1078
1203
|
// Public Interface
|
1079
1204
|
//------------------------------------------------------------------------------
|
1080
1205
|
|
1081
1206
|
/**
|
1082
1207
|
* Object that is responsible for verifying JavaScript text
|
1083
|
-
* @name
|
1208
|
+
* @name Linter
|
1084
1209
|
*/
|
1085
1210
|
class Linter {
|
1086
1211
|
|
@@ -1088,12 +1213,14 @@ class Linter {
|
|
1088
1213
|
* Initialize the Linter.
|
1089
1214
|
* @param {Object} [config] the config object
|
1090
1215
|
* @param {string} [config.cwd] path to a directory that should be considered as the current working directory, can be undefined.
|
1216
|
+
* @param {"flat"|"eslintrc"} [config.configType="eslintrc"] the type of config used.
|
1091
1217
|
*/
|
1092
|
-
constructor({ cwd } = {}) {
|
1218
|
+
constructor({ cwd, configType } = {}) {
|
1093
1219
|
internalSlotsMap.set(this, {
|
1094
1220
|
cwd: normalizeCwd(cwd),
|
1095
1221
|
lastConfigArray: null,
|
1096
1222
|
lastSourceCode: null,
|
1223
|
+
configType, // TODO: Remove after flat config conversion
|
1097
1224
|
parserMap: new Map([["espree", espree]]),
|
1098
1225
|
ruleMap: new Rules()
|
1099
1226
|
});
|
@@ -1168,12 +1295,16 @@ class Linter {
|
|
1168
1295
|
const parserOptions = resolveParserOptions(parser, config.parserOptions || {}, enabledEnvs);
|
1169
1296
|
const configuredGlobals = resolveGlobals(config.globals || {}, enabledEnvs);
|
1170
1297
|
const settings = config.settings || {};
|
1298
|
+
const languageOptions = createLanguageOptions({
|
1299
|
+
globals: config.globals,
|
1300
|
+
parser,
|
1301
|
+
parserOptions
|
1302
|
+
});
|
1171
1303
|
|
1172
1304
|
if (!slots.lastSourceCode) {
|
1173
1305
|
const parseResult = parse(
|
1174
1306
|
text,
|
1175
|
-
|
1176
|
-
parserOptions,
|
1307
|
+
languageOptions,
|
1177
1308
|
options.filename
|
1178
1309
|
);
|
1179
1310
|
|
@@ -1194,7 +1325,7 @@ class Linter {
|
|
1194
1325
|
ast: slots.lastSourceCode.ast,
|
1195
1326
|
parserServices: slots.lastSourceCode.parserServices,
|
1196
1327
|
visitorKeys: slots.lastSourceCode.visitorKeys,
|
1197
|
-
scopeManager: analyzeScope(slots.lastSourceCode.ast,
|
1328
|
+
scopeManager: analyzeScope(slots.lastSourceCode.ast, languageOptions)
|
1198
1329
|
});
|
1199
1330
|
}
|
1200
1331
|
}
|
@@ -1220,8 +1351,8 @@ class Linter {
|
|
1220
1351
|
sourceCode,
|
1221
1352
|
configuredRules,
|
1222
1353
|
ruleId => getRule(slots, ruleId),
|
1223
|
-
parserOptions,
|
1224
1354
|
parserName,
|
1355
|
+
languageOptions,
|
1225
1356
|
settings,
|
1226
1357
|
options.filename,
|
1227
1358
|
options.disableFixes,
|
@@ -1270,15 +1401,43 @@ class Linter {
|
|
1270
1401
|
*/
|
1271
1402
|
verify(textOrSourceCode, config, filenameOrOptions) {
|
1272
1403
|
debug("Verify");
|
1404
|
+
|
1405
|
+
const { configType } = internalSlotsMap.get(this);
|
1406
|
+
|
1273
1407
|
const options = typeof filenameOrOptions === "string"
|
1274
1408
|
? { filename: filenameOrOptions }
|
1275
1409
|
: filenameOrOptions || {};
|
1276
1410
|
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1411
|
+
if (config) {
|
1412
|
+
if (configType === "flat") {
|
1413
|
+
|
1414
|
+
/*
|
1415
|
+
* Because of how Webpack packages up the files, we can't
|
1416
|
+
* compare directly to `FlatConfigArray` using `instanceof`
|
1417
|
+
* because it's not the same `FlatConfigArray` as in the tests.
|
1418
|
+
* So, we work around it by assuming an array is, in fact, a
|
1419
|
+
* `FlatConfigArray` if it has a `getConfig()` method.
|
1420
|
+
*/
|
1421
|
+
let configArray = config;
|
1422
|
+
|
1423
|
+
if (!Array.isArray(config) || typeof config.getConfig !== "function") {
|
1424
|
+
configArray = new FlatConfigArray(config);
|
1425
|
+
configArray.normalizeSync();
|
1426
|
+
}
|
1427
|
+
|
1428
|
+
return this._verifyWithFlatConfigArray(textOrSourceCode, configArray, options, true);
|
1429
|
+
}
|
1430
|
+
|
1431
|
+
if (typeof config.extractConfig === "function") {
|
1432
|
+
return this._verifyWithConfigArray(textOrSourceCode, config, options);
|
1433
|
+
}
|
1280
1434
|
}
|
1281
1435
|
|
1436
|
+
/*
|
1437
|
+
* If we get to here, it means `config` is just an object rather
|
1438
|
+
* than a config array so we can go right into linting.
|
1439
|
+
*/
|
1440
|
+
|
1282
1441
|
/*
|
1283
1442
|
* `Linter` doesn't support `overrides` property in configuration.
|
1284
1443
|
* So we cannot apply multiple processors.
|
@@ -1289,6 +1448,214 @@ class Linter {
|
|
1289
1448
|
return this._verifyWithoutProcessors(textOrSourceCode, config, options);
|
1290
1449
|
}
|
1291
1450
|
|
1451
|
+
/**
|
1452
|
+
* Verify with a processor.
|
1453
|
+
* @param {string|SourceCode} textOrSourceCode The source code.
|
1454
|
+
* @param {FlatConfig} config The config array.
|
1455
|
+
* @param {VerifyOptions&ProcessorOptions} options The options.
|
1456
|
+
* @param {FlatConfigArray} [configForRecursive] The `ConfigArray` object to apply multiple processors recursively.
|
1457
|
+
* @returns {LintMessage[]} The found problems.
|
1458
|
+
*/
|
1459
|
+
_verifyWithFlatConfigArrayAndProcessor(textOrSourceCode, config, options, configForRecursive) {
|
1460
|
+
const filename = options.filename || "<input>";
|
1461
|
+
const filenameToExpose = normalizeFilename(filename);
|
1462
|
+
const physicalFilename = options.physicalFilename || filenameToExpose;
|
1463
|
+
const text = ensureText(textOrSourceCode);
|
1464
|
+
const preprocess = options.preprocess || (rawText => [rawText]);
|
1465
|
+
const postprocess = options.postprocess || (messagesList => messagesList.flat());
|
1466
|
+
const filterCodeBlock =
|
1467
|
+
options.filterCodeBlock ||
|
1468
|
+
(blockFilename => blockFilename.endsWith(".js"));
|
1469
|
+
const originalExtname = path.extname(filename);
|
1470
|
+
const messageLists = preprocess(text, filenameToExpose).map((block, i) => {
|
1471
|
+
debug("A code block was found: %o", block.filename || "(unnamed)");
|
1472
|
+
|
1473
|
+
// Keep the legacy behavior.
|
1474
|
+
if (typeof block === "string") {
|
1475
|
+
return this._verifyWithFlatConfigArrayAndWithoutProcessors(block, config, options);
|
1476
|
+
}
|
1477
|
+
|
1478
|
+
const blockText = block.text;
|
1479
|
+
const blockName = path.join(filename, `${i}_${block.filename}`);
|
1480
|
+
|
1481
|
+
// Skip this block if filtered.
|
1482
|
+
if (!filterCodeBlock(blockName, blockText)) {
|
1483
|
+
debug("This code block was skipped.");
|
1484
|
+
return [];
|
1485
|
+
}
|
1486
|
+
|
1487
|
+
// Resolve configuration again if the file content or extension was changed.
|
1488
|
+
if (configForRecursive && (text !== blockText || path.extname(blockName) !== originalExtname)) {
|
1489
|
+
debug("Resolving configuration again because the file content or extension was changed.");
|
1490
|
+
return this._verifyWithFlatConfigArray(
|
1491
|
+
blockText,
|
1492
|
+
configForRecursive,
|
1493
|
+
{ ...options, filename: blockName, physicalFilename }
|
1494
|
+
);
|
1495
|
+
}
|
1496
|
+
|
1497
|
+
// Does lint.
|
1498
|
+
return this._verifyWithFlatConfigArrayAndWithoutProcessors(
|
1499
|
+
blockText,
|
1500
|
+
config,
|
1501
|
+
{ ...options, filename: blockName, physicalFilename }
|
1502
|
+
);
|
1503
|
+
});
|
1504
|
+
|
1505
|
+
return postprocess(messageLists, filenameToExpose);
|
1506
|
+
}
|
1507
|
+
|
1508
|
+
/**
|
1509
|
+
* Same as linter.verify, except without support for processors.
|
1510
|
+
* @param {string|SourceCode} textOrSourceCode The text to parse or a SourceCode object.
|
1511
|
+
* @param {FlatConfig} providedConfig An ESLintConfig instance to configure everything.
|
1512
|
+
* @param {VerifyOptions} [providedOptions] The optional filename of the file being checked.
|
1513
|
+
* @throws {Error} If during rule execution.
|
1514
|
+
* @returns {LintMessage[]} The results as an array of messages or an empty array if no messages.
|
1515
|
+
*/
|
1516
|
+
_verifyWithFlatConfigArrayAndWithoutProcessors(textOrSourceCode, providedConfig, providedOptions) {
|
1517
|
+
const slots = internalSlotsMap.get(this);
|
1518
|
+
const config = providedConfig || {};
|
1519
|
+
const options = normalizeVerifyOptions(providedOptions, config);
|
1520
|
+
let text;
|
1521
|
+
|
1522
|
+
// evaluate arguments
|
1523
|
+
if (typeof textOrSourceCode === "string") {
|
1524
|
+
slots.lastSourceCode = null;
|
1525
|
+
text = textOrSourceCode;
|
1526
|
+
} else {
|
1527
|
+
slots.lastSourceCode = textOrSourceCode;
|
1528
|
+
text = textOrSourceCode.text;
|
1529
|
+
}
|
1530
|
+
|
1531
|
+
const languageOptions = config.languageOptions;
|
1532
|
+
|
1533
|
+
languageOptions.ecmaVersion = normalizeEcmaVersionForLanguageOptions(
|
1534
|
+
languageOptions.ecmaVersion
|
1535
|
+
);
|
1536
|
+
|
1537
|
+
// add configured globals and language globals
|
1538
|
+
const configuredGlobals = {
|
1539
|
+
...(getGlobalsForEcmaVersion(languageOptions.ecmaVersion)),
|
1540
|
+
...(languageOptions.sourceType === "commonjs" ? globals.commonjs : void 0),
|
1541
|
+
...languageOptions.globals
|
1542
|
+
};
|
1543
|
+
|
1544
|
+
// Espree expects this information to be passed in
|
1545
|
+
if (isEspree(languageOptions.parser)) {
|
1546
|
+
const parserOptions = languageOptions.parserOptions;
|
1547
|
+
|
1548
|
+
if (languageOptions.sourceType) {
|
1549
|
+
|
1550
|
+
parserOptions.sourceType = languageOptions.sourceType;
|
1551
|
+
|
1552
|
+
if (
|
1553
|
+
parserOptions.sourceType === "module" &&
|
1554
|
+
parserOptions.ecmaFeatures &&
|
1555
|
+
parserOptions.ecmaFeatures.globalReturn
|
1556
|
+
) {
|
1557
|
+
parserOptions.ecmaFeatures.globalReturn = false;
|
1558
|
+
}
|
1559
|
+
}
|
1560
|
+
}
|
1561
|
+
|
1562
|
+
const settings = config.settings || {};
|
1563
|
+
|
1564
|
+
if (!slots.lastSourceCode) {
|
1565
|
+
const parseResult = parse(
|
1566
|
+
text,
|
1567
|
+
languageOptions,
|
1568
|
+
options.filename
|
1569
|
+
);
|
1570
|
+
|
1571
|
+
if (!parseResult.success) {
|
1572
|
+
return [parseResult.error];
|
1573
|
+
}
|
1574
|
+
|
1575
|
+
slots.lastSourceCode = parseResult.sourceCode;
|
1576
|
+
} else {
|
1577
|
+
|
1578
|
+
/*
|
1579
|
+
* If the given source code object as the first argument does not have scopeManager, analyze the scope.
|
1580
|
+
* This is for backward compatibility (SourceCode is frozen so it cannot rebind).
|
1581
|
+
*/
|
1582
|
+
if (!slots.lastSourceCode.scopeManager) {
|
1583
|
+
slots.lastSourceCode = new SourceCode({
|
1584
|
+
text: slots.lastSourceCode.text,
|
1585
|
+
ast: slots.lastSourceCode.ast,
|
1586
|
+
parserServices: slots.lastSourceCode.parserServices,
|
1587
|
+
visitorKeys: slots.lastSourceCode.visitorKeys,
|
1588
|
+
scopeManager: analyzeScope(slots.lastSourceCode.ast, languageOptions)
|
1589
|
+
});
|
1590
|
+
}
|
1591
|
+
}
|
1592
|
+
|
1593
|
+
const sourceCode = slots.lastSourceCode;
|
1594
|
+
const commentDirectives = options.allowInlineConfig
|
1595
|
+
? getDirectiveComments(
|
1596
|
+
options.filename,
|
1597
|
+
sourceCode.ast,
|
1598
|
+
ruleId => getRuleFromConfig(ruleId, config),
|
1599
|
+
options.warnInlineConfig
|
1600
|
+
)
|
1601
|
+
: { configuredRules: {}, enabledGlobals: {}, exportedVariables: {}, problems: [], disableDirectives: [] };
|
1602
|
+
|
1603
|
+
// augment global scope with declared global variables
|
1604
|
+
addDeclaredGlobals(
|
1605
|
+
sourceCode.scopeManager.scopes[0],
|
1606
|
+
configuredGlobals,
|
1607
|
+
{ exportedVariables: commentDirectives.exportedVariables, enabledGlobals: commentDirectives.enabledGlobals }
|
1608
|
+
);
|
1609
|
+
|
1610
|
+
const configuredRules = Object.assign({}, config.rules, commentDirectives.configuredRules);
|
1611
|
+
|
1612
|
+
let lintingProblems;
|
1613
|
+
|
1614
|
+
try {
|
1615
|
+
lintingProblems = runRules(
|
1616
|
+
sourceCode,
|
1617
|
+
configuredRules,
|
1618
|
+
ruleId => getRuleFromConfig(ruleId, config),
|
1619
|
+
void 0,
|
1620
|
+
languageOptions,
|
1621
|
+
settings,
|
1622
|
+
options.filename,
|
1623
|
+
options.disableFixes,
|
1624
|
+
slots.cwd,
|
1625
|
+
providedOptions.physicalFilename
|
1626
|
+
);
|
1627
|
+
} catch (err) {
|
1628
|
+
err.message += `\nOccurred while linting ${options.filename}`;
|
1629
|
+
debug("An error occurred while traversing");
|
1630
|
+
debug("Filename:", options.filename);
|
1631
|
+
if (err.currentNode) {
|
1632
|
+
const { line } = err.currentNode.loc.start;
|
1633
|
+
|
1634
|
+
debug("Line:", line);
|
1635
|
+
err.message += `:${line}`;
|
1636
|
+
}
|
1637
|
+
debug("Parser Options:", languageOptions.parserOptions);
|
1638
|
+
|
1639
|
+
// debug("Parser Path:", parserName);
|
1640
|
+
debug("Settings:", settings);
|
1641
|
+
|
1642
|
+
if (err.ruleId) {
|
1643
|
+
err.message += `\nRule: "${err.ruleId}"`;
|
1644
|
+
}
|
1645
|
+
|
1646
|
+
throw err;
|
1647
|
+
}
|
1648
|
+
|
1649
|
+
return applyDisableDirectives({
|
1650
|
+
directives: commentDirectives.disableDirectives,
|
1651
|
+
disableFixes: options.disableFixes,
|
1652
|
+
problems: lintingProblems
|
1653
|
+
.concat(commentDirectives.problems)
|
1654
|
+
.sort((problemA, problemB) => problemA.line - problemB.line || problemA.column - problemB.column),
|
1655
|
+
reportUnusedDisableDirectives: options.reportUnusedDisableDirectives
|
1656
|
+
});
|
1657
|
+
}
|
1658
|
+
|
1292
1659
|
/**
|
1293
1660
|
* Verify a given code with `ConfigArray`.
|
1294
1661
|
* @param {string|SourceCode} textOrSourceCode The source code.
|
@@ -1324,6 +1691,47 @@ class Linter {
|
|
1324
1691
|
return this._verifyWithoutProcessors(textOrSourceCode, config, options);
|
1325
1692
|
}
|
1326
1693
|
|
1694
|
+
/**
|
1695
|
+
* Verify a given code with a flat config.
|
1696
|
+
* @param {string|SourceCode} textOrSourceCode The source code.
|
1697
|
+
* @param {FlatConfigArray} configArray The config array.
|
1698
|
+
* @param {VerifyOptions&ProcessorOptions} options The options.
|
1699
|
+
* @param {boolean} [firstCall=false] Indicates if this is being called directly
|
1700
|
+
* from verify(). (TODO: Remove once eslintrc is removed.)
|
1701
|
+
* @returns {LintMessage[]} The found problems.
|
1702
|
+
*/
|
1703
|
+
_verifyWithFlatConfigArray(textOrSourceCode, configArray, options, firstCall = false) {
|
1704
|
+
debug("With flat config: %s", options.filename);
|
1705
|
+
|
1706
|
+
// we need a filename to match configs against
|
1707
|
+
const filename = options.filename || "<input>";
|
1708
|
+
|
1709
|
+
// Store the config array in order to get plugin envs and rules later.
|
1710
|
+
internalSlotsMap.get(this).lastConfigArray = configArray;
|
1711
|
+
const config = configArray.getConfig(filename);
|
1712
|
+
|
1713
|
+
// Verify.
|
1714
|
+
if (config.processor) {
|
1715
|
+
debug("Apply the processor: %o", config.processor);
|
1716
|
+
const { preprocess, postprocess, supportsAutofix } = config.processor;
|
1717
|
+
const disableFixes = options.disableFixes || !supportsAutofix;
|
1718
|
+
|
1719
|
+
return this._verifyWithFlatConfigArrayAndProcessor(
|
1720
|
+
textOrSourceCode,
|
1721
|
+
config,
|
1722
|
+
{ ...options, filename, disableFixes, postprocess, preprocess },
|
1723
|
+
configArray
|
1724
|
+
);
|
1725
|
+
}
|
1726
|
+
|
1727
|
+
// check for options-based processing
|
1728
|
+
if (firstCall && (options.preprocess || options.postprocess)) {
|
1729
|
+
return this._verifyWithFlatConfigArrayAndProcessor(textOrSourceCode, config, options);
|
1730
|
+
}
|
1731
|
+
|
1732
|
+
return this._verifyWithFlatConfigArrayAndWithoutProcessors(textOrSourceCode, config, options);
|
1733
|
+
}
|
1734
|
+
|
1327
1735
|
/**
|
1328
1736
|
* Verify with a processor.
|
1329
1737
|
* @param {string|SourceCode} textOrSourceCode The source code.
|
@@ -1397,6 +1805,7 @@ class Linter {
|
|
1397
1805
|
* @returns {void}
|
1398
1806
|
*/
|
1399
1807
|
defineRule(ruleId, ruleModule) {
|
1808
|
+
assertEslintrcConfig(this);
|
1400
1809
|
internalSlotsMap.get(this).ruleMap.define(ruleId, ruleModule);
|
1401
1810
|
}
|
1402
1811
|
|
@@ -1406,6 +1815,7 @@ class Linter {
|
|
1406
1815
|
* @returns {void}
|
1407
1816
|
*/
|
1408
1817
|
defineRules(rulesToDefine) {
|
1818
|
+
assertEslintrcConfig(this);
|
1409
1819
|
Object.getOwnPropertyNames(rulesToDefine).forEach(ruleId => {
|
1410
1820
|
this.defineRule(ruleId, rulesToDefine[ruleId]);
|
1411
1821
|
});
|
@@ -1416,6 +1826,7 @@ class Linter {
|
|
1416
1826
|
* @returns {Map<string, Rule>} All loaded rules
|
1417
1827
|
*/
|
1418
1828
|
getRules() {
|
1829
|
+
assertEslintrcConfig(this);
|
1419
1830
|
const { lastConfigArray, ruleMap } = internalSlotsMap.get(this);
|
1420
1831
|
|
1421
1832
|
return new Map(function *() {
|
@@ -1434,6 +1845,7 @@ class Linter {
|
|
1434
1845
|
* @returns {void}
|
1435
1846
|
*/
|
1436
1847
|
defineParser(parserId, parserModule) {
|
1848
|
+
assertEslintrcConfig(this);
|
1437
1849
|
internalSlotsMap.get(this).parserMap.set(parserId, parserModule);
|
1438
1850
|
}
|
1439
1851
|
|
@@ -1441,7 +1853,7 @@ class Linter {
|
|
1441
1853
|
* Performs multiple autofix passes over the text until as many fixes as possible
|
1442
1854
|
* have been applied.
|
1443
1855
|
* @param {string} text The source text to apply fixes to.
|
1444
|
-
* @param {ConfigData|ConfigArray} config The ESLint config object to use.
|
1856
|
+
* @param {ConfigData|ConfigArray|FlatConfigArray} config The ESLint config object to use.
|
1445
1857
|
* @param {VerifyOptions&ProcessorOptions&FixOptions} options The ESLint options object to use.
|
1446
1858
|
* @returns {{fixed:boolean,messages:LintMessage[],output:string}} The result of the fix operation as returned from the
|
1447
1859
|
* SourceCodeFixer.
|