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.
- package/README.md +2 -3
- package/lib/linter/{report-translator.js → file-report.js} +255 -61
- package/lib/linter/linter.js +140 -293
- package/lib/rules/accessor-pairs.js +35 -0
- package/lib/rules/grouped-accessor-pairs.js +36 -6
- package/lib/rules/no-await-in-loop.js +12 -1
- package/lib/rules/no-implied-eval.js +12 -2
- package/lib/rules/no-restricted-globals.js +131 -21
- package/lib/rules/no-unused-vars.js +27 -0
- package/lib/rules/one-var.js +63 -30
- package/lib/rules/prefer-destructuring.js +8 -0
- package/lib/rules/require-await.js +9 -0
- package/lib/rules/utils/ast-utils.js +27 -7
- package/lib/types/index.d.ts +12 -20
- package/lib/types/rules.d.ts +38 -9
- package/package.json +6 -7
package/README.md
CHANGED
@@ -324,12 +324,11 @@ Percy Ma
|
|
324
324
|
The following companies, organizations, and individuals support ESLint's ongoing maintenance and development. [Become a Sponsor](https://eslint.org/donate)
|
325
325
|
to get your logo on our READMEs and [website](https://eslint.org/sponsors).
|
326
326
|
|
327
|
-
<h3>
|
328
|
-
<p><a href="https://www.ag-grid.com/"><img src="https://images.opencollective.com/ag-grid/bec0580/logo.png" alt="AG Grid" height="128"></a></p><h3>Platinum Sponsors</h3>
|
327
|
+
<h3>Platinum Sponsors</h3>
|
329
328
|
<p><a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="128"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="128"></a></p><h3>Gold Sponsors</h3>
|
330
329
|
<p><a href="https://qlty.sh/"><img src="https://images.opencollective.com/qltysh/33d157d/logo.png" alt="Qlty Software" height="96"></a> <a href="https://trunk.io/"><img src="https://images.opencollective.com/trunkio/fb92d60/avatar.png" alt="trunk.io" height="96"></a> <a href="https://shopify.engineering/"><img src="https://avatars.githubusercontent.com/u/8085" alt="Shopify" height="96"></a></p><h3>Silver Sponsors</h3>
|
331
330
|
<p><a href="https://vite.dev/"><img src="https://images.opencollective.com/vite/e6d15e1/logo.png" alt="Vite" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a> <a href="https://americanexpress.io"><img src="https://avatars.githubusercontent.com/u/3853301" alt="American Express" height="64"></a> <a href="https://stackblitz.com"><img src="https://avatars.githubusercontent.com/u/28635252" alt="StackBlitz" height="64"></a></p><h3>Bronze Sponsors</h3>
|
332
|
-
<p><a href="https://cybozu.co.jp/"><img src="https://images.opencollective.com/cybozu/933e46d/logo.png" alt="Cybozu" height="32"></a> <a href="https://
|
331
|
+
<p><a href="https://cybozu.co.jp/"><img src="https://images.opencollective.com/cybozu/933e46d/logo.png" alt="Cybozu" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340" alt="GitBook" height="32"></a> <a href="https://nx.dev"><img src="https://avatars.githubusercontent.com/u/23692104" alt="Nx" height="32"></a> <a href="https://opensource.mercedes-benz.com/"><img src="https://avatars.githubusercontent.com/u/34240465" alt="Mercedes-Benz Group" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774" alt="HeroCoders" height="32"></a> <a href="https://www.lambdatest.com"><img src="https://avatars.githubusercontent.com/u/171592363" alt="LambdaTest" height="32"></a></p>
|
333
332
|
<h3>Technology Sponsors</h3>
|
334
333
|
Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.
|
335
334
|
<p><a href="https://netlify.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/netlify-icon.svg" alt="Netlify" height="32"></a> <a href="https://algolia.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/algolia-icon.svg" alt="Algolia" height="32"></a> <a href="https://1password.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/1password-icon.svg" alt="1Password" height="32"></a></p>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/**
|
2
|
-
* @fileoverview A
|
3
|
-
* @author
|
2
|
+
* @fileoverview A class to track messages reported by the linter for a file.
|
3
|
+
* @author Nicholas C. Zakas
|
4
4
|
*/
|
5
5
|
|
6
6
|
"use strict";
|
@@ -12,6 +12,7 @@
|
|
12
12
|
const assert = require("../shared/assert");
|
13
13
|
const { RuleFixer } = require("./rule-fixer");
|
14
14
|
const { interpolate } = require("./interpolate");
|
15
|
+
const ruleReplacements = require("../../conf/replacements.json");
|
15
16
|
|
16
17
|
//------------------------------------------------------------------------------
|
17
18
|
// Typedefs
|
@@ -19,6 +20,8 @@ const { interpolate } = require("./interpolate");
|
|
19
20
|
|
20
21
|
/** @typedef {import("../types").Linter.LintMessage} LintMessage */
|
21
22
|
/** @typedef {import("../types").Linter.LintSuggestion} SuggestionResult */
|
23
|
+
/** @typedef {import("@eslint/core").Language} Language */
|
24
|
+
/** @typedef {import("@eslint/core").SourceLocation} SourceLocation */
|
22
25
|
|
23
26
|
/**
|
24
27
|
* An error message description
|
@@ -32,10 +35,99 @@ const { interpolate } = require("./interpolate");
|
|
32
35
|
* @property {Array<{desc?: string, messageId?: string, fix: Function}>} suggest Suggestion descriptions and functions to create a the associated fixes.
|
33
36
|
*/
|
34
37
|
|
38
|
+
/**
|
39
|
+
* @typedef {Object} LintProblem
|
40
|
+
* @property {string} ruleId The rule ID that reported the problem.
|
41
|
+
* @property {string} message The problem message.
|
42
|
+
* @property {SourceLocation} loc The location of the problem.
|
43
|
+
*/
|
44
|
+
|
35
45
|
//------------------------------------------------------------------------------
|
36
|
-
//
|
46
|
+
// Helpers
|
37
47
|
//------------------------------------------------------------------------------
|
38
48
|
|
49
|
+
const DEFAULT_ERROR_LOC = {
|
50
|
+
start: { line: 1, column: 0 },
|
51
|
+
end: { line: 1, column: 1 },
|
52
|
+
};
|
53
|
+
|
54
|
+
/**
|
55
|
+
* Updates a given location based on the language offsets. This allows us to
|
56
|
+
* change 0-based locations to 1-based locations. We always want ESLint
|
57
|
+
* reporting lines and columns starting from 1.
|
58
|
+
* @todo Potentially this should be moved into a shared utility file.
|
59
|
+
* @param {Object} location The location to update.
|
60
|
+
* @param {number} location.line The starting line number.
|
61
|
+
* @param {number} location.column The starting column number.
|
62
|
+
* @param {number} [location.endLine] The ending line number.
|
63
|
+
* @param {number} [location.endColumn] The ending column number.
|
64
|
+
* @param {Language} language The language to use to adjust the location information.
|
65
|
+
* @returns {Object} The updated location.
|
66
|
+
*/
|
67
|
+
function updateLocationInformation(
|
68
|
+
{ line, column, endLine, endColumn },
|
69
|
+
language,
|
70
|
+
) {
|
71
|
+
const columnOffset = language.columnStart === 1 ? 0 : 1;
|
72
|
+
const lineOffset = language.lineStart === 1 ? 0 : 1;
|
73
|
+
|
74
|
+
// calculate separately to account for undefined
|
75
|
+
const finalEndLine = endLine === void 0 ? endLine : endLine + lineOffset;
|
76
|
+
const finalEndColumn =
|
77
|
+
endColumn === void 0 ? endColumn : endColumn + columnOffset;
|
78
|
+
|
79
|
+
return {
|
80
|
+
line: line + lineOffset,
|
81
|
+
column: column + columnOffset,
|
82
|
+
endLine: finalEndLine,
|
83
|
+
endColumn: finalEndColumn,
|
84
|
+
};
|
85
|
+
}
|
86
|
+
|
87
|
+
/**
|
88
|
+
* creates a missing-rule message.
|
89
|
+
* @param {string} ruleId the ruleId to create
|
90
|
+
* @returns {string} created error message
|
91
|
+
* @private
|
92
|
+
*/
|
93
|
+
function createMissingRuleMessage(ruleId) {
|
94
|
+
return Object.hasOwn(ruleReplacements.rules, ruleId)
|
95
|
+
? `Rule '${ruleId}' was removed and replaced by: ${ruleReplacements.rules[ruleId].join(", ")}`
|
96
|
+
: `Definition for rule '${ruleId}' was not found.`;
|
97
|
+
}
|
98
|
+
|
99
|
+
/**
|
100
|
+
* creates a linting problem
|
101
|
+
* @param {LintProblem} options to create linting error
|
102
|
+
* @param {RuleSeverity} severity the error message to report
|
103
|
+
* @param {Language} language the language to use to adjust the location information.
|
104
|
+
* @returns {LintMessage} created problem, returns a missing-rule problem if only provided ruleId.
|
105
|
+
* @private
|
106
|
+
*/
|
107
|
+
function createLintingProblem(options, severity, language) {
|
108
|
+
const {
|
109
|
+
ruleId = null,
|
110
|
+
loc = DEFAULT_ERROR_LOC,
|
111
|
+
message = createMissingRuleMessage(options.ruleId),
|
112
|
+
} = options;
|
113
|
+
|
114
|
+
return {
|
115
|
+
ruleId,
|
116
|
+
message,
|
117
|
+
...updateLocationInformation(
|
118
|
+
{
|
119
|
+
line: loc.start.line,
|
120
|
+
column: loc.start.column,
|
121
|
+
endLine: loc.end.line,
|
122
|
+
endColumn: loc.end.column,
|
123
|
+
},
|
124
|
+
language,
|
125
|
+
),
|
126
|
+
severity,
|
127
|
+
nodeType: null,
|
128
|
+
};
|
129
|
+
}
|
130
|
+
|
39
131
|
/**
|
40
132
|
* Translates a multi-argument context.report() call into a single object argument call
|
41
133
|
* @param {...*} args A list of arguments passed to `context.report`
|
@@ -342,73 +434,175 @@ function validateSuggestions(suggest, messages) {
|
|
342
434
|
}
|
343
435
|
|
344
436
|
/**
|
345
|
-
*
|
346
|
-
*
|
347
|
-
* @param {
|
348
|
-
* @returns {
|
437
|
+
* Computes the message from a report descriptor.
|
438
|
+
* @param {MessageDescriptor} descriptor The report descriptor.
|
439
|
+
* @param {Object} messages Object of meta messages for the rule.
|
440
|
+
* @returns {string} The computed message.
|
441
|
+
* @throws {TypeError} If messageId is not found or both message and messageId are provided.
|
349
442
|
*/
|
443
|
+
function computeMessageFromDescriptor(descriptor, messages) {
|
444
|
+
if (descriptor.messageId) {
|
445
|
+
if (!messages) {
|
446
|
+
throw new TypeError(
|
447
|
+
"context.report() called with a messageId, but no messages were present in the rule metadata.",
|
448
|
+
);
|
449
|
+
}
|
450
|
+
const id = descriptor.messageId;
|
350
451
|
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
452
|
+
if (descriptor.message) {
|
453
|
+
throw new TypeError(
|
454
|
+
"context.report() called with a message and a messageId. Please only pass one.",
|
455
|
+
);
|
456
|
+
}
|
457
|
+
if (!messages || !Object.hasOwn(messages, id)) {
|
458
|
+
throw new TypeError(
|
459
|
+
`context.report() called with a messageId of '${id}' which is not present in the 'messages' config: ${JSON.stringify(messages, null, 2)}`,
|
460
|
+
);
|
461
|
+
}
|
462
|
+
return messages[id];
|
463
|
+
}
|
464
|
+
|
465
|
+
if (descriptor.message) {
|
466
|
+
return descriptor.message;
|
467
|
+
}
|
468
|
+
|
469
|
+
throw new TypeError(
|
470
|
+
"Missing `message` property in report() call; add a message that describes the linting problem.",
|
471
|
+
);
|
472
|
+
}
|
473
|
+
|
474
|
+
/**
|
475
|
+
* A report object that contains the messages reported the linter
|
476
|
+
* for a file.
|
477
|
+
*/
|
478
|
+
class FileReport {
|
479
|
+
/**
|
480
|
+
* The messages reported by the linter for this file.
|
481
|
+
* @type {LintMessage[]}
|
482
|
+
*/
|
483
|
+
messages = [];
|
484
|
+
|
485
|
+
/**
|
486
|
+
* A rule mapper that maps rule IDs to their metadata.
|
487
|
+
* @type {(string) => RuleDefinition}
|
488
|
+
*/
|
489
|
+
#ruleMapper;
|
490
|
+
|
491
|
+
/**
|
492
|
+
* The source code object for the file.
|
493
|
+
* @type {SourceCode}
|
494
|
+
*/
|
495
|
+
#sourceCode;
|
496
|
+
|
497
|
+
/**
|
498
|
+
* The language to use to adjust line and column offsets.
|
499
|
+
* @type {Language}
|
500
|
+
*/
|
501
|
+
#language;
|
502
|
+
|
503
|
+
/**
|
504
|
+
* Whether to disable fixes for this report.
|
505
|
+
* @type {boolean}
|
357
506
|
*/
|
358
|
-
|
507
|
+
#disableFixes;
|
508
|
+
|
509
|
+
/**
|
510
|
+
* Creates a new FileReport instance.
|
511
|
+
* @param {Object} options The options for the file report
|
512
|
+
* @param {(string) => RuleDefinition} options.ruleMapper A rule mapper that maps rule IDs to their metadata.
|
513
|
+
* @param {SourceCode} options.sourceCode The source code object for the file.
|
514
|
+
* @param {Language} options.language The language to use to adjust line and column offsets.
|
515
|
+
* @param {boolean} [options.disableFixes=false] Whether to disable fixes for this report.
|
516
|
+
*/
|
517
|
+
constructor({ ruleMapper, sourceCode, language, disableFixes = false }) {
|
518
|
+
this.#ruleMapper = ruleMapper;
|
519
|
+
this.#sourceCode = sourceCode;
|
520
|
+
this.#language = language;
|
521
|
+
this.#disableFixes = disableFixes;
|
522
|
+
}
|
523
|
+
|
524
|
+
/**
|
525
|
+
* Adds a rule-generated message to the report.
|
526
|
+
* @param {string} ruleId The rule ID that reported the problem.
|
527
|
+
* @param {0|1|2} severity The severity of the problem (0 = off, 1 = warning, 2 = error).
|
528
|
+
* @param {...*} args The arguments passed to `context.report()`.
|
529
|
+
* @returns {LintMessage} The created message object.
|
530
|
+
* @throws {TypeError} If the messageId is not found or both message and messageId are provided.
|
531
|
+
* @throws {AssertionError} If the node is not an object or neither a node nor a loc is provided.
|
532
|
+
*/
|
533
|
+
addRuleMessage(ruleId, severity, ...args) {
|
359
534
|
const descriptor = normalizeMultiArgReportCall(...args);
|
360
|
-
const
|
361
|
-
const
|
535
|
+
const ruleDefinition = this.#ruleMapper(ruleId);
|
536
|
+
const messages = ruleDefinition?.meta?.messages;
|
362
537
|
|
363
538
|
assertValidNodeInfo(descriptor);
|
364
539
|
|
365
|
-
|
540
|
+
const computedMessage = computeMessageFromDescriptor(
|
541
|
+
descriptor,
|
542
|
+
messages,
|
543
|
+
);
|
366
544
|
|
367
|
-
|
368
|
-
if (!messages) {
|
369
|
-
throw new TypeError(
|
370
|
-
"context.report() called with a messageId, but no messages were present in the rule metadata.",
|
371
|
-
);
|
372
|
-
}
|
373
|
-
const id = descriptor.messageId;
|
545
|
+
validateSuggestions(descriptor.suggest, messages);
|
374
546
|
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
547
|
+
this.messages.push(
|
548
|
+
createProblem({
|
549
|
+
ruleId,
|
550
|
+
severity,
|
551
|
+
node: descriptor.node,
|
552
|
+
message: interpolate(computedMessage, descriptor.data),
|
553
|
+
messageId: descriptor.messageId,
|
554
|
+
loc: descriptor.loc
|
555
|
+
? normalizeReportLoc(descriptor)
|
556
|
+
: this.#sourceCode.getLoc(descriptor.node),
|
557
|
+
fix: this.#disableFixes
|
558
|
+
? null
|
559
|
+
: normalizeFixes(descriptor, this.#sourceCode),
|
560
|
+
suggestions: this.#disableFixes
|
561
|
+
? []
|
562
|
+
: mapSuggestions(descriptor, this.#sourceCode, messages),
|
563
|
+
language: this.#language,
|
564
|
+
}),
|
565
|
+
);
|
393
566
|
|
394
|
-
|
567
|
+
return this.messages.at(-1);
|
568
|
+
}
|
395
569
|
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
570
|
+
/**
|
571
|
+
* Adds an error message to the report. Meant to be called outside of rules.
|
572
|
+
* @param {LintProblem} descriptor The descriptor for the error message.
|
573
|
+
* @returns {LintMessage} The created message object.
|
574
|
+
*/
|
575
|
+
addError(descriptor) {
|
576
|
+
const message = createLintingProblem(descriptor, 2, this.#language);
|
577
|
+
this.messages.push(message);
|
578
|
+
return message;
|
579
|
+
}
|
580
|
+
|
581
|
+
/**
|
582
|
+
* Adds a fatal error message to the report. Meant to be called outside of rules.
|
583
|
+
* @param {LintProblem} descriptor The descriptor for the fatal error message.
|
584
|
+
* @returns {LintMessage} The created message object.
|
585
|
+
*/
|
586
|
+
addFatal(descriptor) {
|
587
|
+
const message = createLintingProblem(descriptor, 2, this.#language);
|
588
|
+
message.fatal = true;
|
589
|
+
this.messages.push(message);
|
590
|
+
return message;
|
591
|
+
}
|
592
|
+
|
593
|
+
/**
|
594
|
+
* Adds a warning message to the report. Meant to be called outside of rules.
|
595
|
+
* @param {LintProblem} descriptor The descriptor for the warning message.
|
596
|
+
* @returns {LintMessage} The created message object.
|
597
|
+
*/
|
598
|
+
addWarning(descriptor) {
|
599
|
+
const message = createLintingProblem(descriptor, 1, this.#language);
|
600
|
+
this.messages.push(message);
|
601
|
+
return message;
|
602
|
+
}
|
603
|
+
}
|
604
|
+
|
605
|
+
module.exports = {
|
606
|
+
FileReport,
|
607
|
+
updateLocationInformation,
|
414
608
|
};
|