eslint 9.26.0 → 9.28.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 -2
- package/bin/eslint.js +7 -11
- package/conf/rule-type-list.json +2 -1
- package/lib/cli-engine/cli-engine.js +7 -7
- package/lib/cli.js +19 -16
- package/lib/config/config-loader.js +42 -39
- package/lib/config/config.js +362 -16
- package/lib/eslint/eslint-helpers.js +3 -1
- package/lib/eslint/eslint.js +31 -13
- package/lib/eslint/legacy-eslint.js +6 -6
- package/lib/languages/js/source-code/source-code.js +40 -6
- package/lib/linter/apply-disable-directives.js +1 -1
- package/lib/linter/file-context.js +11 -0
- package/lib/linter/linter.js +102 -140
- package/lib/linter/report-translator.js +2 -1
- package/lib/linter/{node-event-generator.js → source-code-traverser.js} +143 -87
- package/lib/options.js +7 -0
- package/lib/rule-tester/rule-tester.js +3 -3
- package/lib/rules/func-style.js +57 -7
- package/lib/rules/index.js +1 -0
- package/lib/rules/max-params.js +32 -7
- package/lib/rules/no-array-constructor.js +51 -1
- package/lib/rules/no-implicit-globals.js +31 -15
- package/lib/rules/no-magic-numbers.js +98 -5
- package/lib/rules/no-shadow.js +262 -6
- package/lib/rules/no-unassigned-vars.js +80 -0
- package/lib/rules/no-use-before-define.js +97 -1
- package/lib/rules/no-useless-escape.js +24 -2
- package/lib/rules/prefer-arrow-callback.js +9 -0
- package/lib/rules/prefer-named-capture-group.js +7 -1
- package/lib/services/processor-service.js +1 -1
- package/lib/services/suppressions-service.js +5 -3
- package/lib/services/warning-service.js +85 -0
- package/lib/shared/flags.js +1 -0
- package/lib/types/index.d.ts +132 -9
- package/lib/types/rules.d.ts +66 -3
- package/package.json +11 -11
- package/lib/config/flat-config-helpers.js +0 -128
- package/lib/config/rule-validator.js +0 -199
- package/lib/mcp/mcp-server.js +0 -66
- package/lib/shared/types.js +0 -229
@@ -53,7 +53,7 @@ const CODE_PATH_EVENTS = [
|
|
53
53
|
/**
|
54
54
|
* Validates that the given AST has the required information.
|
55
55
|
* @param {ASTNode} ast The Program node of the AST to check.
|
56
|
-
* @throws {
|
56
|
+
* @throws {TypeError} If the AST doesn't contain the correct information.
|
57
57
|
* @returns {void}
|
58
58
|
* @private
|
59
59
|
*/
|
@@ -147,8 +147,8 @@ function sortedMerge(tokens, comments) {
|
|
147
147
|
* Normalizes a value for a global in a config
|
148
148
|
* @param {(boolean|string|null)} configuredValue The value given for a global in configuration or in
|
149
149
|
* a global directive comment
|
150
|
-
* @returns {("
|
151
|
-
* @throws Error if global value is invalid
|
150
|
+
* @returns {("readonly"|"writable"|"off")} The value normalized as a string
|
151
|
+
* @throws {Error} if global value is invalid
|
152
152
|
*/
|
153
153
|
function normalizeConfigGlobal(configuredValue) {
|
154
154
|
switch (configuredValue) {
|
@@ -316,6 +316,36 @@ function addDeclaredGlobals(
|
|
316
316
|
|
317
317
|
return true;
|
318
318
|
});
|
319
|
+
|
320
|
+
/*
|
321
|
+
* "implicit" contains information about implicit global variables (those created
|
322
|
+
* implicitly by assigning values to undeclared variables in non-strict code).
|
323
|
+
* Since we augment the global scope using configuration, we need to remove
|
324
|
+
* the ones that were added by configuration, as they are either built-in
|
325
|
+
* or declared elsewhere, therefore not implicit.
|
326
|
+
* Since the "implicit" property was not documented, first we'll check if it exists
|
327
|
+
* because it's possible that not all custom scope managers create this property.
|
328
|
+
* If it exists, we assume it has properties `variables` and `set`. Property
|
329
|
+
* `left` is considered optional (for example, typescript-eslint's scope manage
|
330
|
+
* has this property named `leftToBeResolved`).
|
331
|
+
*/
|
332
|
+
const { implicit } = globalScope;
|
333
|
+
if (typeof implicit === "object" && implicit !== null) {
|
334
|
+
implicit.variables = implicit.variables.filter(variable => {
|
335
|
+
const name = variable.name;
|
336
|
+
if (globalScope.set.has(name)) {
|
337
|
+
implicit.set.delete(name);
|
338
|
+
return false;
|
339
|
+
}
|
340
|
+
return true;
|
341
|
+
});
|
342
|
+
|
343
|
+
if (implicit.left) {
|
344
|
+
implicit.left = implicit.left.filter(
|
345
|
+
reference => !globalScope.set.has(reference.identifier.name),
|
346
|
+
);
|
347
|
+
}
|
348
|
+
}
|
319
349
|
}
|
320
350
|
|
321
351
|
/**
|
@@ -471,6 +501,10 @@ class SourceCode extends TokenStore {
|
|
471
501
|
* @type {string[]}
|
472
502
|
*/
|
473
503
|
this.lines = [];
|
504
|
+
|
505
|
+
/**
|
506
|
+
* @type {number[]}
|
507
|
+
*/
|
474
508
|
this.lineStartIndices = [0];
|
475
509
|
|
476
510
|
const lineEndingPattern = astUtils.createGlobalLinebreakMatcher();
|
@@ -528,7 +562,7 @@ class SourceCode extends TokenStore {
|
|
528
562
|
|
529
563
|
/**
|
530
564
|
* Gets the entire source text split into an array of lines.
|
531
|
-
* @returns {
|
565
|
+
* @returns {string[]} The source text as an array of lines.
|
532
566
|
* @public
|
533
567
|
*/
|
534
568
|
getLines() {
|
@@ -687,8 +721,8 @@ class SourceCode extends TokenStore {
|
|
687
721
|
/**
|
688
722
|
* Converts a source text index into a (line, column) pair.
|
689
723
|
* @param {number} index The index of a character in a file
|
690
|
-
* @throws {TypeError} If non-numeric index or index out of range.
|
691
|
-
* @returns {
|
724
|
+
* @throws {TypeError|RangeError} If non-numeric index or index out of range.
|
725
|
+
* @returns {{line: number, column: number}} A {line, column} location object with a 0-indexed column
|
692
726
|
* @public
|
693
727
|
*/
|
694
728
|
getLocFromIndex(index) {
|
@@ -9,7 +9,7 @@
|
|
9
9
|
// Typedefs
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
|
-
/** @typedef {import("../
|
12
|
+
/** @typedef {import("../types").Linter.LintMessage} LintMessage */
|
13
13
|
/** @typedef {import("@eslint/core").Language} Language */
|
14
14
|
/** @typedef {import("@eslint/core").Position} Position */
|
15
15
|
/** @typedef {import("@eslint/core").RulesConfig} RulesConfig */
|
@@ -128,6 +128,17 @@ class FileContext {
|
|
128
128
|
getSourceCode() {
|
129
129
|
return this.sourceCode;
|
130
130
|
}
|
131
|
+
|
132
|
+
/**
|
133
|
+
* Creates a new object with the current object as the prototype and
|
134
|
+
* the specified properties as its own properties.
|
135
|
+
* @param {Object} extension The properties to add to the new object.
|
136
|
+
* @returns {FileContext} A new object with the current object as the prototype
|
137
|
+
* and the specified properties as its own properties.
|
138
|
+
*/
|
139
|
+
extend(extension) {
|
140
|
+
return Object.freeze(Object.assign(Object.create(this), extension));
|
141
|
+
}
|
131
142
|
}
|
132
143
|
|
133
144
|
exports.FileContext = FileContext;
|
package/lib/linter/linter.js
CHANGED
@@ -27,17 +27,14 @@ const path = require("node:path"),
|
|
27
27
|
{ SourceCode } = require("../languages/js/source-code"),
|
28
28
|
applyDisableDirectives = require("./apply-disable-directives"),
|
29
29
|
{ ConfigCommentParser } = require("@eslint/plugin-kit"),
|
30
|
-
NodeEventGenerator = require("./node-event-generator"),
|
31
30
|
createReportTranslator = require("./report-translator"),
|
32
31
|
Rules = require("./rules"),
|
33
32
|
createEmitter = require("./safe-emitter"),
|
34
33
|
SourceCodeFixer = require("./source-code-fixer"),
|
35
34
|
timing = require("./timing"),
|
36
35
|
ruleReplacements = require("../../conf/replacements.json");
|
37
|
-
const { getRuleFromConfig } = require("../config/flat-config-helpers");
|
38
36
|
const { FlatConfigArray } = require("../config/flat-config-array");
|
39
37
|
const { startTime, endTime } = require("../shared/stats");
|
40
|
-
const { RuleValidator } = require("../config/rule-validator");
|
41
38
|
const { assertIsRuleSeverity } = require("../config/flat-config-schema");
|
42
39
|
const {
|
43
40
|
normalizeSeverityToString,
|
@@ -66,8 +63,9 @@ const { ParserService } = require("../services/parser-service");
|
|
66
63
|
const { FileContext } = require("./file-context");
|
67
64
|
const { ProcessorService } = require("../services/processor-service");
|
68
65
|
const { containsDifferentProperty } = require("../shared/option-utils");
|
69
|
-
const
|
70
|
-
const
|
66
|
+
const { Config } = require("../config/config");
|
67
|
+
const { WarningService } = require("../services/warning-service");
|
68
|
+
const { SourceCodeTraverser } = require("./source-code-traverser");
|
71
69
|
|
72
70
|
//------------------------------------------------------------------------------
|
73
71
|
// Typedefs
|
@@ -75,17 +73,19 @@ const STEP_KIND_CALL = 2;
|
|
75
73
|
|
76
74
|
/** @import { Language, LanguageOptions, RuleConfig, RuleDefinition, RuleSeverity } from "@eslint/core" */
|
77
75
|
|
78
|
-
/** @typedef {import("../
|
79
|
-
/** @typedef {import("../
|
80
|
-
/** @typedef {import("../
|
81
|
-
/** @typedef {import("../
|
82
|
-
/** @typedef {import("../shared/types").SuppressedLintMessage} SuppressedLintMessage */
|
83
|
-
/** @typedef {import("../shared/types").ParserOptions} ParserOptions */
|
84
|
-
/** @typedef {import("../shared/types").Processor} Processor */
|
85
|
-
/** @typedef {import("../shared/types").Times} Times */
|
76
|
+
/** @typedef {import("../types").Linter.Config} Config */
|
77
|
+
/** @typedef {import("../types").ESLint.ConfigData} ConfigData */
|
78
|
+
/** @typedef {import("../types").ESLint.Environment} Environment */
|
79
|
+
/** @typedef {import("../types").Linter.GlobalConf} GlobalConf */
|
86
80
|
/** @typedef {import("../types").Linter.LanguageOptions} JSLanguageOptions */
|
87
|
-
/** @typedef {import("../types").Linter.
|
81
|
+
/** @typedef {import("../types").Linter.LintMessage} LintMessage */
|
82
|
+
/** @typedef {import("../types").Linter.Parser} Parser */
|
83
|
+
/** @typedef {import("../types").Linter.ParserOptions} ParserOptions */
|
84
|
+
/** @typedef {import("../types").Linter.Processor} Processor */
|
88
85
|
/** @typedef {import("../types").Rule.RuleModule} Rule */
|
86
|
+
/** @typedef {import("../types").Linter.StringSeverity} StringSeverity */
|
87
|
+
/** @typedef {import("../types").Linter.SuppressedLintMessage} SuppressedLintMessage */
|
88
|
+
/** @typedef {import("../types").Linter.TimePass} TimePass */
|
89
89
|
|
90
90
|
/* eslint-disable jsdoc/valid-types -- https://github.com/jsdoc-type-pratt-parser/jsdoc-type-pratt-parser/issues/4#issuecomment-778805577 */
|
91
91
|
/**
|
@@ -110,8 +110,9 @@ const STEP_KIND_CALL = 2;
|
|
110
110
|
* @property {SourceCode|null} lastSourceCode The `SourceCode` instance that the last `verify()` call used.
|
111
111
|
* @property {SuppressedLintMessage[]} lastSuppressedMessages The `SuppressedLintMessage[]` instance that the last `verify()` call produced.
|
112
112
|
* @property {Map<string, Parser>} parserMap The loaded parsers.
|
113
|
-
* @property {
|
113
|
+
* @property {{ passes: TimePass[]; }} times The times spent on applying a rule to a file (see `stats` option).
|
114
114
|
* @property {Rules} ruleMap The loaded rules.
|
115
|
+
* @property {WarningService} warningService The warning service.
|
115
116
|
*/
|
116
117
|
|
117
118
|
/**
|
@@ -350,7 +351,7 @@ function asArray(value) {
|
|
350
351
|
|
351
352
|
/**
|
352
353
|
* Pushes a problem to inlineConfigProblems if ruleOptions are redundant.
|
353
|
-
* @param {
|
354
|
+
* @param {Config} config Provided config.
|
354
355
|
* @param {Object} loc A line/column location
|
355
356
|
* @param {Array} problems Problems that may be added to.
|
356
357
|
* @param {string} ruleId The rule ID.
|
@@ -901,7 +902,7 @@ function normalizeFilename(filename) {
|
|
901
902
|
* Normalizes the possible options for `linter.verify` and `linter.verifyAndFix` to a
|
902
903
|
* consistent shape.
|
903
904
|
* @param {VerifyOptions} providedOptions Options
|
904
|
-
* @param {ConfigData} config Config.
|
905
|
+
* @param {Config|ConfigData} config Config.
|
905
906
|
* @returns {Required<VerifyOptions> & InternalOptions} Normalized options
|
906
907
|
*/
|
907
908
|
function normalizeVerifyOptions(providedOptions, config) {
|
@@ -1176,15 +1177,12 @@ function runRules(
|
|
1176
1177
|
) {
|
1177
1178
|
const emitter = createEmitter();
|
1178
1179
|
|
1179
|
-
// must happen first to assign all node.parent properties
|
1180
|
-
const eventQueue = sourceCode.traverse();
|
1181
|
-
|
1182
1180
|
/*
|
1183
1181
|
* Create a frozen object with the ruleContext properties and methods that are shared by all rules.
|
1184
1182
|
* All rule contexts will inherit from this object. This avoids the performance penalty of copying all the
|
1185
1183
|
* properties once for each rule.
|
1186
1184
|
*/
|
1187
|
-
const
|
1185
|
+
const fileContext = new FileContext({
|
1188
1186
|
cwd,
|
1189
1187
|
filename,
|
1190
1188
|
physicalFilename: physicalFilename || filename,
|
@@ -1198,9 +1196,10 @@ function runRules(
|
|
1198
1196
|
});
|
1199
1197
|
|
1200
1198
|
const lintingProblems = [];
|
1199
|
+
const steps = sourceCode.traverse();
|
1201
1200
|
|
1202
1201
|
Object.keys(configuredRules).forEach(ruleId => {
|
1203
|
-
const severity =
|
1202
|
+
const severity = Config.getRuleNumericSeverity(configuredRules[ruleId]);
|
1204
1203
|
|
1205
1204
|
// not load disabled rules
|
1206
1205
|
if (severity === 0) {
|
@@ -1220,63 +1219,61 @@ function runRules(
|
|
1220
1219
|
|
1221
1220
|
const messageIds = rule.meta && rule.meta.messages;
|
1222
1221
|
let reportTranslator = null;
|
1223
|
-
const ruleContext =
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
const problem = reportTranslator(...args);
|
1222
|
+
const ruleContext = fileContext.extend({
|
1223
|
+
id: ruleId,
|
1224
|
+
options: getRuleOptions(
|
1225
|
+
configuredRules[ruleId],
|
1226
|
+
applyDefaultOptions ? rule.meta?.defaultOptions : void 0,
|
1227
|
+
),
|
1228
|
+
report(...args) {
|
1229
|
+
/*
|
1230
|
+
* Create a report translator lazily.
|
1231
|
+
* In a vast majority of cases, any given rule reports zero errors on a given
|
1232
|
+
* piece of code. Creating a translator lazily avoids the performance cost of
|
1233
|
+
* creating a new translator function for each rule that usually doesn't get
|
1234
|
+
* called.
|
1235
|
+
*
|
1236
|
+
* Using lazy report translators improves end-to-end performance by about 3%
|
1237
|
+
* with Node 8.4.0.
|
1238
|
+
*/
|
1239
|
+
if (reportTranslator === null) {
|
1240
|
+
reportTranslator = createReportTranslator({
|
1241
|
+
ruleId,
|
1242
|
+
severity,
|
1243
|
+
sourceCode,
|
1244
|
+
messageIds,
|
1245
|
+
disableFixes,
|
1246
|
+
language,
|
1247
|
+
});
|
1248
|
+
}
|
1249
|
+
const problem = reportTranslator(...args);
|
1252
1250
|
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1251
|
+
if (problem.fix && !(rule.meta && rule.meta.fixable)) {
|
1252
|
+
throw new Error(
|
1253
|
+
'Fixable rules must set the `meta.fixable` property to "code" or "whitespace".',
|
1254
|
+
);
|
1255
|
+
}
|
1256
|
+
if (
|
1257
|
+
problem.suggestions &&
|
1258
|
+
!(rule.meta && rule.meta.hasSuggestions === true)
|
1259
|
+
) {
|
1258
1260
|
if (
|
1259
|
-
|
1260
|
-
|
1261
|
+
rule.meta &&
|
1262
|
+
rule.meta.docs &&
|
1263
|
+
typeof rule.meta.docs.suggestion !== "undefined"
|
1261
1264
|
) {
|
1262
|
-
|
1263
|
-
rule.meta &&
|
1264
|
-
rule.meta.docs &&
|
1265
|
-
typeof rule.meta.docs.suggestion !== "undefined"
|
1266
|
-
) {
|
1267
|
-
// Encourage migration from the former property name.
|
1268
|
-
throw new Error(
|
1269
|
-
"Rules with suggestions must set the `meta.hasSuggestions` property to `true`. `meta.docs.suggestion` is ignored by ESLint.",
|
1270
|
-
);
|
1271
|
-
}
|
1265
|
+
// Encourage migration from the former property name.
|
1272
1266
|
throw new Error(
|
1273
|
-
"Rules with suggestions must set the `meta.hasSuggestions` property to `true`.",
|
1267
|
+
"Rules with suggestions must set the `meta.hasSuggestions` property to `true`. `meta.docs.suggestion` is ignored by ESLint.",
|
1274
1268
|
);
|
1275
1269
|
}
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1270
|
+
throw new Error(
|
1271
|
+
"Rules with suggestions must set the `meta.hasSuggestions` property to `true`.",
|
1272
|
+
);
|
1273
|
+
}
|
1274
|
+
lintingProblems.push(problem);
|
1275
|
+
},
|
1276
|
+
});
|
1280
1277
|
|
1281
1278
|
const ruleListenersReturn =
|
1282
1279
|
timing.enabled || stats
|
@@ -1346,40 +1343,9 @@ function runRules(
|
|
1346
1343
|
});
|
1347
1344
|
});
|
1348
1345
|
|
1349
|
-
const
|
1350
|
-
visitorKeys: sourceCode.visitorKeys ?? language.visitorKeys,
|
1351
|
-
fallback: Traverser.getKeys,
|
1352
|
-
matchClass: language.matchesSelectorClass ?? (() => false),
|
1353
|
-
nodeTypeKey: language.nodeTypeKey,
|
1354
|
-
});
|
1346
|
+
const traverser = SourceCodeTraverser.getInstance(language);
|
1355
1347
|
|
1356
|
-
|
1357
|
-
switch (step.kind) {
|
1358
|
-
case STEP_KIND_VISIT: {
|
1359
|
-
try {
|
1360
|
-
if (step.phase === 1) {
|
1361
|
-
eventGenerator.enterNode(step.target);
|
1362
|
-
} else {
|
1363
|
-
eventGenerator.leaveNode(step.target);
|
1364
|
-
}
|
1365
|
-
} catch (err) {
|
1366
|
-
err.currentNode = step.target;
|
1367
|
-
throw err;
|
1368
|
-
}
|
1369
|
-
break;
|
1370
|
-
}
|
1371
|
-
|
1372
|
-
case STEP_KIND_CALL: {
|
1373
|
-
emitter.emit(step.target, ...step.args);
|
1374
|
-
break;
|
1375
|
-
}
|
1376
|
-
|
1377
|
-
default:
|
1378
|
-
throw new Error(
|
1379
|
-
`Invalid traversal step found: "${step.type}".`,
|
1380
|
-
);
|
1381
|
-
}
|
1382
|
-
}
|
1348
|
+
traverser.traverseSync(sourceCode, emitter, { steps });
|
1383
1349
|
|
1384
1350
|
return lintingProblems;
|
1385
1351
|
}
|
@@ -1484,8 +1450,14 @@ class Linter {
|
|
1484
1450
|
* @param {string} [config.cwd] path to a directory that should be considered as the current working directory, can be undefined.
|
1485
1451
|
* @param {Array<string>} [config.flags] the feature flags to enable.
|
1486
1452
|
* @param {"flat"|"eslintrc"} [config.configType="flat"] the type of config used.
|
1453
|
+
* @param {WarningService} [config.warningService] The warning service to use.
|
1487
1454
|
*/
|
1488
|
-
constructor({
|
1455
|
+
constructor({
|
1456
|
+
cwd,
|
1457
|
+
configType = "flat",
|
1458
|
+
flags = [],
|
1459
|
+
warningService = new WarningService(),
|
1460
|
+
} = {}) {
|
1489
1461
|
const processedFlags = [];
|
1490
1462
|
|
1491
1463
|
flags.forEach(flag => {
|
@@ -1493,11 +1465,10 @@ class Linter {
|
|
1493
1465
|
const inactiveFlagData = inactiveFlags.get(flag);
|
1494
1466
|
const inactivityReason =
|
1495
1467
|
getInactivityReasonMessage(inactiveFlagData);
|
1468
|
+
const message = `The flag '${flag}' is inactive: ${inactivityReason}`;
|
1496
1469
|
|
1497
1470
|
if (typeof inactiveFlagData.replacedBy === "undefined") {
|
1498
|
-
throw new Error(
|
1499
|
-
`The flag '${flag}' is inactive: ${inactivityReason}`,
|
1500
|
-
);
|
1471
|
+
throw new Error(message);
|
1501
1472
|
}
|
1502
1473
|
|
1503
1474
|
// if there's a replacement, enable it instead of original
|
@@ -1505,10 +1476,7 @@ class Linter {
|
|
1505
1476
|
processedFlags.push(inactiveFlagData.replacedBy);
|
1506
1477
|
}
|
1507
1478
|
|
1508
|
-
|
1509
|
-
`The flag '${flag}' is inactive: ${inactivityReason}`,
|
1510
|
-
`ESLintInactiveFlag_${flag}`,
|
1511
|
-
);
|
1479
|
+
warningService.emitInactiveFlagWarning(flag, message);
|
1512
1480
|
|
1513
1481
|
return;
|
1514
1482
|
}
|
@@ -1529,6 +1497,7 @@ class Linter {
|
|
1529
1497
|
configType, // TODO: Remove after flat config conversion
|
1530
1498
|
parserMap: new Map([["espree", espree]]),
|
1531
1499
|
ruleMap: new Rules(),
|
1500
|
+
warningService,
|
1532
1501
|
});
|
1533
1502
|
|
1534
1503
|
this.version = pkg.version;
|
@@ -1885,7 +1854,7 @@ class Linter {
|
|
1885
1854
|
/**
|
1886
1855
|
* Verify with a processor.
|
1887
1856
|
* @param {string|SourceCode} textOrSourceCode The source code.
|
1888
|
-
* @param {
|
1857
|
+
* @param {Config} config The config array.
|
1889
1858
|
* @param {VerifyOptions&ProcessorOptions} options The options.
|
1890
1859
|
* @param {FlatConfigArray} [configForRecursive] The `ConfigArray` object to apply multiple processors recursively.
|
1891
1860
|
* @returns {(LintMessage|SuppressedLintMessage)[]} The found problems.
|
@@ -1986,7 +1955,7 @@ class Linter {
|
|
1986
1955
|
/**
|
1987
1956
|
* Verify using flat config and without any processors.
|
1988
1957
|
* @param {VFile} file The file to lint.
|
1989
|
-
* @param {
|
1958
|
+
* @param {Config} providedConfig An ESLintConfig instance to configure everything.
|
1990
1959
|
* @param {VerifyOptions} [providedOptions] The optional filename of the file being checked.
|
1991
1960
|
* @throws {Error} If during rule execution.
|
1992
1961
|
* @returns {(LintMessage|SuppressedLintMessage)[]} The results as an array of messages or an empty array if no messages.
|
@@ -2100,15 +2069,12 @@ class Linter {
|
|
2100
2069
|
}),
|
2101
2070
|
);
|
2102
2071
|
|
2103
|
-
// next we need to verify information about the specified rules
|
2104
|
-
const ruleValidator = new RuleValidator();
|
2105
|
-
|
2106
2072
|
for (const {
|
2107
2073
|
config: inlineConfig,
|
2108
2074
|
loc,
|
2109
2075
|
} of inlineConfigResult.configs) {
|
2110
2076
|
Object.keys(inlineConfig.rules).forEach(ruleId => {
|
2111
|
-
const rule =
|
2077
|
+
const rule = config.getRuleDefinition(ruleId);
|
2112
2078
|
const ruleValue = inlineConfig.rules[ruleId];
|
2113
2079
|
|
2114
2080
|
if (!rule) {
|
@@ -2218,11 +2184,8 @@ class Linter {
|
|
2218
2184
|
}
|
2219
2185
|
|
2220
2186
|
if (shouldValidateOptions) {
|
2221
|
-
|
2222
|
-
|
2223
|
-
rules: {
|
2224
|
-
[ruleId]: ruleOptions,
|
2225
|
-
},
|
2187
|
+
config.validateRulesConfig({
|
2188
|
+
[ruleId]: ruleOptions,
|
2226
2189
|
});
|
2227
2190
|
}
|
2228
2191
|
|
@@ -2270,7 +2233,7 @@ class Linter {
|
|
2270
2233
|
options.allowInlineConfig && !options.warnInlineConfig
|
2271
2234
|
? getDirectiveCommentsForFlatConfig(
|
2272
2235
|
sourceCode,
|
2273
|
-
ruleId =>
|
2236
|
+
ruleId => config.getRuleDefinition(ruleId),
|
2274
2237
|
config.language,
|
2275
2238
|
)
|
2276
2239
|
: { problems: [], disableDirectives: [] };
|
@@ -2289,7 +2252,7 @@ class Linter {
|
|
2289
2252
|
lintingProblems = runRules(
|
2290
2253
|
sourceCode,
|
2291
2254
|
configuredRules,
|
2292
|
-
ruleId =>
|
2255
|
+
ruleId => config.getRuleDefinition(ruleId),
|
2293
2256
|
void 0,
|
2294
2257
|
config.language,
|
2295
2258
|
languageOptions,
|
@@ -2348,7 +2311,7 @@ class Linter {
|
|
2348
2311
|
/**
|
2349
2312
|
* Same as linter.verify, except without support for processors.
|
2350
2313
|
* @param {string|SourceCode} textOrSourceCode The text to parse or a SourceCode object.
|
2351
|
-
* @param {
|
2314
|
+
* @param {Config} providedConfig An ESLintConfig instance to configure everything.
|
2352
2315
|
* @param {VerifyOptions} [providedOptions] The optional filename of the file being checked.
|
2353
2316
|
* @throws {Error} If during rule execution.
|
2354
2317
|
* @returns {(LintMessage|SuppressedLintMessage)[]} The results as an array of messages or an empty array if no messages.
|
@@ -2619,7 +2582,7 @@ class Linter {
|
|
2619
2582
|
|
2620
2583
|
/**
|
2621
2584
|
* Gets the times spent on (parsing, fixing, linting) a file.
|
2622
|
-
* @returns {
|
2585
|
+
* @returns {{ passes: TimePass[]; }} The times.
|
2623
2586
|
*/
|
2624
2587
|
getTimes() {
|
2625
2588
|
return internalSlotsMap.get(this).times ?? { passes: [] };
|
@@ -2717,6 +2680,14 @@ class Linter {
|
|
2717
2680
|
options && typeof options.fix !== "undefined" ? options.fix : true;
|
2718
2681
|
const stats = options?.stats;
|
2719
2682
|
|
2683
|
+
const slots = internalSlotsMap.get(this);
|
2684
|
+
|
2685
|
+
// Remove lint times from the last run.
|
2686
|
+
if (stats) {
|
2687
|
+
delete slots.times;
|
2688
|
+
slots.fixPasses = 0;
|
2689
|
+
}
|
2690
|
+
|
2720
2691
|
/**
|
2721
2692
|
* This loop continues until one of the following is true:
|
2722
2693
|
*
|
@@ -2726,14 +2697,6 @@ class Linter {
|
|
2726
2697
|
* That means anytime a fix is successfully applied, there will be another pass.
|
2727
2698
|
* Essentially, guaranteeing a minimum of two passes.
|
2728
2699
|
*/
|
2729
|
-
const slots = internalSlotsMap.get(this);
|
2730
|
-
|
2731
|
-
// Remove lint times from the last run.
|
2732
|
-
if (stats) {
|
2733
|
-
delete slots.times;
|
2734
|
-
slots.fixPasses = 0;
|
2735
|
-
}
|
2736
|
-
|
2737
2700
|
do {
|
2738
2701
|
passNumber++;
|
2739
2702
|
let tTotal;
|
@@ -2805,9 +2768,8 @@ class Linter {
|
|
2805
2768
|
debug(
|
2806
2769
|
`Circular fixes detected after pass ${passNumber}. Exiting fix loop.`,
|
2807
2770
|
);
|
2808
|
-
|
2809
|
-
|
2810
|
-
"ESLintCircularFixesWarning",
|
2771
|
+
slots.warningService.emitCircularFixesWarning(
|
2772
|
+
options?.filename ?? "text",
|
2811
2773
|
);
|
2812
2774
|
break;
|
2813
2775
|
}
|
@@ -17,7 +17,8 @@ const { interpolate } = require("./interpolate");
|
|
17
17
|
// Typedefs
|
18
18
|
//------------------------------------------------------------------------------
|
19
19
|
|
20
|
-
/** @typedef {import("../
|
20
|
+
/** @typedef {import("../types").Linter.LintMessage} LintMessage */
|
21
|
+
/** @typedef {import("../types").Linter.LintSuggestion} SuggestionResult */
|
21
22
|
|
22
23
|
/**
|
23
24
|
* An error message description
|