eslint 9.31.0 → 9.33.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.
@@ -27,12 +27,10 @@ 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
- createReportTranslator = require("./report-translator"),
31
30
  Rules = require("./rules"),
32
31
  SourceCodeFixer = require("./source-code-fixer"),
33
32
  { SourceCodeVisitor } = require("./source-code-visitor"),
34
- timing = require("./timing"),
35
- ruleReplacements = require("../../conf/replacements.json");
33
+ timing = require("./timing");
36
34
  const { FlatConfigArray } = require("../config/flat-config-array");
37
35
  const { startTime, endTime } = require("../shared/stats");
38
36
  const { assertIsRuleSeverity } = require("../config/flat-config-schema");
@@ -52,10 +50,6 @@ const MAX_AUTOFIX_PASSES = 10;
52
50
  const DEFAULT_PARSER_NAME = "espree";
53
51
  const DEFAULT_ECMA_VERSION = 5;
54
52
  const commentParser = new ConfigCommentParser();
55
- const DEFAULT_ERROR_LOC = {
56
- start: { line: 1, column: 0 },
57
- end: { line: 1, column: 1 },
58
- };
59
53
  const parserSymbol = Symbol.for("eslint.RuleTester.parser");
60
54
  const { LATEST_ECMA_VERSION } = require("../../conf/ecma-version");
61
55
  const { VFile } = require("./vfile");
@@ -66,6 +60,7 @@ const { containsDifferentProperty } = require("../shared/option-utils");
66
60
  const { Config } = require("../config/config");
67
61
  const { WarningService } = require("../services/warning-service");
68
62
  const { SourceCodeTraverser } = require("./source-code-traverser");
63
+ const { FileReport, updateLocationInformation } = require("./file-report");
69
64
 
70
65
  //------------------------------------------------------------------------------
71
66
  // Typedefs
@@ -253,92 +248,6 @@ function addDeclaredGlobals(
253
248
  });
254
249
  }
255
250
 
256
- /**
257
- * creates a missing-rule message.
258
- * @param {string} ruleId the ruleId to create
259
- * @returns {string} created error message
260
- * @private
261
- */
262
- function createMissingRuleMessage(ruleId) {
263
- return Object.hasOwn(ruleReplacements.rules, ruleId)
264
- ? `Rule '${ruleId}' was removed and replaced by: ${ruleReplacements.rules[ruleId].join(", ")}`
265
- : `Definition for rule '${ruleId}' was not found.`;
266
- }
267
-
268
- /**
269
- * Updates a given location based on the language offsets. This allows us to
270
- * change 0-based locations to 1-based locations. We always want ESLint
271
- * reporting lines and columns starting from 1.
272
- * @param {Object} location The location to update.
273
- * @param {number} location.line The starting line number.
274
- * @param {number} location.column The starting column number.
275
- * @param {number} [location.endLine] The ending line number.
276
- * @param {number} [location.endColumn] The ending column number.
277
- * @param {Language} language The language to use to adjust the location information.
278
- * @returns {Object} The updated location.
279
- */
280
- function updateLocationInformation(
281
- { line, column, endLine, endColumn },
282
- language,
283
- ) {
284
- const columnOffset = language.columnStart === 1 ? 0 : 1;
285
- const lineOffset = language.lineStart === 1 ? 0 : 1;
286
-
287
- // calculate separately to account for undefined
288
- const finalEndLine = endLine === void 0 ? endLine : endLine + lineOffset;
289
- const finalEndColumn =
290
- endColumn === void 0 ? endColumn : endColumn + columnOffset;
291
-
292
- return {
293
- line: line + lineOffset,
294
- column: column + columnOffset,
295
- endLine: finalEndLine,
296
- endColumn: finalEndColumn,
297
- };
298
- }
299
-
300
- /**
301
- * creates a linting problem
302
- * @param {Object} options to create linting error
303
- * @param {string} [options.ruleId] the ruleId to report
304
- * @param {Object} [options.loc] the loc to report
305
- * @param {string} [options.message] the error message to report
306
- * @param {RuleSeverity} [options.severity] the error message to report
307
- * @param {Language} [options.language] the language to use to adjust the location information
308
- * @returns {LintMessage} created problem, returns a missing-rule problem if only provided ruleId.
309
- * @private
310
- */
311
- function createLintingProblem(options) {
312
- const {
313
- ruleId = null,
314
- loc = DEFAULT_ERROR_LOC,
315
- message = createMissingRuleMessage(options.ruleId),
316
- severity = 2,
317
-
318
- // fallback for eslintrc mode
319
- language = {
320
- columnStart: 0,
321
- lineStart: 1,
322
- },
323
- } = options;
324
-
325
- return {
326
- ruleId,
327
- message,
328
- ...updateLocationInformation(
329
- {
330
- line: loc.start.line,
331
- column: loc.start.column,
332
- endLine: loc.end.line,
333
- endColumn: loc.end.column,
334
- },
335
- language,
336
- ),
337
- severity,
338
- nodeType: null,
339
- };
340
- }
341
-
342
251
  /**
343
252
  * Wraps the value in an Array if it isn't already one.
344
253
  * @template T
@@ -353,7 +262,7 @@ function asArray(value) {
353
262
  * Pushes a problem to inlineConfigProblems if ruleOptions are redundant.
354
263
  * @param {Config} config Provided config.
355
264
  * @param {Object} loc A line/column location
356
- * @param {Array} problems Problems that may be added to.
265
+ * @param {FileReport} report Report that may be added to.
357
266
  * @param {string} ruleId The rule ID.
358
267
  * @param {Array} ruleOptions The rule options, merged with the config's.
359
268
  * @param {Array} ruleOptionsInline The rule options from the comment.
@@ -363,7 +272,7 @@ function asArray(value) {
363
272
  function addProblemIfSameSeverityAndOptions(
364
273
  config,
365
274
  loc,
366
- problems,
275
+ report,
367
276
  ruleId,
368
277
  ruleOptions,
369
278
  ruleOptionsInline,
@@ -404,15 +313,17 @@ function addProblemIfSameSeverityAndOptions(
404
313
  }
405
314
 
406
315
  if (message) {
407
- problems.push(
408
- createLintingProblem({
409
- ruleId: null,
410
- message,
411
- loc,
412
- language: config.language,
413
- severity: normalizeSeverityToNumber(severity),
414
- }),
415
- );
316
+ const numericSeverity = normalizeSeverityToNumber(severity);
317
+ const descriptor = {
318
+ message,
319
+ loc,
320
+ };
321
+
322
+ if (numericSeverity === 1) {
323
+ report.addWarning(descriptor);
324
+ } else if (numericSeverity === 2) {
325
+ report.addError(descriptor);
326
+ }
416
327
  }
417
328
  }
418
329
 
@@ -427,20 +338,19 @@ function addProblemIfSameSeverityAndOptions(
427
338
  * @param {function(string): {create: Function}} ruleMapper A map from rule IDs to defined rules
428
339
  * @param {Language} language The language to use to adjust the location information.
429
340
  * @param {SourceCode} sourceCode The SourceCode object to get comments from.
430
- * @returns {Object} Directives and problems from the comment
341
+ * @param {FileReport} report The report to add problems to.
342
+ * @returns {Object[]} Directives from the comment
431
343
  */
432
344
  function createDisableDirectives(
433
345
  { type, value, justification, node },
434
346
  ruleMapper,
435
347
  language,
436
348
  sourceCode,
349
+ report,
437
350
  ) {
438
351
  const ruleIds = Object.keys(commentParser.parseListConfig(value));
439
352
  const directiveRules = ruleIds.length ? ruleIds : [null];
440
- const result = {
441
- directives: [], // valid disable directives
442
- directiveProblems: [], // problems in directives
443
- };
353
+ const directives = []; // valid disable directives
444
354
  const parentDirective = { node, value, ruleIds };
445
355
 
446
356
  for (const ruleId of directiveRules) {
@@ -454,7 +364,7 @@ function createDisableDirectives(
454
364
  language,
455
365
  );
456
366
 
457
- result.directives.push({
367
+ directives.push({
458
368
  parentDirective,
459
369
  type,
460
370
  line,
@@ -468,7 +378,7 @@ function createDisableDirectives(
468
378
  language,
469
379
  );
470
380
 
471
- result.directives.push({
381
+ directives.push({
472
382
  parentDirective,
473
383
  type,
474
384
  line,
@@ -478,12 +388,11 @@ function createDisableDirectives(
478
388
  });
479
389
  }
480
390
  } else {
481
- result.directiveProblems.push(
482
- createLintingProblem({ ruleId, loc, language }),
483
- );
391
+ report.addError({ ruleId, loc });
484
392
  }
485
393
  }
486
- return result;
394
+
395
+ return directives;
487
396
  }
488
397
 
489
398
  /**
@@ -494,7 +403,8 @@ function createDisableDirectives(
494
403
  * @param {function(string): {create: Function}} ruleMapper A map from rule IDs to defined rules
495
404
  * @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.
496
405
  * @param {ConfigData} config Provided config.
497
- * @returns {{configuredRules: Object, enabledGlobals: {value:string,comment:Token}[], exportedVariables: Object, problems: LintMessage[], disableDirectives: DisableDirective[]}}
406
+ * @param {FileReport} report The report to add problems to.
407
+ * @returns {{configuredRules: Object, enabledGlobals: {value:string,comment:Token}[], exportedVariables: Object, disableDirectives: DisableDirective[]}}
498
408
  * A collection of the directive comments that were found, along with any problems that occurred when parsing
499
409
  */
500
410
  function getDirectiveComments(
@@ -502,11 +412,11 @@ function getDirectiveComments(
502
412
  ruleMapper,
503
413
  warnInlineConfig,
504
414
  config,
415
+ report,
505
416
  ) {
506
417
  const configuredRules = {};
507
418
  const enabledGlobals = Object.create(null);
508
419
  const exportedVariables = {};
509
- const problems = [];
510
420
  const disableDirectives = [];
511
421
  const validator = new ConfigValidator({
512
422
  builtInRules: Rules,
@@ -542,14 +452,11 @@ function getDirectiveComments(
542
452
  const kind =
543
453
  comment.type === "Block" ? `/*${label}*/` : `//${label}`;
544
454
 
545
- problems.push(
546
- createLintingProblem({
547
- ruleId: null,
548
- message: `'${kind}' has no effect because you have 'noInlineConfig' setting in ${warnInlineConfig}.`,
549
- loc,
550
- severity: 1,
551
- }),
552
- );
455
+ report.addWarning({
456
+ ruleId: null,
457
+ message: `'${kind}' has no effect because you have 'noInlineConfig' setting in ${warnInlineConfig}.`,
458
+ loc,
459
+ });
553
460
  return;
554
461
  }
555
462
 
@@ -559,13 +466,10 @@ function getDirectiveComments(
559
466
  ) {
560
467
  const message = `${label} comment should not span multiple lines.`;
561
468
 
562
- problems.push(
563
- createLintingProblem({
564
- ruleId: null,
565
- message,
566
- loc,
567
- }),
568
- );
469
+ report.addError({
470
+ message,
471
+ loc,
472
+ });
569
473
  return;
570
474
  }
571
475
 
@@ -575,21 +479,20 @@ function getDirectiveComments(
575
479
  case "eslint-disable-next-line":
576
480
  case "eslint-disable-line": {
577
481
  const directiveType = label.slice("eslint-".length);
578
- const { directives, directiveProblems } =
579
- createDisableDirectives(
580
- {
581
- type: directiveType,
582
- value,
583
- justification: justificationPart,
584
- node: comment,
585
- },
586
- ruleMapper,
587
- jslang,
588
- sourceCode,
589
- );
482
+ const directives = createDisableDirectives(
483
+ {
484
+ type: directiveType,
485
+ value,
486
+ justification: justificationPart,
487
+ node: comment,
488
+ },
489
+ ruleMapper,
490
+ jslang,
491
+ sourceCode,
492
+ report,
493
+ );
590
494
 
591
495
  disableDirectives.push(...directives);
592
- problems.push(...directiveProblems);
593
496
  break;
594
497
  }
595
498
 
@@ -611,13 +514,10 @@ function getDirectiveComments(
611
514
  normalizedValue =
612
515
  ConfigOps.normalizeConfigGlobal(idSetting);
613
516
  } catch (err) {
614
- problems.push(
615
- createLintingProblem({
616
- ruleId: null,
617
- loc,
618
- message: err.message,
619
- }),
620
- );
517
+ report.addError({
518
+ loc,
519
+ message: err.message,
520
+ });
621
521
  continue;
622
522
  }
623
523
 
@@ -643,19 +543,15 @@ function getDirectiveComments(
643
543
  const ruleValue = parseResult.config[name];
644
544
 
645
545
  if (!rule) {
646
- problems.push(
647
- createLintingProblem({ ruleId: name, loc }),
648
- );
546
+ report.addError({ ruleId: name, loc });
649
547
  return;
650
548
  }
651
549
 
652
550
  if (Object.hasOwn(configuredRules, name)) {
653
- problems.push(
654
- createLintingProblem({
655
- message: `Rule "${name}" is already configured by another configuration comment in the preceding code. This configuration is ignored.`,
656
- loc,
657
- }),
658
- );
551
+ report.addError({
552
+ message: `Rule "${name}" is already configured by another configuration comment in the preceding code. This configuration is ignored.`,
553
+ loc,
554
+ });
659
555
  return;
660
556
  }
661
557
 
@@ -717,13 +613,11 @@ function getDirectiveComments(
717
613
  throw err;
718
614
  }
719
615
 
720
- problems.push(
721
- createLintingProblem({
722
- ruleId: name,
723
- message: err.message,
724
- loc,
725
- }),
726
- );
616
+ report.addError({
617
+ ruleId: name,
618
+ message: err.message,
619
+ loc,
620
+ });
727
621
 
728
622
  // do not apply the config, if found invalid options.
729
623
  return;
@@ -732,14 +626,10 @@ function getDirectiveComments(
732
626
  configuredRules[name] = ruleOptions;
733
627
  });
734
628
  } else {
735
- const problem = createLintingProblem({
736
- ruleId: null,
629
+ report.addFatal({
737
630
  loc,
738
631
  message: parseResult.error.message,
739
632
  });
740
-
741
- problem.fatal = true;
742
- problems.push(problem);
743
633
  }
744
634
 
745
635
  break;
@@ -753,7 +643,6 @@ function getDirectiveComments(
753
643
  configuredRules,
754
644
  enabledGlobals,
755
645
  exportedVariables,
756
- problems,
757
646
  disableDirectives,
758
647
  };
759
648
  }
@@ -763,43 +652,40 @@ function getDirectiveComments(
763
652
  * @param {SourceCode} sourceCode The SourceCode object to get comments from.
764
653
  * @param {function(string): {create: Function}} ruleMapper A map from rule IDs to defined rules
765
654
  * @param {Language} language The language to use to adjust the location information
766
- * @returns {{problems: LintMessage[], disableDirectives: DisableDirective[]}}
655
+ * @param {FileReport} report The report to add problems to.
656
+ * @returns {DisableDirective[]}
767
657
  * A collection of the directive comments that were found, along with any problems that occurred when parsing
768
658
  */
769
- function getDirectiveCommentsForFlatConfig(sourceCode, ruleMapper, language) {
659
+ function getDirectiveCommentsForFlatConfig(
660
+ sourceCode,
661
+ ruleMapper,
662
+ language,
663
+ report,
664
+ ) {
770
665
  const disableDirectives = [];
771
- const problems = [];
772
666
 
773
667
  if (sourceCode.getDisableDirectives) {
774
668
  const { directives: directivesSources, problems: directivesProblems } =
775
669
  sourceCode.getDisableDirectives();
776
670
 
777
- problems.push(
778
- ...directivesProblems.map(directiveProblem =>
779
- createLintingProblem({
780
- ...directiveProblem,
781
- language,
782
- }),
783
- ),
784
- );
671
+ if (Array.isArray(directivesProblems)) {
672
+ directivesProblems.forEach(problem => report.addError(problem));
673
+ }
785
674
 
786
675
  directivesSources.forEach(directive => {
787
- const { directives, directiveProblems } = createDisableDirectives(
676
+ const directives = createDisableDirectives(
788
677
  directive,
789
678
  ruleMapper,
790
679
  language,
791
680
  sourceCode,
681
+ report,
792
682
  );
793
683
 
794
684
  disableDirectives.push(...directives);
795
- problems.push(...directiveProblems);
796
685
  });
797
686
  }
798
687
 
799
- return {
800
- problems,
801
- disableDirectives,
802
- };
688
+ return disableDirectives;
803
689
  }
804
690
 
805
691
  /**
@@ -1149,13 +1035,13 @@ function createRuleListeners(rule, ruleContext) {
1149
1035
  * @param {Object} settings The settings that were enabled in the config
1150
1036
  * @param {string} filename The reported filename of the code
1151
1037
  * @param {boolean} applyDefaultOptions If true, apply rules' meta.defaultOptions in computing their config options.
1152
- * @param {boolean} disableFixes If true, it doesn't make `fix` properties.
1153
1038
  * @param {string | undefined} cwd cwd of the cli
1154
1039
  * @param {string} physicalFilename The full path of the file on disk without any code block information
1155
1040
  * @param {Function} ruleFilter A predicate function to filter which rules should be executed.
1156
1041
  * @param {boolean} stats If true, stats are collected appended to the result
1157
1042
  * @param {WeakMap<Linter, LinterInternalSlots>} slots InternalSlotsMap of linter
1158
- * @returns {LintMessage[]} An array of reported problems
1043
+ * @param {FileReport} report The report to add problems to
1044
+ * @returns {FileReport} report The report with added problems
1159
1045
  * @throws {Error} If traversal into a node fails.
1160
1046
  */
1161
1047
  function runRules(
@@ -1168,12 +1054,12 @@ function runRules(
1168
1054
  settings,
1169
1055
  filename,
1170
1056
  applyDefaultOptions,
1171
- disableFixes,
1172
1057
  cwd,
1173
1058
  physicalFilename,
1174
1059
  ruleFilter,
1175
1060
  stats,
1176
1061
  slots,
1062
+ report,
1177
1063
  ) {
1178
1064
  const visitor = new SourceCodeVisitor();
1179
1065
 
@@ -1195,7 +1081,6 @@ function runRules(
1195
1081
  settings,
1196
1082
  });
1197
1083
 
1198
- const lintingProblems = [];
1199
1084
  const steps = sourceCode.traverse();
1200
1085
 
1201
1086
  Object.keys(configuredRules).forEach(ruleId => {
@@ -1213,12 +1098,10 @@ function runRules(
1213
1098
  const rule = ruleMapper(ruleId);
1214
1099
 
1215
1100
  if (!rule) {
1216
- lintingProblems.push(createLintingProblem({ ruleId, language }));
1101
+ report.addError({ ruleId });
1217
1102
  return;
1218
1103
  }
1219
1104
 
1220
- const messageIds = rule.meta && rule.meta.messages;
1221
- let reportTranslator = null;
1222
1105
  const ruleContext = fileContext.extend({
1223
1106
  id: ruleId,
1224
1107
  options: getRuleOptions(
@@ -1226,33 +1109,18 @@ function runRules(
1226
1109
  applyDefaultOptions ? rule.meta?.defaultOptions : void 0,
1227
1110
  ),
1228
1111
  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);
1112
+ const problem = report.addRuleMessage(
1113
+ ruleId,
1114
+ severity,
1115
+ ...args,
1116
+ );
1250
1117
 
1251
1118
  if (problem.fix && !(rule.meta && rule.meta.fixable)) {
1252
1119
  throw new Error(
1253
1120
  'Fixable rules must set the `meta.fixable` property to "code" or "whitespace".',
1254
1121
  );
1255
1122
  }
1123
+
1256
1124
  if (
1257
1125
  problem.suggestions &&
1258
1126
  !(rule.meta && rule.meta.hasSuggestions === true)
@@ -1271,7 +1139,6 @@ function runRules(
1271
1139
  "Rules with suggestions must set the `meta.hasSuggestions` property to `true`.",
1272
1140
  );
1273
1141
  }
1274
- lintingProblems.push(problem);
1275
1142
  },
1276
1143
  });
1277
1144
 
@@ -1347,7 +1214,7 @@ function runRules(
1347
1214
 
1348
1215
  traverser.traverseSync(sourceCode, visitor, { steps });
1349
1216
 
1350
- return lintingProblems;
1217
+ return report;
1351
1218
  }
1352
1219
 
1353
1220
  /**
@@ -1636,18 +1503,25 @@ class Linter {
1636
1503
  }
1637
1504
 
1638
1505
  const sourceCode = slots.lastSourceCode;
1506
+ const report = new FileReport({
1507
+ ruleMapper: ruleId => getRule(slots, ruleId),
1508
+ language: jslang,
1509
+ sourceCode,
1510
+ disableFixes: options.disableFixes,
1511
+ });
1512
+
1639
1513
  const commentDirectives = options.allowInlineConfig
1640
1514
  ? getDirectiveComments(
1641
1515
  sourceCode,
1642
1516
  ruleId => getRule(slots, ruleId),
1643
1517
  options.warnInlineConfig,
1644
1518
  config,
1519
+ report,
1645
1520
  )
1646
1521
  : {
1647
1522
  configuredRules: {},
1648
1523
  enabledGlobals: {},
1649
1524
  exportedVariables: {},
1650
- problems: [],
1651
1525
  disableDirectives: [],
1652
1526
  };
1653
1527
 
@@ -1666,10 +1540,8 @@ class Linter {
1666
1540
  commentDirectives.configuredRules,
1667
1541
  );
1668
1542
 
1669
- let lintingProblems;
1670
-
1671
1543
  try {
1672
- lintingProblems = runRules(
1544
+ runRules(
1673
1545
  sourceCode,
1674
1546
  configuredRules,
1675
1547
  ruleId => getRule(slots, ruleId),
@@ -1679,12 +1551,12 @@ class Linter {
1679
1551
  settings,
1680
1552
  options.filename,
1681
1553
  true,
1682
- options.disableFixes,
1683
1554
  slots.cwd,
1684
1555
  providedOptions.physicalFilename,
1685
1556
  null,
1686
1557
  options.stats,
1687
1558
  slots,
1559
+ report,
1688
1560
  );
1689
1561
  } catch (err) {
1690
1562
  err.message += `\nOccurred while linting ${options.filename}`;
@@ -1712,13 +1584,11 @@ class Linter {
1712
1584
  sourceCode,
1713
1585
  directives: commentDirectives.disableDirectives,
1714
1586
  disableFixes: options.disableFixes,
1715
- problems: lintingProblems
1716
- .concat(commentDirectives.problems)
1717
- .sort(
1718
- (problemA, problemB) =>
1719
- problemA.line - problemB.line ||
1720
- problemA.column - problemB.column,
1721
- ),
1587
+ problems: report.messages.sort(
1588
+ (problemA, problemB) =>
1589
+ problemA.line - problemB.line ||
1590
+ problemA.column - problemB.column,
1591
+ ),
1722
1592
  reportUnusedDisableDirectives:
1723
1593
  options.reportUnusedDisableDirectives,
1724
1594
  });
@@ -2013,6 +1883,12 @@ class Linter {
2013
1883
  }
2014
1884
 
2015
1885
  const sourceCode = slots.lastSourceCode;
1886
+ const report = new FileReport({
1887
+ ruleMapper: ruleId => config.getRuleDefinition(ruleId),
1888
+ language: config.language,
1889
+ sourceCode,
1890
+ disableFixes: options.disableFixes,
1891
+ });
2016
1892
 
2017
1893
  /*
2018
1894
  * Make adjustments based on the language options. For JavaScript,
@@ -2024,7 +1900,6 @@ class Linter {
2024
1900
  const mergedInlineConfig = {
2025
1901
  rules: {},
2026
1902
  };
2027
- const inlineConfigProblems = [];
2028
1903
 
2029
1904
  /*
2030
1905
  * Inline config can be either enabled or disabled. If disabled, it's possible
@@ -2040,34 +1915,19 @@ class Linter {
2040
1915
  const loc = sourceCode.getLoc(node);
2041
1916
  const range = sourceCode.getRange(node);
2042
1917
 
2043
- inlineConfigProblems.push(
2044
- createLintingProblem({
2045
- ruleId: null,
2046
- message: `'${sourceCode.text.slice(range[0], range[1])}' has no effect because you have 'noInlineConfig' setting in ${options.warnInlineConfig}.`,
2047
- loc,
2048
- severity: 1,
2049
- language: config.language,
2050
- }),
2051
- );
1918
+ report.addWarning({
1919
+ message: `'${sourceCode.text.slice(range[0], range[1])}' has no effect because you have 'noInlineConfig' setting in ${options.warnInlineConfig}.`,
1920
+ loc,
1921
+ });
2052
1922
  });
2053
1923
  }
2054
1924
  } else {
2055
1925
  const inlineConfigResult = sourceCode.applyInlineConfig?.();
2056
1926
 
2057
1927
  if (inlineConfigResult) {
2058
- inlineConfigProblems.push(
2059
- ...inlineConfigResult.problems
2060
- .map(problem =>
2061
- createLintingProblem({
2062
- ...problem,
2063
- language: config.language,
2064
- }),
2065
- )
2066
- .map(problem => {
2067
- problem.fatal = true;
2068
- return problem;
2069
- }),
2070
- );
1928
+ inlineConfigResult.problems.forEach(problem => {
1929
+ report.addFatal(problem);
1930
+ });
2071
1931
 
2072
1932
  for (const {
2073
1933
  config: inlineConfig,
@@ -2078,26 +1938,20 @@ class Linter {
2078
1938
  const ruleValue = inlineConfig.rules[ruleId];
2079
1939
 
2080
1940
  if (!rule) {
2081
- inlineConfigProblems.push(
2082
- createLintingProblem({
2083
- ruleId,
2084
- loc,
2085
- language: config.language,
2086
- }),
2087
- );
1941
+ report.addError({
1942
+ ruleId,
1943
+ loc,
1944
+ });
2088
1945
  return;
2089
1946
  }
2090
1947
 
2091
1948
  if (
2092
1949
  Object.hasOwn(mergedInlineConfig.rules, ruleId)
2093
1950
  ) {
2094
- inlineConfigProblems.push(
2095
- createLintingProblem({
2096
- message: `Rule "${ruleId}" is already configured by another configuration comment in the preceding code. This configuration is ignored.`,
2097
- loc,
2098
- language: config.language,
2099
- }),
2100
- );
1951
+ report.addError({
1952
+ message: `Rule "${ruleId}" is already configured by another configuration comment in the preceding code. This configuration is ignored.`,
1953
+ loc,
1954
+ });
2101
1955
  return;
2102
1956
  }
2103
1957
 
@@ -2175,7 +2029,7 @@ class Linter {
2175
2029
  addProblemIfSameSeverityAndOptions(
2176
2030
  config,
2177
2031
  loc,
2178
- inlineConfigProblems,
2032
+ report,
2179
2033
  ruleId,
2180
2034
  ruleOptions,
2181
2035
  ruleOptionsInline,
@@ -2214,14 +2068,11 @@ class Linter {
2214
2068
  baseMessage += ` You passed "${ruleValue}".`;
2215
2069
  }
2216
2070
 
2217
- inlineConfigProblems.push(
2218
- createLintingProblem({
2219
- ruleId,
2220
- message: `Inline configuration for rule "${ruleId}" is invalid:\n\t${baseMessage}\n`,
2221
- loc,
2222
- language: config.language,
2223
- }),
2224
- );
2071
+ report.addError({
2072
+ ruleId,
2073
+ message: `Inline configuration for rule "${ruleId}" is invalid:\n\t${baseMessage}\n`,
2074
+ loc,
2075
+ });
2225
2076
  }
2226
2077
  });
2227
2078
  }
@@ -2235,8 +2086,9 @@ class Linter {
2235
2086
  sourceCode,
2236
2087
  ruleId => config.getRuleDefinition(ruleId),
2237
2088
  config.language,
2089
+ report,
2238
2090
  )
2239
- : { problems: [], disableDirectives: [] };
2091
+ : [];
2240
2092
 
2241
2093
  const configuredRules = Object.assign(
2242
2094
  {},
@@ -2244,12 +2096,10 @@ class Linter {
2244
2096
  mergedInlineConfig.rules,
2245
2097
  );
2246
2098
 
2247
- let lintingProblems;
2248
-
2249
2099
  sourceCode.finalize?.();
2250
2100
 
2251
2101
  try {
2252
- lintingProblems = runRules(
2102
+ runRules(
2253
2103
  sourceCode,
2254
2104
  configuredRules,
2255
2105
  ruleId => config.getRuleDefinition(ruleId),
@@ -2259,12 +2109,12 @@ class Linter {
2259
2109
  settings,
2260
2110
  options.filename,
2261
2111
  false,
2262
- options.disableFixes,
2263
2112
  slots.cwd,
2264
2113
  providedOptions.physicalFilename,
2265
2114
  options.ruleFilter,
2266
2115
  options.stats,
2267
2116
  slots,
2117
+ report,
2268
2118
  );
2269
2119
  } catch (err) {
2270
2120
  err.message += `\nOccurred while linting ${options.filename}`;
@@ -2291,16 +2141,13 @@ class Linter {
2291
2141
  return applyDisableDirectives({
2292
2142
  language: config.language,
2293
2143
  sourceCode,
2294
- directives: commentDirectives.disableDirectives,
2144
+ directives: commentDirectives,
2295
2145
  disableFixes: options.disableFixes,
2296
- problems: lintingProblems
2297
- .concat(commentDirectives.problems)
2298
- .concat(inlineConfigProblems)
2299
- .sort(
2300
- (problemA, problemB) =>
2301
- problemA.line - problemB.line ||
2302
- problemA.column - problemB.column,
2303
- ),
2146
+ problems: report.messages.sort(
2147
+ (problemA, problemB) =>
2148
+ problemA.line - problemB.line ||
2149
+ problemA.column - problemB.column,
2150
+ ),
2304
2151
  reportUnusedDisableDirectives:
2305
2152
  options.reportUnusedDisableDirectives,
2306
2153
  ruleFilter: options.ruleFilter,