eslint 8.7.0 → 8.8.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.
@@ -51,6 +51,7 @@ const validFixTypes = new Set(["directive", "problem", "suggestion", "layout"]);
51
51
  /** @typedef {import("../shared/types").ConfigData} ConfigData */
52
52
  /** @typedef {import("../shared/types").DeprecatedRuleInfo} DeprecatedRuleInfo */
53
53
  /** @typedef {import("../shared/types").LintMessage} LintMessage */
54
+ /** @typedef {import("../shared/types").SuppressedLintMessage} SuppressedLintMessage */
54
55
  /** @typedef {import("../shared/types").ParserOptions} ParserOptions */
55
56
  /** @typedef {import("../shared/types").Plugin} Plugin */
56
57
  /** @typedef {import("../shared/types").RuleConf} RuleConf */
@@ -91,6 +92,7 @@ const validFixTypes = new Set(["directive", "problem", "suggestion", "layout"]);
91
92
  * @typedef {Object} LintResult
92
93
  * @property {string} filePath The path to the file that was linted.
93
94
  * @property {LintMessage[]} messages All of the messages for the result.
95
+ * @property {SuppressedLintMessage[]} suppressedMessages All of the suppressed messages for the result.
94
96
  * @property {number} errorCount Number of errors for the result.
95
97
  * @property {number} fatalErrorCount Number of fatal errors for the result.
96
98
  * @property {number} warningCount Number of warnings for the result.
@@ -263,6 +265,7 @@ function verifyText({
263
265
  const result = {
264
266
  filePath,
265
267
  messages,
268
+ suppressedMessages: linter.getSuppressedMessages(),
266
269
  ...calculateStatsPerFile(messages)
267
270
  };
268
271
 
@@ -309,6 +312,7 @@ function createIgnoreResult(filePath, baseDir) {
309
312
  message
310
313
  }
311
314
  ],
315
+ suppressedMessages: [],
312
316
  errorCount: 0,
313
317
  fatalErrorCount: 0,
314
318
  warningCount: 1,
@@ -683,11 +687,13 @@ class CLIEngine {
683
687
 
684
688
  results.forEach(result => {
685
689
  const filteredMessages = result.messages.filter(isErrorMessage);
690
+ const filteredSuppressedMessages = result.suppressedMessages.filter(isErrorMessage);
686
691
 
687
692
  if (filteredMessages.length > 0) {
688
693
  filtered.push({
689
694
  ...result,
690
695
  messages: filteredMessages,
696
+ suppressedMessages: filteredSuppressedMessages,
691
697
  errorCount: filteredMessages.length,
692
698
  warningCount: 0,
693
699
  fixableErrorCount: result.fixableErrorCount,
@@ -32,6 +32,7 @@ const { version } = require("../../package.json");
32
32
  /** @typedef {import("../shared/types").DeprecatedRuleInfo} DeprecatedRuleInfo */
33
33
  /** @typedef {import("../shared/types").ConfigData} ConfigData */
34
34
  /** @typedef {import("../shared/types").LintMessage} LintMessage */
35
+ /** @typedef {import("../shared/types").SuppressedLintMessage} SuppressedLintMessage */
35
36
  /** @typedef {import("../shared/types").Plugin} Plugin */
36
37
  /** @typedef {import("../shared/types").Rule} Rule */
37
38
 
@@ -78,6 +79,7 @@ const { version } = require("../../package.json");
78
79
  * @typedef {Object} LintResult
79
80
  * @property {string} filePath The path to the file that was linted.
80
81
  * @property {LintMessage[]} messages All of the messages for the result.
82
+ * @property {SuppressedLintMessage[]} suppressedMessages All of the suppressed messages for the result.
81
83
  * @property {number} errorCount Number of errors for the result.
82
84
  * @property {number} fatalErrorCount Number of fatal errors for the result.
83
85
  * @property {number} warningCount Number of warnings for the result.
@@ -526,6 +528,9 @@ class ESLint {
526
528
  for (const { ruleId } of result.messages) {
527
529
  resultRuleIds.add(ruleId);
528
530
  }
531
+ for (const { ruleId } of result.suppressedMessages) {
532
+ resultRuleIds.add(ruleId);
533
+ }
529
534
  }
530
535
 
531
536
  // create a map of all rules in the results
@@ -197,62 +197,52 @@ function processUnusedDisableDirectives(allDirectives) {
197
197
  * for the exported function, except that `reportUnusedDisableDirectives` is not supported
198
198
  * (this function always reports unused disable directives).
199
199
  * @returns {{problems: Problem[], unusedDisableDirectives: Problem[]}} An object with a list
200
- * of filtered problems and unused eslint-disable directives
200
+ * of problems (including suppressed ones) and unused eslint-disable directives
201
201
  */
202
202
  function applyDirectives(options) {
203
203
  const problems = [];
204
- let nextDirectiveIndex = 0;
205
- let currentGlobalDisableDirective = null;
206
- const disabledRuleMap = new Map();
207
-
208
- // enabledRules is only used when there is a current global disable directive.
209
- const enabledRules = new Set();
210
204
  const usedDisableDirectives = new Set();
211
205
 
212
206
  for (const problem of options.problems) {
207
+ let disableDirectivesForProblem = [];
208
+ let nextDirectiveIndex = 0;
209
+
213
210
  while (
214
211
  nextDirectiveIndex < options.directives.length &&
215
212
  compareLocations(options.directives[nextDirectiveIndex], problem) <= 0
216
213
  ) {
217
214
  const directive = options.directives[nextDirectiveIndex++];
218
215
 
219
- switch (directive.type) {
220
- case "disable":
221
- if (directive.ruleId === null) {
222
- currentGlobalDisableDirective = directive;
223
- disabledRuleMap.clear();
224
- enabledRules.clear();
225
- } else if (currentGlobalDisableDirective) {
226
- enabledRules.delete(directive.ruleId);
227
- disabledRuleMap.set(directive.ruleId, directive);
228
- } else {
229
- disabledRuleMap.set(directive.ruleId, directive);
230
- }
231
- break;
232
-
233
- case "enable":
234
- if (directive.ruleId === null) {
235
- currentGlobalDisableDirective = null;
236
- disabledRuleMap.clear();
237
- } else if (currentGlobalDisableDirective) {
238
- enabledRules.add(directive.ruleId);
239
- disabledRuleMap.delete(directive.ruleId);
240
- } else {
241
- disabledRuleMap.delete(directive.ruleId);
242
- }
243
- break;
244
-
245
- // no default
216
+ if (directive.ruleId === null || directive.ruleId === problem.ruleId) {
217
+ switch (directive.type) {
218
+ case "disable":
219
+ disableDirectivesForProblem.push(directive);
220
+ break;
221
+
222
+ case "enable":
223
+ disableDirectivesForProblem = [];
224
+ break;
225
+
226
+ // no default
227
+ }
246
228
  }
247
229
  }
248
230
 
249
- if (disabledRuleMap.has(problem.ruleId)) {
250
- usedDisableDirectives.add(disabledRuleMap.get(problem.ruleId));
251
- } else if (currentGlobalDisableDirective && !enabledRules.has(problem.ruleId)) {
252
- usedDisableDirectives.add(currentGlobalDisableDirective);
253
- } else {
254
- problems.push(problem);
231
+ if (disableDirectivesForProblem.length > 0) {
232
+ const suppressions = disableDirectivesForProblem.map(directive => ({
233
+ kind: "directive",
234
+ justification: directive.unprocessedDirective.justification
235
+ }));
236
+
237
+ if (problem.suppressions) {
238
+ problem.suppressions = problem.suppressions.concat(suppressions);
239
+ } else {
240
+ problem.suppressions = suppressions;
241
+ usedDisableDirectives.add(disableDirectivesForProblem[disableDirectivesForProblem.length - 1]);
242
+ }
255
243
  }
244
+
245
+ problems.push(problem);
256
246
  }
257
247
 
258
248
  const unusedDisableDirectivesToReport = options.directives
@@ -282,13 +272,14 @@ function applyDirectives(options) {
282
272
 
283
273
  /**
284
274
  * Given a list of directive comments (i.e. metadata about eslint-disable and eslint-enable comments) and a list
285
- * of reported problems, determines which problems should be reported.
275
+ * of reported problems, adds the suppression information to the problems.
286
276
  * @param {Object} options Information about directives and problems
287
277
  * @param {{
288
278
  * type: ("disable"|"enable"|"disable-line"|"disable-next-line"),
289
279
  * ruleId: (string|null),
290
280
  * line: number,
291
- * column: number
281
+ * column: number,
282
+ * justification: string
292
283
  * }} options.directives Directive comments found in the file, with one-based columns.
293
284
  * Two directive comments can only have the same location if they also have the same type (e.g. a single eslint-disable
294
285
  * comment for two different rules is represented as two directives).
@@ -296,8 +287,8 @@ function applyDirectives(options) {
296
287
  * A list of problems reported by rules, sorted by increasing location in the file, with one-based columns.
297
288
  * @param {"off" | "warn" | "error"} options.reportUnusedDisableDirectives If `"warn"` or `"error"`, adds additional problems for unused directives
298
289
  * @param {boolean} options.disableFixes If true, it doesn't make `fix` properties.
299
- * @returns {{ruleId: (string|null), line: number, column: number}[]}
300
- * A list of reported problems that were not disabled by the directive comments.
290
+ * @returns {{ruleId: (string|null), line: number, column: number, suppressions?: {kind: string, justification: string}}[]}
291
+ * An object with a list of reported problems, the suppressed of which contain the suppression information.
301
292
  */
302
293
  module.exports = ({ directives, disableFixes, problems, reportUnusedDisableDirectives = "off" }) => {
303
294
  const blockDirectives = directives
@@ -59,6 +59,7 @@ const globals = require("../../conf/globals");
59
59
  /** @typedef {import("../shared/types").Environment} Environment */
60
60
  /** @typedef {import("../shared/types").GlobalConf} GlobalConf */
61
61
  /** @typedef {import("../shared/types").LintMessage} LintMessage */
62
+ /** @typedef {import("../shared/types").SuppressedLintMessage} SuppressedLintMessage */
62
63
  /** @typedef {import("../shared/types").ParserOptions} ParserOptions */
63
64
  /** @typedef {import("../shared/types").LanguageOptions} LanguageOptions */
64
65
  /** @typedef {import("../shared/types").Processor} Processor */
@@ -77,6 +78,7 @@ const globals = require("../../conf/globals");
77
78
  * @property {number} line The line number
78
79
  * @property {number} column The column number
79
80
  * @property {(string|null)} ruleId The rule ID
81
+ * @property {string} justification The justification of directive
80
82
  */
81
83
 
82
84
  /**
@@ -84,6 +86,7 @@ const globals = require("../../conf/globals");
84
86
  * @typedef {Object} LinterInternalSlots
85
87
  * @property {ConfigArray|null} lastConfigArray The `ConfigArray` instance that the last `verify()` call used.
86
88
  * @property {SourceCode|null} lastSourceCode The `SourceCode` instance that the last `verify()` call used.
89
+ * @property {SuppressedLintMessage[]} lastSuppressedMessages The `SuppressedLintMessage[]` instance that the last `verify()` call produced.
87
90
  * @property {Map<string, Parser>} parserMap The loaded parsers.
88
91
  * @property {Rules} ruleMap The loaded rules.
89
92
  */
@@ -287,11 +290,12 @@ function createLintingProblem(options) {
287
290
  * @param {token} options.commentToken The Comment token
288
291
  * @param {string} options.value The value after the directive in the comment
289
292
  * comment specified no specific rules, so it applies to all rules (e.g. `eslint-disable`)
293
+ * @param {string} options.justification The justification of the directive
290
294
  * @param {function(string): {create: Function}} options.ruleMapper A map from rule IDs to defined rules
291
295
  * @returns {Object} Directives and problems from the comment
292
296
  */
293
297
  function createDisableDirectives(options) {
294
- const { commentToken, type, value, ruleMapper } = options;
298
+ const { commentToken, type, value, justification, ruleMapper } = options;
295
299
  const ruleIds = Object.keys(commentParser.parseListConfig(value));
296
300
  const directiveRules = ruleIds.length ? ruleIds : [null];
297
301
  const result = {
@@ -306,9 +310,23 @@ function createDisableDirectives(options) {
306
310
  // push to directives, if the rule is defined(including null, e.g. /*eslint enable*/)
307
311
  if (ruleId === null || !!ruleMapper(ruleId)) {
308
312
  if (type === "disable-next-line") {
309
- result.directives.push({ parentComment, type, line: commentToken.loc.end.line, column: commentToken.loc.end.column + 1, ruleId });
313
+ result.directives.push({
314
+ parentComment,
315
+ type,
316
+ line: commentToken.loc.end.line,
317
+ column: commentToken.loc.end.column + 1,
318
+ ruleId,
319
+ justification
320
+ });
310
321
  } else {
311
- result.directives.push({ parentComment, type, line: commentToken.loc.start.line, column: commentToken.loc.start.column + 1, ruleId });
322
+ result.directives.push({
323
+ parentComment,
324
+ type,
325
+ line: commentToken.loc.start.line,
326
+ column: commentToken.loc.start.column + 1,
327
+ ruleId,
328
+ justification
329
+ });
312
330
  }
313
331
  } else {
314
332
  result.directiveProblems.push(createLintingProblem({ ruleId, loc: commentToken.loc }));
@@ -318,12 +336,21 @@ function createDisableDirectives(options) {
318
336
  }
319
337
 
320
338
  /**
321
- * Remove the ignored part from a given directive comment and trim it.
322
- * @param {string} value The comment text to strip.
323
- * @returns {string} The stripped text.
339
+ * Extract the directive and the justification from a given directive comment and trim them.
340
+ * @param {string} value The comment text to extract.
341
+ * @returns {{directivePart: string, justificationPart: string}} The extracted directive and justification.
324
342
  */
325
- function stripDirectiveComment(value) {
326
- return value.split(/\s-{2,}\s/u)[0].trim();
343
+ function extractDirectiveComment(value) {
344
+ const match = /\s-{2,}\s/u.exec(value);
345
+
346
+ if (!match) {
347
+ return { directivePart: value.trim(), justificationPart: "" };
348
+ }
349
+
350
+ const directive = value.slice(0, match.index).trim();
351
+ const justification = value.slice(match.index + match[0].length).trim();
352
+
353
+ return { directivePart: directive, justificationPart: justification };
327
354
  }
328
355
 
329
356
  /**
@@ -347,8 +374,9 @@ function getDirectiveComments(ast, ruleMapper, warnInlineConfig) {
347
374
  });
348
375
 
349
376
  ast.comments.filter(token => token.type !== "Shebang").forEach(comment => {
350
- const trimmedCommentText = stripDirectiveComment(comment.value);
351
- const match = /^(eslint(?:-env|-enable|-disable(?:(?:-next)?-line)?)?|exported|globals?)(?:\s|$)/u.exec(trimmedCommentText);
377
+ const { directivePart, justificationPart } = extractDirectiveComment(comment.value);
378
+
379
+ const match = /^(eslint(?:-env|-enable|-disable(?:(?:-next)?-line)?)?|exported|globals?)(?:\s|$)/u.exec(directivePart);
352
380
 
353
381
  if (!match) {
354
382
  return;
@@ -383,7 +411,7 @@ function getDirectiveComments(ast, ruleMapper, warnInlineConfig) {
383
411
  return;
384
412
  }
385
413
 
386
- const directiveValue = trimmedCommentText.slice(match.index + directiveText.length);
414
+ const directiveValue = directivePart.slice(match.index + directiveText.length);
387
415
 
388
416
  switch (directiveText) {
389
417
  case "eslint-disable":
@@ -391,7 +419,7 @@ function getDirectiveComments(ast, ruleMapper, warnInlineConfig) {
391
419
  case "eslint-disable-next-line":
392
420
  case "eslint-disable-line": {
393
421
  const directiveType = directiveText.slice("eslint-".length);
394
- const options = { commentToken: comment, type: directiveType, value: directiveValue, ruleMapper };
422
+ const options = { commentToken: comment, type: directiveType, value: directiveValue, justification: justificationPart, ruleMapper };
395
423
  const { directives, directiveProblems } = createDisableDirectives(options);
396
424
 
397
425
  disableDirectives.push(...directives);
@@ -548,7 +576,7 @@ function findEslintEnv(text) {
548
576
  if (match[0].endsWith("*/")) {
549
577
  retv = Object.assign(
550
578
  retv || {},
551
- commentParser.parseListConfig(stripDirectiveComment(match[1]))
579
+ commentParser.parseListConfig(extractDirectiveComment(match[1]).directivePart)
552
580
  );
553
581
  }
554
582
  }
@@ -1223,6 +1251,7 @@ class Linter {
1223
1251
  cwd: normalizeCwd(cwd),
1224
1252
  lastConfigArray: null,
1225
1253
  lastSourceCode: null,
1254
+ lastSuppressedMessages: [],
1226
1255
  configType, // TODO: Remove after flat config conversion
1227
1256
  parserMap: new Map([["espree", espree]]),
1228
1257
  ruleMap: new Rules()
@@ -1246,7 +1275,7 @@ class Linter {
1246
1275
  * @param {ConfigData} providedConfig An ESLintConfig instance to configure everything.
1247
1276
  * @param {VerifyOptions} [providedOptions] The optional filename of the file being checked.
1248
1277
  * @throws {Error} If during rule execution.
1249
- * @returns {LintMessage[]} The results as an array of messages or an empty array if no messages.
1278
+ * @returns {(LintMessage|SuppressedLintMessage)[]} The results as an array of messages or an empty array if no messages.
1250
1279
  */
1251
1280
  _verifyWithoutProcessors(textOrSourceCode, providedConfig, providedOptions) {
1252
1281
  const slots = internalSlotsMap.get(this);
@@ -1428,11 +1457,11 @@ class Linter {
1428
1457
  configArray.normalizeSync();
1429
1458
  }
1430
1459
 
1431
- return this._verifyWithFlatConfigArray(textOrSourceCode, configArray, options, true);
1460
+ return this._distinguishSuppressedMessages(this._verifyWithFlatConfigArray(textOrSourceCode, configArray, options, true));
1432
1461
  }
1433
1462
 
1434
1463
  if (typeof config.extractConfig === "function") {
1435
- return this._verifyWithConfigArray(textOrSourceCode, config, options);
1464
+ return this._distinguishSuppressedMessages(this._verifyWithConfigArray(textOrSourceCode, config, options));
1436
1465
  }
1437
1466
  }
1438
1467
 
@@ -1446,9 +1475,9 @@ class Linter {
1446
1475
  * So we cannot apply multiple processors.
1447
1476
  */
1448
1477
  if (options.preprocess || options.postprocess) {
1449
- return this._verifyWithProcessor(textOrSourceCode, config, options);
1478
+ return this._distinguishSuppressedMessages(this._verifyWithProcessor(textOrSourceCode, config, options));
1450
1479
  }
1451
- return this._verifyWithoutProcessors(textOrSourceCode, config, options);
1480
+ return this._distinguishSuppressedMessages(this._verifyWithoutProcessors(textOrSourceCode, config, options));
1452
1481
  }
1453
1482
 
1454
1483
  /**
@@ -1457,7 +1486,7 @@ class Linter {
1457
1486
  * @param {FlatConfig} config The config array.
1458
1487
  * @param {VerifyOptions&ProcessorOptions} options The options.
1459
1488
  * @param {FlatConfigArray} [configForRecursive] The `ConfigArray` object to apply multiple processors recursively.
1460
- * @returns {LintMessage[]} The found problems.
1489
+ * @returns {(LintMessage|SuppressedLintMessage)[]} The found problems.
1461
1490
  */
1462
1491
  _verifyWithFlatConfigArrayAndProcessor(textOrSourceCode, config, options, configForRecursive) {
1463
1492
  const filename = options.filename || "<input>";
@@ -1514,7 +1543,7 @@ class Linter {
1514
1543
  * @param {FlatConfig} providedConfig An ESLintConfig instance to configure everything.
1515
1544
  * @param {VerifyOptions} [providedOptions] The optional filename of the file being checked.
1516
1545
  * @throws {Error} If during rule execution.
1517
- * @returns {LintMessage[]} The results as an array of messages or an empty array if no messages.
1546
+ * @returns {(LintMessage|SuppressedLintMessage)[]} The results as an array of messages or an empty array if no messages.
1518
1547
  */
1519
1548
  _verifyWithFlatConfigArrayAndWithoutProcessors(textOrSourceCode, providedConfig, providedOptions) {
1520
1549
  const slots = internalSlotsMap.get(this);
@@ -1663,7 +1692,7 @@ class Linter {
1663
1692
  * @param {string|SourceCode} textOrSourceCode The source code.
1664
1693
  * @param {ConfigArray} configArray The config array.
1665
1694
  * @param {VerifyOptions&ProcessorOptions} options The options.
1666
- * @returns {LintMessage[]} The found problems.
1695
+ * @returns {(LintMessage|SuppressedLintMessage)[]} The found problems.
1667
1696
  */
1668
1697
  _verifyWithConfigArray(textOrSourceCode, configArray, options) {
1669
1698
  debug("With ConfigArray: %s", options.filename);
@@ -1700,7 +1729,7 @@ class Linter {
1700
1729
  * @param {VerifyOptions&ProcessorOptions} options The options.
1701
1730
  * @param {boolean} [firstCall=false] Indicates if this is being called directly
1702
1731
  * from verify(). (TODO: Remove once eslintrc is removed.)
1703
- * @returns {LintMessage[]} The found problems.
1732
+ * @returns {(LintMessage|SuppressedLintMessage)[]} The found problems.
1704
1733
  */
1705
1734
  _verifyWithFlatConfigArray(textOrSourceCode, configArray, options, firstCall = false) {
1706
1735
  debug("With flat config: %s", options.filename);
@@ -1740,7 +1769,7 @@ class Linter {
1740
1769
  * @param {ConfigData|ExtractedConfig} config The config array.
1741
1770
  * @param {VerifyOptions&ProcessorOptions} options The options.
1742
1771
  * @param {ConfigArray} [configForRecursive] The `ConfigArray` object to apply multiple processors recursively.
1743
- * @returns {LintMessage[]} The found problems.
1772
+ * @returns {(LintMessage|SuppressedLintMessage)[]} The found problems.
1744
1773
  */
1745
1774
  _verifyWithProcessor(textOrSourceCode, config, options, configForRecursive) {
1746
1775
  const filename = options.filename || "<input>";
@@ -1792,6 +1821,30 @@ class Linter {
1792
1821
  return postprocess(messageLists, filenameToExpose);
1793
1822
  }
1794
1823
 
1824
+ /**
1825
+ * Given a list of reported problems, distinguish problems between normal messages and suppressed messages.
1826
+ * The normal messages will be returned and the suppressed messages will be stored as lastSuppressedMessages.
1827
+ * @param {Problem[]} problems A list of reported problems.
1828
+ * @returns {LintMessage[]} A list of LintMessage.
1829
+ */
1830
+ _distinguishSuppressedMessages(problems) {
1831
+ const messages = [];
1832
+ const suppressedMessages = [];
1833
+ const slots = internalSlotsMap.get(this);
1834
+
1835
+ for (const problem of problems) {
1836
+ if (problem.suppressions) {
1837
+ suppressedMessages.push(problem);
1838
+ } else {
1839
+ messages.push(problem);
1840
+ }
1841
+ }
1842
+
1843
+ slots.lastSuppressedMessages = suppressedMessages;
1844
+
1845
+ return messages;
1846
+ }
1847
+
1795
1848
  /**
1796
1849
  * Gets the SourceCode object representing the parsed source.
1797
1850
  * @returns {SourceCode} The SourceCode object.
@@ -1800,6 +1853,14 @@ class Linter {
1800
1853
  return internalSlotsMap.get(this).lastSourceCode;
1801
1854
  }
1802
1855
 
1856
+ /**
1857
+ * Gets the list of SuppressedLintMessage produced in the last running.
1858
+ * @returns {SuppressedLintMessage[]} The list of SuppressedLintMessage
1859
+ */
1860
+ getSuppressedMessages() {
1861
+ return internalSlotsMap.get(this).lastSuppressedMessages;
1862
+ }
1863
+
1803
1864
  /**
1804
1865
  * Defines a new linting rule.
1805
1866
  * @param {string} ruleId A unique rule identifier
@@ -105,6 +105,21 @@ module.exports = {};
105
105
  * @property {Array<{desc?: string, messageId?: string, fix: {range: [number, number], text: string}}>} [suggestions] Information for suggestions.
106
106
  */
107
107
 
108
+ /**
109
+ * @typedef {Object} SuppressedLintMessage
110
+ * @property {number|undefined} column The 1-based column number.
111
+ * @property {number} [endColumn] The 1-based column number of the end location.
112
+ * @property {number} [endLine] The 1-based line number of the end location.
113
+ * @property {boolean} fatal If `true` then this is a fatal error.
114
+ * @property {{range:[number,number], text:string}} [fix] Information for autofix.
115
+ * @property {number|undefined} line The 1-based line number.
116
+ * @property {string} message The error message.
117
+ * @property {string|null} ruleId The ID of the rule which makes this message.
118
+ * @property {0|1|2} severity The severity of this message.
119
+ * @property {Array<{kind: string, justification: string}>} suppressions The suppression info.
120
+ * @property {Array<{desc?: string, messageId?: string, fix: {range: [number, number], text: string}}>} [suggestions] Information for suggestions.
121
+ */
122
+
108
123
  /**
109
124
  * @typedef {Object} SuggestionResult
110
125
  * @property {string} desc A short description.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint",
3
- "version": "8.7.0",
3
+ "version": "8.8.0",
4
4
  "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
5
5
  "description": "An AST-based pattern checker for JavaScript.",
6
6
  "bin": {