eslint 9.7.0 → 9.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.
- package/lib/cli.js +0 -20
- package/lib/languages/js/source-code/source-code.js +19 -0
- package/lib/linter/apply-disable-directives.js +24 -12
- package/lib/linter/linter.js +44 -20
- package/lib/linter/report-translator.js +10 -10
- package/lib/linter/rule-fixer.js +38 -15
- package/lib/shared/flags.js +2 -2
- package/package.json +5 -4
package/lib/cli.js
CHANGED
@@ -26,7 +26,6 @@ const fs = require("node:fs"),
|
|
26
26
|
{ normalizeSeverityToString } = require("./shared/severity");
|
27
27
|
const { Legacy: { naming } } = require("@eslint/eslintrc");
|
28
28
|
const { ModuleImporter } = require("@humanwhocodes/module-importer");
|
29
|
-
const { inactiveFlags, activeFlags } = require("./shared/flags");
|
30
29
|
const debug = require("debug")("eslint:cli");
|
31
30
|
|
32
31
|
//------------------------------------------------------------------------------
|
@@ -488,25 +487,6 @@ const cli = {
|
|
488
487
|
|
489
488
|
const ActiveESLint = usingFlatConfig ? ESLint : LegacyESLint;
|
490
489
|
const eslintOptions = await translateOptions(options, usingFlatConfig ? "flat" : "eslintrc");
|
491
|
-
|
492
|
-
if (eslintOptions.flags) {
|
493
|
-
debug("Checking for inactive flags");
|
494
|
-
|
495
|
-
for (const flag of eslintOptions.flags) {
|
496
|
-
if (inactiveFlags.has(flag)) {
|
497
|
-
log.warn(`InactiveFlag: The '${flag}' flag is no longer active: ${inactiveFlags.get(flag)}`);
|
498
|
-
continue;
|
499
|
-
}
|
500
|
-
|
501
|
-
if (activeFlags.has(flag)) {
|
502
|
-
continue;
|
503
|
-
}
|
504
|
-
|
505
|
-
log.error(`InvalidFlag: The '${flag}' flag is invalid.`);
|
506
|
-
return 2;
|
507
|
-
}
|
508
|
-
}
|
509
|
-
|
510
490
|
const engine = new ActiveESLint(eslintOptions);
|
511
491
|
let results;
|
512
492
|
|
@@ -916,6 +916,25 @@ class SourceCode extends TokenStore {
|
|
916
916
|
|
917
917
|
return ancestorsStartingAtParent.reverse();
|
918
918
|
}
|
919
|
+
|
920
|
+
/**
|
921
|
+
* Returns the locatin of the given node or token.
|
922
|
+
* @param {ASTNode|Token} nodeOrToken The node or token to get the location of.
|
923
|
+
* @returns {SourceLocation} The location of the node or token.
|
924
|
+
*/
|
925
|
+
getLoc(nodeOrToken) {
|
926
|
+
return nodeOrToken.loc;
|
927
|
+
}
|
928
|
+
|
929
|
+
/**
|
930
|
+
* Returns the range of the given node or token.
|
931
|
+
* @param {ASTNode|Token} nodeOrToken The node or token to get the range of.
|
932
|
+
* @returns {[number, number]} The range of the node or token.
|
933
|
+
*/
|
934
|
+
getRange(nodeOrToken) {
|
935
|
+
return nodeOrToken.range;
|
936
|
+
}
|
937
|
+
|
919
938
|
/* eslint-enable class-methods-use-this -- node is owned by SourceCode */
|
920
939
|
|
921
940
|
/**
|
@@ -61,15 +61,18 @@ function groupByParentDirective(directives) {
|
|
61
61
|
* Creates removal details for a set of directives within the same comment.
|
62
62
|
* @param {Directive[]} directives Unused directives to be removed.
|
63
63
|
* @param {Token} node The backing Comment token.
|
64
|
+
* @param {SourceCode} sourceCode The source code object for the file being linted.
|
64
65
|
* @returns {{ description, fix, unprocessedDirective }[]} Details for later creation of output Problems.
|
65
66
|
*/
|
66
|
-
function createIndividualDirectivesRemoval(directives, node) {
|
67
|
+
function createIndividualDirectivesRemoval(directives, node, sourceCode) {
|
68
|
+
|
69
|
+
const range = sourceCode.getRange(node);
|
67
70
|
|
68
71
|
/*
|
69
72
|
* `node.value` starts right after `//` or `/*`.
|
70
73
|
* All calculated offsets will be relative to this index.
|
71
74
|
*/
|
72
|
-
const commentValueStart =
|
75
|
+
const commentValueStart = range[0] + "//".length;
|
73
76
|
|
74
77
|
// Find where the list of rules starts. `\S+` matches with the directive name (e.g. `eslint-disable-line`)
|
75
78
|
const listStartOffset = /^\s*\S+\s+/u.exec(node.value)[0].length;
|
@@ -165,10 +168,11 @@ function createIndividualDirectivesRemoval(directives, node) {
|
|
165
168
|
* Creates a description of deleting an entire unused disable directive.
|
166
169
|
* @param {Directive[]} directives Unused directives to be removed.
|
167
170
|
* @param {Token} node The backing Comment token.
|
171
|
+
* @param {SourceCode} sourceCode The source code object for the file being linted.
|
168
172
|
* @returns {{ description, fix, unprocessedDirective }} Details for later creation of an output problem.
|
169
173
|
*/
|
170
|
-
function createDirectiveRemoval(directives, node) {
|
171
|
-
const
|
174
|
+
function createDirectiveRemoval(directives, node, sourceCode) {
|
175
|
+
const range = sourceCode.getRange(node);
|
172
176
|
const ruleIds = directives.filter(directive => directive.ruleId).map(directive => `'${directive.ruleId}'`);
|
173
177
|
|
174
178
|
return {
|
@@ -186,9 +190,10 @@ function createDirectiveRemoval(directives, node) {
|
|
186
190
|
/**
|
187
191
|
* Parses details from directives to create output Problems.
|
188
192
|
* @param {Iterable<Directive>} allDirectives Unused directives to be removed.
|
193
|
+
* @param {SourceCode} sourceCode The source code object for the file being linted.
|
189
194
|
* @returns {{ description, fix, unprocessedDirective }[]} Details for later creation of output Problems.
|
190
195
|
*/
|
191
|
-
function processUnusedDirectives(allDirectives) {
|
196
|
+
function processUnusedDirectives(allDirectives, sourceCode) {
|
192
197
|
const directiveGroups = groupByParentDirective(allDirectives);
|
193
198
|
|
194
199
|
return directiveGroups.flatMap(
|
@@ -201,8 +206,8 @@ function processUnusedDirectives(allDirectives) {
|
|
201
206
|
}
|
202
207
|
|
203
208
|
return remainingRuleIds.size
|
204
|
-
? createIndividualDirectivesRemoval(directives, parentDirective.node)
|
205
|
-
: [createDirectiveRemoval(directives, parentDirective.node)];
|
209
|
+
? createIndividualDirectivesRemoval(directives, parentDirective.node, sourceCode)
|
210
|
+
: [createDirectiveRemoval(directives, parentDirective.node, sourceCode)];
|
206
211
|
}
|
207
212
|
);
|
208
213
|
}
|
@@ -309,6 +314,7 @@ function collectUsedEnableDirectives(directives) {
|
|
309
314
|
function applyDirectives(options) {
|
310
315
|
const problems = [];
|
311
316
|
const usedDisableDirectives = new Set();
|
317
|
+
const { sourceCode } = options;
|
312
318
|
|
313
319
|
for (const problem of options.problems) {
|
314
320
|
let disableDirectivesForProblem = [];
|
@@ -370,8 +376,8 @@ function applyDirectives(options) {
|
|
370
376
|
}
|
371
377
|
}
|
372
378
|
|
373
|
-
const processed = processUnusedDirectives(unusedDisableDirectivesToReport)
|
374
|
-
.concat(processUnusedDirectives(unusedEnableDirectivesToReport));
|
379
|
+
const processed = processUnusedDirectives(unusedDisableDirectivesToReport, sourceCode)
|
380
|
+
.concat(processUnusedDirectives(unusedEnableDirectivesToReport, sourceCode));
|
375
381
|
const columnOffset = options.language.columnStart === 1 ? 0 : 1;
|
376
382
|
const lineOffset = options.language.lineStart === 1 ? 0 : 1;
|
377
383
|
|
@@ -390,11 +396,14 @@ function applyDirectives(options) {
|
|
390
396
|
? `Unused eslint-disable directive (no problems were reported from ${description}).`
|
391
397
|
: "Unused eslint-disable directive (no problems were reported).";
|
392
398
|
}
|
399
|
+
|
400
|
+
const loc = sourceCode.getLoc(parentDirective.node);
|
401
|
+
|
393
402
|
return {
|
394
403
|
ruleId: null,
|
395
404
|
message,
|
396
|
-
line: type === "disable-next-line" ?
|
397
|
-
column: type === "disable-next-line" ?
|
405
|
+
line: type === "disable-next-line" ? loc.start.line + lineOffset : line,
|
406
|
+
column: type === "disable-next-line" ? loc.start.column + columnOffset : column,
|
398
407
|
severity: options.reportUnusedDisableDirectives === "warn" ? 1 : 2,
|
399
408
|
nodeType: null,
|
400
409
|
...options.disableFixes ? {} : { fix }
|
@@ -409,6 +418,7 @@ function applyDirectives(options) {
|
|
409
418
|
* of reported problems, adds the suppression information to the problems.
|
410
419
|
* @param {Object} options Information about directives and problems
|
411
420
|
* @param {Language} options.language The language being linted.
|
421
|
+
* @param {SourceCode} options.sourceCode The source code object for the file being linted.
|
412
422
|
* @param {{
|
413
423
|
* type: ("disable"|"enable"|"disable-line"|"disable-next-line"),
|
414
424
|
* ruleId: (string|null),
|
@@ -427,7 +437,7 @@ function applyDirectives(options) {
|
|
427
437
|
* @returns {{ruleId: (string|null), line: number, column: number, suppressions?: {kind: string, justification: string}}[]}
|
428
438
|
* An object with a list of reported problems, the suppressed of which contain the suppression information.
|
429
439
|
*/
|
430
|
-
module.exports = ({ language, directives, disableFixes, problems, configuredRules, ruleFilter, reportUnusedDisableDirectives = "off" }) => {
|
440
|
+
module.exports = ({ language, sourceCode, directives, disableFixes, problems, configuredRules, ruleFilter, reportUnusedDisableDirectives = "off" }) => {
|
431
441
|
const blockDirectives = directives
|
432
442
|
.filter(directive => directive.type === "disable" || directive.type === "enable")
|
433
443
|
.map(directive => Object.assign({}, directive, { unprocessedDirective: directive }))
|
@@ -477,6 +487,7 @@ module.exports = ({ language, directives, disableFixes, problems, configuredRule
|
|
477
487
|
|
478
488
|
const blockDirectivesResult = applyDirectives({
|
479
489
|
language,
|
490
|
+
sourceCode,
|
480
491
|
problems,
|
481
492
|
directives: blockDirectives,
|
482
493
|
disableFixes,
|
@@ -485,6 +496,7 @@ module.exports = ({ language, directives, disableFixes, problems, configuredRule
|
|
485
496
|
});
|
486
497
|
const lineDirectivesResult = applyDirectives({
|
487
498
|
language,
|
499
|
+
sourceCode,
|
488
500
|
problems: blockDirectivesResult.problems,
|
489
501
|
directives: lineDirectives,
|
490
502
|
disableFixes,
|
package/lib/linter/linter.js
CHANGED
@@ -45,7 +45,7 @@ const { RuleValidator } = require("../config/rule-validator");
|
|
45
45
|
const { assertIsRuleSeverity } = require("../config/flat-config-schema");
|
46
46
|
const { normalizeSeverityToString } = require("../shared/severity");
|
47
47
|
const jslang = require("../languages/js");
|
48
|
-
const { activeFlags } = require("../shared/flags");
|
48
|
+
const { activeFlags, inactiveFlags } = require("../shared/flags");
|
49
49
|
const debug = require("debug")("eslint:linter");
|
50
50
|
const MAX_AUTOFIX_PASSES = 10;
|
51
51
|
const DEFAULT_PARSER_NAME = "espree";
|
@@ -323,9 +323,10 @@ function createLintingProblem(options) {
|
|
323
323
|
* @param {ASTNode|token} options.node The Comment node/token.
|
324
324
|
* @param {function(string): {create: Function}} ruleMapper A map from rule IDs to defined rules
|
325
325
|
* @param {Language} language The language to use to adjust the location information.
|
326
|
+
* @param {SourceCode} sourceCode The SourceCode object to get comments from.
|
326
327
|
* @returns {Object} Directives and problems from the comment
|
327
328
|
*/
|
328
|
-
function createDisableDirectives({ type, value, justification, node }, ruleMapper, language) {
|
329
|
+
function createDisableDirectives({ type, value, justification, node }, ruleMapper, language, sourceCode) {
|
329
330
|
const ruleIds = Object.keys(commentParser.parseListConfig(value));
|
330
331
|
const directiveRules = ruleIds.length ? ruleIds : [null];
|
331
332
|
const result = {
|
@@ -336,11 +337,15 @@ function createDisableDirectives({ type, value, justification, node }, ruleMappe
|
|
336
337
|
|
337
338
|
for (const ruleId of directiveRules) {
|
338
339
|
|
340
|
+
const loc = sourceCode.getLoc(node);
|
341
|
+
|
339
342
|
// push to directives, if the rule is defined(including null, e.g. /*eslint enable*/)
|
340
343
|
if (ruleId === null || !!ruleMapper(ruleId)) {
|
344
|
+
|
345
|
+
|
341
346
|
if (type === "disable-next-line") {
|
342
347
|
const { line, column } = updateLocationInformation(
|
343
|
-
|
348
|
+
loc.end,
|
344
349
|
language
|
345
350
|
);
|
346
351
|
|
@@ -354,7 +359,7 @@ function createDisableDirectives({ type, value, justification, node }, ruleMappe
|
|
354
359
|
});
|
355
360
|
} else {
|
356
361
|
const { line, column } = updateLocationInformation(
|
357
|
-
|
362
|
+
loc.start,
|
358
363
|
language
|
359
364
|
);
|
360
365
|
|
@@ -368,7 +373,7 @@ function createDisableDirectives({ type, value, justification, node }, ruleMappe
|
|
368
373
|
});
|
369
374
|
}
|
370
375
|
} else {
|
371
|
-
result.directiveProblems.push(createLintingProblem({ ruleId, loc
|
376
|
+
result.directiveProblems.push(createLintingProblem({ ruleId, loc, language }));
|
372
377
|
}
|
373
378
|
}
|
374
379
|
return result;
|
@@ -410,25 +415,27 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig, config)
|
|
410
415
|
return;
|
411
416
|
}
|
412
417
|
|
418
|
+
const loc = sourceCode.getLoc(comment);
|
419
|
+
|
413
420
|
if (warnInlineConfig) {
|
414
421
|
const kind = comment.type === "Block" ? `/*${directiveText}*/` : `//${directiveText}`;
|
415
422
|
|
416
423
|
problems.push(createLintingProblem({
|
417
424
|
ruleId: null,
|
418
425
|
message: `'${kind}' has no effect because you have 'noInlineConfig' setting in ${warnInlineConfig}.`,
|
419
|
-
loc
|
426
|
+
loc,
|
420
427
|
severity: 1
|
421
428
|
}));
|
422
429
|
return;
|
423
430
|
}
|
424
431
|
|
425
|
-
if (directiveText === "eslint-disable-line" &&
|
432
|
+
if (directiveText === "eslint-disable-line" && loc.start.line !== loc.end.line) {
|
426
433
|
const message = `${directiveText} comment should not span multiple lines.`;
|
427
434
|
|
428
435
|
problems.push(createLintingProblem({
|
429
436
|
ruleId: null,
|
430
437
|
message,
|
431
|
-
loc
|
438
|
+
loc
|
432
439
|
}));
|
433
440
|
return;
|
434
441
|
}
|
@@ -446,7 +453,7 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig, config)
|
|
446
453
|
value: directiveValue,
|
447
454
|
justification: justificationPart,
|
448
455
|
node: comment
|
449
|
-
}, ruleMapper, jslang);
|
456
|
+
}, ruleMapper, jslang, sourceCode);
|
450
457
|
|
451
458
|
disableDirectives.push(...directives);
|
452
459
|
problems.push(...directiveProblems);
|
@@ -467,7 +474,7 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig, config)
|
|
467
474
|
} catch (err) {
|
468
475
|
problems.push(createLintingProblem({
|
469
476
|
ruleId: null,
|
470
|
-
loc
|
477
|
+
loc,
|
471
478
|
message: err.message
|
472
479
|
}));
|
473
480
|
continue;
|
@@ -494,14 +501,14 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig, config)
|
|
494
501
|
const ruleValue = parseResult.config[name];
|
495
502
|
|
496
503
|
if (!rule) {
|
497
|
-
problems.push(createLintingProblem({ ruleId: name, loc
|
504
|
+
problems.push(createLintingProblem({ ruleId: name, loc }));
|
498
505
|
return;
|
499
506
|
}
|
500
507
|
|
501
508
|
if (Object.hasOwn(configuredRules, name)) {
|
502
509
|
problems.push(createLintingProblem({
|
503
510
|
message: `Rule "${name}" is already configured by another configuration comment in the preceding code. This configuration is ignored.`,
|
504
|
-
loc
|
511
|
+
loc
|
505
512
|
}));
|
506
513
|
return;
|
507
514
|
}
|
@@ -563,7 +570,7 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig, config)
|
|
563
570
|
problems.push(createLintingProblem({
|
564
571
|
ruleId: name,
|
565
572
|
message: err.message,
|
566
|
-
loc
|
573
|
+
loc
|
567
574
|
}));
|
568
575
|
|
569
576
|
// do not apply the config, if found invalid options.
|
@@ -575,7 +582,7 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig, config)
|
|
575
582
|
} else {
|
576
583
|
const problem = createLintingProblem({
|
577
584
|
ruleId: null,
|
578
|
-
loc
|
585
|
+
loc,
|
579
586
|
message: parseResult.error.message
|
580
587
|
});
|
581
588
|
|
@@ -623,7 +630,7 @@ function getDirectiveCommentsForFlatConfig(sourceCode, ruleMapper, language) {
|
|
623
630
|
})));
|
624
631
|
|
625
632
|
directivesSources.forEach(directive => {
|
626
|
-
const { directives, directiveProblems } = createDisableDirectives(directive, ruleMapper, language);
|
633
|
+
const { directives, directiveProblems } = createDisableDirectives(directive, ruleMapper, language, sourceCode);
|
627
634
|
|
628
635
|
disableDirectives.push(...directives);
|
629
636
|
problems.push(...directiveProblems);
|
@@ -1282,9 +1289,20 @@ class Linter {
|
|
1282
1289
|
* @param {"flat"|"eslintrc"} [config.configType="flat"] the type of config used.
|
1283
1290
|
*/
|
1284
1291
|
constructor({ cwd, configType = "flat", flags = [] } = {}) {
|
1292
|
+
|
1293
|
+
flags.forEach(flag => {
|
1294
|
+
if (inactiveFlags.has(flag)) {
|
1295
|
+
throw new Error(`The flag '${flag}' is inactive: ${inactiveFlags.get(flag)}`);
|
1296
|
+
}
|
1297
|
+
|
1298
|
+
if (!activeFlags.has(flag)) {
|
1299
|
+
throw new Error(`Unknown flag '${flag}'.`);
|
1300
|
+
}
|
1301
|
+
});
|
1302
|
+
|
1285
1303
|
internalSlotsMap.set(this, {
|
1286
1304
|
cwd: normalizeCwd(cwd),
|
1287
|
-
flags
|
1305
|
+
flags,
|
1288
1306
|
lastConfigArray: null,
|
1289
1307
|
lastSourceCode: null,
|
1290
1308
|
lastSuppressedMessages: [],
|
@@ -1462,7 +1480,7 @@ class Linter {
|
|
1462
1480
|
debug("An error occurred while traversing");
|
1463
1481
|
debug("Filename:", options.filename);
|
1464
1482
|
if (err.currentNode) {
|
1465
|
-
const { line } = err.currentNode.
|
1483
|
+
const { line } = sourceCode.getLoc(err.currentNode).start;
|
1466
1484
|
|
1467
1485
|
debug("Line:", line);
|
1468
1486
|
err.message += `:${line}`;
|
@@ -1480,6 +1498,7 @@ class Linter {
|
|
1480
1498
|
|
1481
1499
|
return applyDisableDirectives({
|
1482
1500
|
language: jslang,
|
1501
|
+
sourceCode,
|
1483
1502
|
directives: commentDirectives.disableDirectives,
|
1484
1503
|
disableFixes: options.disableFixes,
|
1485
1504
|
problems: lintingProblems
|
@@ -1759,10 +1778,14 @@ class Linter {
|
|
1759
1778
|
if (options.warnInlineConfig) {
|
1760
1779
|
if (sourceCode.getInlineConfigNodes) {
|
1761
1780
|
sourceCode.getInlineConfigNodes().forEach(node => {
|
1781
|
+
|
1782
|
+
const loc = sourceCode.getLoc(node);
|
1783
|
+
const range = sourceCode.getRange(node);
|
1784
|
+
|
1762
1785
|
inlineConfigProblems.push(createLintingProblem({
|
1763
1786
|
ruleId: null,
|
1764
|
-
message: `'${sourceCode.text.slice(
|
1765
|
-
loc
|
1787
|
+
message: `'${sourceCode.text.slice(range[0], range[1])}' has no effect because you have 'noInlineConfig' setting in ${options.warnInlineConfig}.`,
|
1788
|
+
loc,
|
1766
1789
|
severity: 1,
|
1767
1790
|
language: config.language
|
1768
1791
|
}));
|
@@ -1942,7 +1965,7 @@ class Linter {
|
|
1942
1965
|
debug("An error occurred while traversing");
|
1943
1966
|
debug("Filename:", options.filename);
|
1944
1967
|
if (err.currentNode) {
|
1945
|
-
const { line } = err.currentNode.
|
1968
|
+
const { line } = sourceCode.getLoc(err.currentNode).start;
|
1946
1969
|
|
1947
1970
|
debug("Line:", line);
|
1948
1971
|
err.message += `:${line}`;
|
@@ -1961,6 +1984,7 @@ class Linter {
|
|
1961
1984
|
|
1962
1985
|
return applyDisableDirectives({
|
1963
1986
|
language: config.language,
|
1987
|
+
sourceCode,
|
1964
1988
|
directives: commentDirectives.disableDirectives,
|
1965
1989
|
disableFixes: options.disableFixes,
|
1966
1990
|
problems: lintingProblems
|
@@ -10,7 +10,7 @@
|
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
12
|
const assert = require("node:assert");
|
13
|
-
const
|
13
|
+
const { RuleFixer } = require("./rule-fixer");
|
14
14
|
const { interpolate } = require("./interpolate");
|
15
15
|
|
16
16
|
//------------------------------------------------------------------------------
|
@@ -91,13 +91,10 @@ function assertValidNodeInfo(descriptor) {
|
|
91
91
|
* from the `node` of the original descriptor, or infers the `start` from the `loc` of the original descriptor.
|
92
92
|
*/
|
93
93
|
function normalizeReportLoc(descriptor) {
|
94
|
-
if (descriptor.loc) {
|
95
|
-
|
96
|
-
return descriptor.loc;
|
97
|
-
}
|
98
|
-
return { start: descriptor.loc, end: null };
|
94
|
+
if (descriptor.loc.start) {
|
95
|
+
return descriptor.loc;
|
99
96
|
}
|
100
|
-
return descriptor.
|
97
|
+
return { start: descriptor.loc, end: null };
|
101
98
|
}
|
102
99
|
|
103
100
|
/**
|
@@ -190,6 +187,8 @@ function normalizeFixes(descriptor, sourceCode) {
|
|
190
187
|
return null;
|
191
188
|
}
|
192
189
|
|
190
|
+
const ruleFixer = new RuleFixer({ sourceCode });
|
191
|
+
|
193
192
|
// @type {null | Fix | Fix[] | IterableIterator<Fix>}
|
194
193
|
const fix = descriptor.fix(ruleFixer);
|
195
194
|
|
@@ -335,6 +334,7 @@ module.exports = function createReportTranslator(metadata) {
|
|
335
334
|
return (...args) => {
|
336
335
|
const descriptor = normalizeMultiArgReportCall(...args);
|
337
336
|
const messages = metadata.messageIds;
|
337
|
+
const { sourceCode } = metadata;
|
338
338
|
|
339
339
|
assertValidNodeInfo(descriptor);
|
340
340
|
|
@@ -367,9 +367,9 @@ module.exports = function createReportTranslator(metadata) {
|
|
367
367
|
node: descriptor.node,
|
368
368
|
message: interpolate(computedMessage, descriptor.data),
|
369
369
|
messageId: descriptor.messageId,
|
370
|
-
loc: normalizeReportLoc(descriptor),
|
371
|
-
fix: metadata.disableFixes ? null : normalizeFixes(descriptor,
|
372
|
-
suggestions: metadata.disableFixes ? [] : mapSuggestions(descriptor,
|
370
|
+
loc: descriptor.loc ? normalizeReportLoc(descriptor) : sourceCode.getLoc(descriptor.node),
|
371
|
+
fix: metadata.disableFixes ? null : normalizeFixes(descriptor, sourceCode),
|
372
|
+
suggestions: metadata.disableFixes ? [] : mapSuggestions(descriptor, sourceCode, messages),
|
373
373
|
language: metadata.language
|
374
374
|
});
|
375
375
|
};
|
package/lib/linter/rule-fixer.js
CHANGED
@@ -4,6 +4,8 @@
|
|
4
4
|
*/
|
5
5
|
"use strict";
|
6
6
|
|
7
|
+
/* eslint class-methods-use-this: off -- Methods desired on instance */
|
8
|
+
|
7
9
|
//------------------------------------------------------------------------------
|
8
10
|
// Requirements
|
9
11
|
//------------------------------------------------------------------------------
|
@@ -35,8 +37,22 @@ function insertTextAt(index, text) {
|
|
35
37
|
/**
|
36
38
|
* Creates code fixing commands for rules.
|
37
39
|
*/
|
40
|
+
class RuleFixer {
|
38
41
|
|
39
|
-
|
42
|
+
/**
|
43
|
+
* The source code object representing the text to be fixed.
|
44
|
+
* @type {SourceCode}
|
45
|
+
*/
|
46
|
+
#sourceCode;
|
47
|
+
|
48
|
+
/**
|
49
|
+
* Creates a new instance.
|
50
|
+
* @param {Object} options The options for the fixer.
|
51
|
+
* @param {SourceCode} options.sourceCode The source code object representing the text to be fixed.
|
52
|
+
*/
|
53
|
+
constructor({ sourceCode }) {
|
54
|
+
this.#sourceCode = sourceCode;
|
55
|
+
}
|
40
56
|
|
41
57
|
/**
|
42
58
|
* Creates a fix command that inserts text after the given node or token.
|
@@ -46,8 +62,10 @@ const ruleFixer = Object.freeze({
|
|
46
62
|
* @returns {Object} The fix command.
|
47
63
|
*/
|
48
64
|
insertTextAfter(nodeOrToken, text) {
|
49
|
-
|
50
|
-
|
65
|
+
const range = this.#sourceCode.getRange(nodeOrToken);
|
66
|
+
|
67
|
+
return this.insertTextAfterRange(range, text);
|
68
|
+
}
|
51
69
|
|
52
70
|
/**
|
53
71
|
* Creates a fix command that inserts text after the specified range in the source text.
|
@@ -59,7 +77,7 @@ const ruleFixer = Object.freeze({
|
|
59
77
|
*/
|
60
78
|
insertTextAfterRange(range, text) {
|
61
79
|
return insertTextAt(range[1], text);
|
62
|
-
}
|
80
|
+
}
|
63
81
|
|
64
82
|
/**
|
65
83
|
* Creates a fix command that inserts text before the given node or token.
|
@@ -69,8 +87,10 @@ const ruleFixer = Object.freeze({
|
|
69
87
|
* @returns {Object} The fix command.
|
70
88
|
*/
|
71
89
|
insertTextBefore(nodeOrToken, text) {
|
72
|
-
|
73
|
-
|
90
|
+
const range = this.#sourceCode.getRange(nodeOrToken);
|
91
|
+
|
92
|
+
return this.insertTextBeforeRange(range, text);
|
93
|
+
}
|
74
94
|
|
75
95
|
/**
|
76
96
|
* Creates a fix command that inserts text before the specified range in the source text.
|
@@ -82,7 +102,7 @@ const ruleFixer = Object.freeze({
|
|
82
102
|
*/
|
83
103
|
insertTextBeforeRange(range, text) {
|
84
104
|
return insertTextAt(range[0], text);
|
85
|
-
}
|
105
|
+
}
|
86
106
|
|
87
107
|
/**
|
88
108
|
* Creates a fix command that replaces text at the node or token.
|
@@ -92,8 +112,10 @@ const ruleFixer = Object.freeze({
|
|
92
112
|
* @returns {Object} The fix command.
|
93
113
|
*/
|
94
114
|
replaceText(nodeOrToken, text) {
|
95
|
-
|
96
|
-
|
115
|
+
const range = this.#sourceCode.getRange(nodeOrToken);
|
116
|
+
|
117
|
+
return this.replaceTextRange(range, text);
|
118
|
+
}
|
97
119
|
|
98
120
|
/**
|
99
121
|
* Creates a fix command that replaces text at the specified range in the source text.
|
@@ -108,7 +130,7 @@ const ruleFixer = Object.freeze({
|
|
108
130
|
range,
|
109
131
|
text
|
110
132
|
};
|
111
|
-
}
|
133
|
+
}
|
112
134
|
|
113
135
|
/**
|
114
136
|
* Creates a fix command that removes the node or token from the source.
|
@@ -117,8 +139,10 @@ const ruleFixer = Object.freeze({
|
|
117
139
|
* @returns {Object} The fix command.
|
118
140
|
*/
|
119
141
|
remove(nodeOrToken) {
|
120
|
-
|
121
|
-
|
142
|
+
const range = this.#sourceCode.getRange(nodeOrToken);
|
143
|
+
|
144
|
+
return this.removeRange(range);
|
145
|
+
}
|
122
146
|
|
123
147
|
/**
|
124
148
|
* Creates a fix command that removes the specified range of text from the source.
|
@@ -133,8 +157,7 @@ const ruleFixer = Object.freeze({
|
|
133
157
|
text: ""
|
134
158
|
};
|
135
159
|
}
|
136
|
-
|
137
|
-
});
|
160
|
+
}
|
138
161
|
|
139
162
|
|
140
|
-
module.exports =
|
163
|
+
module.exports = { RuleFixer };
|
package/lib/shared/flags.js
CHANGED
@@ -9,7 +9,7 @@
|
|
9
9
|
* @type {Map<string, string>}
|
10
10
|
*/
|
11
11
|
const activeFlags = new Map([
|
12
|
-
["test_only", "
|
12
|
+
["test_only", "Used only for testing."]
|
13
13
|
]);
|
14
14
|
|
15
15
|
/**
|
@@ -17,7 +17,7 @@ const activeFlags = new Map([
|
|
17
17
|
* @type {Map<string, string>}
|
18
18
|
*/
|
19
19
|
const inactiveFlags = new Map([
|
20
|
-
["test_only_old", "
|
20
|
+
["test_only_old", "Used only for testing."]
|
21
21
|
]);
|
22
22
|
|
23
23
|
module.exports = {
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "eslint",
|
3
|
-
"version": "9.
|
3
|
+
"version": "9.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": {
|
@@ -68,9 +68,9 @@
|
|
68
68
|
"dependencies": {
|
69
69
|
"@eslint-community/eslint-utils": "^4.2.0",
|
70
70
|
"@eslint-community/regexpp": "^4.11.0",
|
71
|
-
"@eslint/config-array": "^0.17.
|
71
|
+
"@eslint/config-array": "^0.17.1",
|
72
72
|
"@eslint/eslintrc": "^3.1.0",
|
73
|
-
"@eslint/js": "9.
|
73
|
+
"@eslint/js": "9.8.0",
|
74
74
|
"@humanwhocodes/module-importer": "^1.0.1",
|
75
75
|
"@humanwhocodes/retry": "^0.3.0",
|
76
76
|
"@nodelib/fs.walk": "^1.2.8",
|
@@ -104,7 +104,8 @@
|
|
104
104
|
"devDependencies": {
|
105
105
|
"@babel/core": "^7.4.3",
|
106
106
|
"@babel/preset-env": "^7.4.3",
|
107
|
-
"@eslint/core": "^0.
|
107
|
+
"@eslint/core": "^0.2.0",
|
108
|
+
"@eslint/json": "^0.2.0",
|
108
109
|
"@types/estree": "^1.0.5",
|
109
110
|
"@types/node": "^20.11.5",
|
110
111
|
"@wdio/browser-runner": "^8.38.3",
|