eslint 9.9.1 → 9.11.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 -2
- package/lib/config/config.js +278 -0
- package/lib/config/flat-config-array.js +3 -204
- package/lib/config/flat-config-helpers.js +1 -5
- package/lib/languages/js/source-code/source-code.js +29 -145
- package/lib/linter/apply-disable-directives.js +17 -28
- package/lib/linter/file-context.js +134 -0
- package/lib/linter/linter.js +182 -150
- package/lib/linter/vfile.js +8 -1
- package/lib/rules/id-length.js +8 -0
- package/lib/rules/no-invalid-regexp.js +34 -18
- package/lib/rules/no-useless-constructor.js +18 -2
- package/lib/rules/require-unicode-regexp.js +95 -14
- package/lib/rules/utils/regular-expressions.js +11 -3
- package/lib/services/processor-service.js +109 -0
- package/lib/shared/types.js +1 -1
- package/lib/types/index.d.ts +1668 -0
- package/lib/types/rules/best-practices.d.ts +1083 -0
- package/lib/types/rules/deprecated.d.ts +294 -0
- package/lib/types/rules/ecmascript-6.d.ts +607 -0
- package/lib/types/rules/index.d.ts +50 -0
- package/lib/types/rules/node-commonjs.d.ts +160 -0
- package/lib/types/rules/possible-errors.d.ts +631 -0
- package/lib/types/rules/strict-mode.d.ts +38 -0
- package/lib/types/rules/stylistic-issues.d.ts +1942 -0
- package/lib/types/rules/variables.d.ts +221 -0
- package/lib/types/universal.d.ts +6 -0
- package/lib/types/use-at-your-own-risk.d.ts +85 -0
- package/lib/universal.js +10 -0
- package/package.json +29 -10
- package/lib/linter/config-comment-parser.js +0 -169
package/lib/linter/linter.js
CHANGED
@@ -17,9 +17,6 @@ const
|
|
17
17
|
espree = require("espree"),
|
18
18
|
merge = require("lodash.merge"),
|
19
19
|
pkg = require("../../package.json"),
|
20
|
-
{
|
21
|
-
directivesPattern
|
22
|
-
} = require("../shared/directives"),
|
23
20
|
{
|
24
21
|
Legacy: {
|
25
22
|
ConfigOps,
|
@@ -30,7 +27,7 @@ const
|
|
30
27
|
Traverser = require("../shared/traverser"),
|
31
28
|
{ SourceCode } = require("../languages/js/source-code"),
|
32
29
|
applyDisableDirectives = require("./apply-disable-directives"),
|
33
|
-
ConfigCommentParser = require("
|
30
|
+
{ ConfigCommentParser } = require("@eslint/plugin-kit"),
|
34
31
|
NodeEventGenerator = require("./node-event-generator"),
|
35
32
|
createReportTranslator = require("./report-translator"),
|
36
33
|
Rules = require("./rules"),
|
@@ -56,6 +53,8 @@ const parserSymbol = Symbol.for("eslint.RuleTester.parser");
|
|
56
53
|
const { LATEST_ECMA_VERSION } = require("../../conf/ecma-version");
|
57
54
|
const { VFile } = require("./vfile");
|
58
55
|
const { ParserService } = require("../services/parser-service");
|
56
|
+
const { FileContext } = require("./file-context");
|
57
|
+
const { ProcessorService } = require("../services/processor-service");
|
59
58
|
const STEP_KIND_VISIT = 1;
|
60
59
|
const STEP_KIND_CALL = 2;
|
61
60
|
|
@@ -334,7 +333,7 @@ function createDisableDirectives({ type, value, justification, node }, ruleMappe
|
|
334
333
|
directives: [], // valid disable directives
|
335
334
|
directiveProblems: [] // problems in directives
|
336
335
|
};
|
337
|
-
const parentDirective = { node, ruleIds };
|
336
|
+
const parentDirective = { node, value, ruleIds };
|
338
337
|
|
339
338
|
for (const ruleId of directiveRules) {
|
340
339
|
|
@@ -402,15 +401,20 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig, config)
|
|
402
401
|
});
|
403
402
|
|
404
403
|
sourceCode.getInlineConfigNodes().filter(token => token.type !== "Shebang").forEach(comment => {
|
405
|
-
const { directivePart, justificationPart } = commentParser.extractDirectiveComment(comment.value);
|
406
404
|
|
407
|
-
const
|
405
|
+
const directive = commentParser.parseDirective(comment.value);
|
408
406
|
|
409
|
-
if (!
|
407
|
+
if (!directive) {
|
410
408
|
return;
|
411
409
|
}
|
412
|
-
|
413
|
-
const
|
410
|
+
|
411
|
+
const {
|
412
|
+
label,
|
413
|
+
value,
|
414
|
+
justification: justificationPart
|
415
|
+
} = directive;
|
416
|
+
|
417
|
+
const lineCommentSupported = /^eslint-disable-(next-)?line$/u.test(label);
|
414
418
|
|
415
419
|
if (comment.type === "Line" && !lineCommentSupported) {
|
416
420
|
return;
|
@@ -419,7 +423,7 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig, config)
|
|
419
423
|
const loc = sourceCode.getLoc(comment);
|
420
424
|
|
421
425
|
if (warnInlineConfig) {
|
422
|
-
const kind = comment.type === "Block" ? `/*${
|
426
|
+
const kind = comment.type === "Block" ? `/*${label}*/` : `//${label}`;
|
423
427
|
|
424
428
|
problems.push(createLintingProblem({
|
425
429
|
ruleId: null,
|
@@ -430,8 +434,8 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig, config)
|
|
430
434
|
return;
|
431
435
|
}
|
432
436
|
|
433
|
-
if (
|
434
|
-
const message = `${
|
437
|
+
if (label === "eslint-disable-line" && loc.start.line !== loc.end.line) {
|
438
|
+
const message = `${label} comment should not span multiple lines.`;
|
435
439
|
|
436
440
|
problems.push(createLintingProblem({
|
437
441
|
ruleId: null,
|
@@ -441,17 +445,15 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig, config)
|
|
441
445
|
return;
|
442
446
|
}
|
443
447
|
|
444
|
-
|
445
|
-
|
446
|
-
switch (directiveText) {
|
448
|
+
switch (label) {
|
447
449
|
case "eslint-disable":
|
448
450
|
case "eslint-enable":
|
449
451
|
case "eslint-disable-next-line":
|
450
452
|
case "eslint-disable-line": {
|
451
|
-
const directiveType =
|
453
|
+
const directiveType = label.slice("eslint-".length);
|
452
454
|
const { directives, directiveProblems } = createDisableDirectives({
|
453
455
|
type: directiveType,
|
454
|
-
value
|
456
|
+
value,
|
455
457
|
justification: justificationPart,
|
456
458
|
node: comment
|
457
459
|
}, ruleMapper, jslang, sourceCode);
|
@@ -462,16 +464,16 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig, config)
|
|
462
464
|
}
|
463
465
|
|
464
466
|
case "exported":
|
465
|
-
Object.assign(exportedVariables, commentParser.parseListConfig(
|
467
|
+
Object.assign(exportedVariables, commentParser.parseListConfig(value));
|
466
468
|
break;
|
467
469
|
|
468
470
|
case "globals":
|
469
471
|
case "global":
|
470
|
-
for (const [id,
|
472
|
+
for (const [id, idSetting] of Object.entries(commentParser.parseStringConfig(value))) {
|
471
473
|
let normalizedValue;
|
472
474
|
|
473
475
|
try {
|
474
|
-
normalizedValue = ConfigOps.normalizeConfigGlobal(
|
476
|
+
normalizedValue = ConfigOps.normalizeConfigGlobal(idSetting);
|
475
477
|
} catch (err) {
|
476
478
|
problems.push(createLintingProblem({
|
477
479
|
ruleId: null,
|
@@ -494,9 +496,9 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig, config)
|
|
494
496
|
break;
|
495
497
|
|
496
498
|
case "eslint": {
|
497
|
-
const parseResult = commentParser.
|
499
|
+
const parseResult = commentParser.parseJSONLikeConfig(value);
|
498
500
|
|
499
|
-
if (parseResult.
|
501
|
+
if (parseResult.ok) {
|
500
502
|
Object.keys(parseResult.config).forEach(name => {
|
501
503
|
const rule = ruleMapper(name);
|
502
504
|
const ruleValue = parseResult.config[name];
|
@@ -713,7 +715,7 @@ function findEslintEnv(text) {
|
|
713
715
|
if (match[0].endsWith("*/")) {
|
714
716
|
retv = Object.assign(
|
715
717
|
retv || {},
|
716
|
-
commentParser.parseListConfig(commentParser.
|
718
|
+
commentParser.parseListConfig(commentParser.parseDirective(match[0].slice(2, -2)).value)
|
717
719
|
);
|
718
720
|
}
|
719
721
|
}
|
@@ -979,24 +981,18 @@ function runRules(
|
|
979
981
|
* All rule contexts will inherit from this object. This avoids the performance penalty of copying all the
|
980
982
|
* properties once for each rule.
|
981
983
|
*/
|
982
|
-
const sharedTraversalContext =
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
},
|
995
|
-
parserPath: parserName,
|
996
|
-
languageOptions,
|
997
|
-
settings
|
998
|
-
}
|
999
|
-
);
|
984
|
+
const sharedTraversalContext = new FileContext({
|
985
|
+
cwd,
|
986
|
+
filename,
|
987
|
+
physicalFilename: physicalFilename || filename,
|
988
|
+
sourceCode,
|
989
|
+
parserOptions: {
|
990
|
+
...languageOptions.parserOptions
|
991
|
+
},
|
992
|
+
parserPath: parserName,
|
993
|
+
languageOptions,
|
994
|
+
settings
|
995
|
+
});
|
1000
996
|
|
1001
997
|
const lintingProblems = [];
|
1002
998
|
|
@@ -1297,27 +1293,18 @@ class Linter {
|
|
1297
1293
|
}
|
1298
1294
|
|
1299
1295
|
/**
|
1300
|
-
*
|
1301
|
-
* @param {
|
1296
|
+
* Lint using eslintrc and without processors.
|
1297
|
+
* @param {VFile} file The file to lint.
|
1302
1298
|
* @param {ConfigData} providedConfig An ESLintConfig instance to configure everything.
|
1303
1299
|
* @param {VerifyOptions} [providedOptions] The optional filename of the file being checked.
|
1304
1300
|
* @throws {Error} If during rule execution.
|
1305
1301
|
* @returns {(LintMessage|SuppressedLintMessage)[]} The results as an array of messages or an empty array if no messages.
|
1306
1302
|
*/
|
1307
|
-
|
1303
|
+
#eslintrcVerifyWithoutProcessors(file, providedConfig, providedOptions) {
|
1304
|
+
|
1308
1305
|
const slots = internalSlotsMap.get(this);
|
1309
1306
|
const config = providedConfig || {};
|
1310
1307
|
const options = normalizeVerifyOptions(providedOptions, config);
|
1311
|
-
let text;
|
1312
|
-
|
1313
|
-
// evaluate arguments
|
1314
|
-
if (typeof textOrSourceCode === "string") {
|
1315
|
-
slots.lastSourceCode = null;
|
1316
|
-
text = textOrSourceCode;
|
1317
|
-
} else {
|
1318
|
-
slots.lastSourceCode = textOrSourceCode;
|
1319
|
-
text = textOrSourceCode.text;
|
1320
|
-
}
|
1321
1308
|
|
1322
1309
|
// Resolve parser.
|
1323
1310
|
let parserName = DEFAULT_PARSER_NAME;
|
@@ -1344,7 +1331,7 @@ class Linter {
|
|
1344
1331
|
|
1345
1332
|
// search and apply "eslint-env *".
|
1346
1333
|
const envInFile = options.allowInlineConfig && !options.warnInlineConfig
|
1347
|
-
? findEslintEnv(
|
1334
|
+
? findEslintEnv(file.body)
|
1348
1335
|
: {};
|
1349
1336
|
const resolvedEnvConfig = Object.assign({ builtin: true }, config.env, envInFile);
|
1350
1337
|
const enabledEnvs = Object.keys(resolvedEnvConfig)
|
@@ -1360,9 +1347,6 @@ class Linter {
|
|
1360
1347
|
parser,
|
1361
1348
|
parserOptions
|
1362
1349
|
});
|
1363
|
-
const file = new VFile(options.filename, text, {
|
1364
|
-
physicalPath: providedOptions.physicalFilename
|
1365
|
-
});
|
1366
1350
|
|
1367
1351
|
if (!slots.lastSourceCode) {
|
1368
1352
|
let t;
|
@@ -1473,6 +1457,36 @@ class Linter {
|
|
1473
1457
|
.sort((problemA, problemB) => problemA.line - problemB.line || problemA.column - problemB.column),
|
1474
1458
|
reportUnusedDisableDirectives: options.reportUnusedDisableDirectives
|
1475
1459
|
});
|
1460
|
+
|
1461
|
+
}
|
1462
|
+
|
1463
|
+
/**
|
1464
|
+
* Same as linter.verify, except without support for processors.
|
1465
|
+
* @param {string|SourceCode} textOrSourceCode The text to parse or a SourceCode object.
|
1466
|
+
* @param {ConfigData} providedConfig An ESLintConfig instance to configure everything.
|
1467
|
+
* @param {VerifyOptions} [providedOptions] The optional filename of the file being checked.
|
1468
|
+
* @throws {Error} If during rule execution.
|
1469
|
+
* @returns {(LintMessage|SuppressedLintMessage)[]} The results as an array of messages or an empty array if no messages.
|
1470
|
+
*/
|
1471
|
+
_verifyWithoutProcessors(textOrSourceCode, providedConfig, providedOptions) {
|
1472
|
+
const slots = internalSlotsMap.get(this);
|
1473
|
+
const filename = normalizeFilename(providedOptions.filename || "<input>");
|
1474
|
+
let text;
|
1475
|
+
|
1476
|
+
// evaluate arguments
|
1477
|
+
if (typeof textOrSourceCode === "string") {
|
1478
|
+
slots.lastSourceCode = null;
|
1479
|
+
text = textOrSourceCode;
|
1480
|
+
} else {
|
1481
|
+
slots.lastSourceCode = textOrSourceCode;
|
1482
|
+
text = textOrSourceCode.text;
|
1483
|
+
}
|
1484
|
+
|
1485
|
+
const file = new VFile(filename, text, {
|
1486
|
+
physicalPath: providedOptions.physicalFilename
|
1487
|
+
});
|
1488
|
+
|
1489
|
+
return this.#eslintrcVerifyWithoutProcessors(file, providedConfig, providedOptions);
|
1476
1490
|
}
|
1477
1491
|
|
1478
1492
|
/**
|
@@ -1542,102 +1556,91 @@ class Linter {
|
|
1542
1556
|
* @returns {(LintMessage|SuppressedLintMessage)[]} The found problems.
|
1543
1557
|
*/
|
1544
1558
|
_verifyWithFlatConfigArrayAndProcessor(textOrSourceCode, config, options, configForRecursive) {
|
1559
|
+
const slots = internalSlotsMap.get(this);
|
1545
1560
|
const filename = options.filename || "<input>";
|
1546
1561
|
const filenameToExpose = normalizeFilename(filename);
|
1547
1562
|
const physicalFilename = options.physicalFilename || filenameToExpose;
|
1548
1563
|
const text = ensureText(textOrSourceCode);
|
1564
|
+
const file = new VFile(filenameToExpose, text, {
|
1565
|
+
physicalPath: physicalFilename
|
1566
|
+
});
|
1567
|
+
|
1549
1568
|
const preprocess = options.preprocess || (rawText => [rawText]);
|
1550
1569
|
const postprocess = options.postprocess || (messagesList => messagesList.flat());
|
1570
|
+
|
1571
|
+
const processorService = new ProcessorService();
|
1572
|
+
const preprocessResult = processorService.preprocessSync(file, {
|
1573
|
+
processor: {
|
1574
|
+
preprocess,
|
1575
|
+
postprocess
|
1576
|
+
}
|
1577
|
+
});
|
1578
|
+
|
1579
|
+
if (!preprocessResult.ok) {
|
1580
|
+
return preprocessResult.errors;
|
1581
|
+
}
|
1582
|
+
|
1551
1583
|
const filterCodeBlock =
|
1552
1584
|
options.filterCodeBlock ||
|
1553
1585
|
(blockFilename => blockFilename.endsWith(".js"));
|
1554
1586
|
const originalExtname = path.extname(filename);
|
1587
|
+
const { files } = preprocessResult;
|
1555
1588
|
|
1556
|
-
|
1557
|
-
|
1558
|
-
try {
|
1559
|
-
blocks = preprocess(text, filenameToExpose);
|
1560
|
-
} catch (ex) {
|
1561
|
-
|
1562
|
-
// If the message includes a leading line number, strip it:
|
1563
|
-
const message = `Preprocessing error: ${ex.message.replace(/^line \d+:/iu, "").trim()}`;
|
1564
|
-
|
1565
|
-
debug("%s\n%s", message, ex.stack);
|
1566
|
-
|
1567
|
-
return [
|
1568
|
-
{
|
1569
|
-
ruleId: null,
|
1570
|
-
fatal: true,
|
1571
|
-
severity: 2,
|
1572
|
-
message,
|
1573
|
-
line: ex.lineNumber,
|
1574
|
-
column: ex.column,
|
1575
|
-
nodeType: null
|
1576
|
-
}
|
1577
|
-
];
|
1578
|
-
}
|
1579
|
-
|
1580
|
-
const messageLists = blocks.map((block, i) => {
|
1581
|
-
debug("A code block was found: %o", block.filename || "(unnamed)");
|
1589
|
+
const messageLists = files.map(block => {
|
1590
|
+
debug("A code block was found: %o", block.path || "(unnamed)");
|
1582
1591
|
|
1583
1592
|
// Keep the legacy behavior.
|
1584
1593
|
if (typeof block === "string") {
|
1585
1594
|
return this._verifyWithFlatConfigArrayAndWithoutProcessors(block, config, options);
|
1586
1595
|
}
|
1587
1596
|
|
1588
|
-
const blockText = block.text;
|
1589
|
-
const blockName = path.join(filename, `${i}_${block.filename}`);
|
1590
|
-
|
1591
1597
|
// Skip this block if filtered.
|
1592
|
-
if (!filterCodeBlock(
|
1598
|
+
if (!filterCodeBlock(block.path, block.body)) {
|
1593
1599
|
debug("This code block was skipped.");
|
1594
1600
|
return [];
|
1595
1601
|
}
|
1596
1602
|
|
1597
1603
|
// Resolve configuration again if the file content or extension was changed.
|
1598
|
-
if (configForRecursive && (text !==
|
1604
|
+
if (configForRecursive && (text !== block.rawBody || path.extname(block.path) !== originalExtname)) {
|
1599
1605
|
debug("Resolving configuration again because the file content or extension was changed.");
|
1600
1606
|
return this._verifyWithFlatConfigArray(
|
1601
|
-
|
1607
|
+
block.rawBody,
|
1602
1608
|
configForRecursive,
|
1603
|
-
{ ...options, filename:
|
1609
|
+
{ ...options, filename: block.path, physicalFilename: block.physicalPath }
|
1604
1610
|
);
|
1605
1611
|
}
|
1606
1612
|
|
1613
|
+
slots.lastSourceCode = null;
|
1614
|
+
|
1607
1615
|
// Does lint.
|
1608
|
-
return this
|
1609
|
-
|
1616
|
+
return this.#flatVerifyWithoutProcessors(
|
1617
|
+
block,
|
1610
1618
|
config,
|
1611
|
-
{ ...options, filename:
|
1619
|
+
{ ...options, filename: block.path, physicalFilename: block.physicalPath }
|
1612
1620
|
);
|
1613
1621
|
});
|
1614
1622
|
|
1615
|
-
return
|
1623
|
+
return processorService.postprocessSync(file, messageLists, {
|
1624
|
+
processor: {
|
1625
|
+
preprocess,
|
1626
|
+
postprocess
|
1627
|
+
}
|
1628
|
+
});
|
1616
1629
|
}
|
1617
1630
|
|
1618
1631
|
/**
|
1619
|
-
*
|
1620
|
-
* @param {
|
1632
|
+
* Verify using flat config and without any processors.
|
1633
|
+
* @param {VFile} file The file to lint.
|
1621
1634
|
* @param {FlatConfig} providedConfig An ESLintConfig instance to configure everything.
|
1622
1635
|
* @param {VerifyOptions} [providedOptions] The optional filename of the file being checked.
|
1623
1636
|
* @throws {Error} If during rule execution.
|
1624
1637
|
* @returns {(LintMessage|SuppressedLintMessage)[]} The results as an array of messages or an empty array if no messages.
|
1625
1638
|
*/
|
1626
|
-
|
1639
|
+
#flatVerifyWithoutProcessors(file, providedConfig, providedOptions) {
|
1640
|
+
|
1627
1641
|
const slots = internalSlotsMap.get(this);
|
1628
1642
|
const config = providedConfig || {};
|
1629
1643
|
const options = normalizeVerifyOptions(providedOptions, config);
|
1630
|
-
let text;
|
1631
|
-
|
1632
|
-
// evaluate arguments
|
1633
|
-
if (typeof textOrSourceCode === "string") {
|
1634
|
-
slots.lastSourceCode = null;
|
1635
|
-
text = textOrSourceCode;
|
1636
|
-
} else {
|
1637
|
-
slots.lastSourceCode = textOrSourceCode;
|
1638
|
-
text = textOrSourceCode.text;
|
1639
|
-
}
|
1640
|
-
|
1641
1644
|
const languageOptions = config.languageOptions;
|
1642
1645
|
|
1643
1646
|
languageOptions.ecmaVersion = normalizeEcmaVersionForLanguageOptions(
|
@@ -1668,9 +1671,6 @@ class Linter {
|
|
1668
1671
|
}
|
1669
1672
|
|
1670
1673
|
const settings = config.settings || {};
|
1671
|
-
const file = new VFile(options.filename, text, {
|
1672
|
-
physicalPath: providedOptions.physicalFilename
|
1673
|
-
});
|
1674
1674
|
|
1675
1675
|
if (!slots.lastSourceCode) {
|
1676
1676
|
let t;
|
@@ -1962,6 +1962,37 @@ class Linter {
|
|
1962
1962
|
ruleFilter: options.ruleFilter,
|
1963
1963
|
configuredRules
|
1964
1964
|
});
|
1965
|
+
|
1966
|
+
|
1967
|
+
}
|
1968
|
+
|
1969
|
+
/**
|
1970
|
+
* Same as linter.verify, except without support for processors.
|
1971
|
+
* @param {string|SourceCode} textOrSourceCode The text to parse or a SourceCode object.
|
1972
|
+
* @param {FlatConfig} providedConfig An ESLintConfig instance to configure everything.
|
1973
|
+
* @param {VerifyOptions} [providedOptions] The optional filename of the file being checked.
|
1974
|
+
* @throws {Error} If during rule execution.
|
1975
|
+
* @returns {(LintMessage|SuppressedLintMessage)[]} The results as an array of messages or an empty array if no messages.
|
1976
|
+
*/
|
1977
|
+
_verifyWithFlatConfigArrayAndWithoutProcessors(textOrSourceCode, providedConfig, providedOptions) {
|
1978
|
+
const slots = internalSlotsMap.get(this);
|
1979
|
+
const filename = normalizeFilename(providedOptions.filename || "<input>");
|
1980
|
+
let text;
|
1981
|
+
|
1982
|
+
// evaluate arguments
|
1983
|
+
if (typeof textOrSourceCode === "string") {
|
1984
|
+
slots.lastSourceCode = null;
|
1985
|
+
text = textOrSourceCode;
|
1986
|
+
} else {
|
1987
|
+
slots.lastSourceCode = textOrSourceCode;
|
1988
|
+
text = textOrSourceCode.text;
|
1989
|
+
}
|
1990
|
+
|
1991
|
+
const file = new VFile(filename, text, {
|
1992
|
+
physicalPath: providedOptions.physicalFilename
|
1993
|
+
});
|
1994
|
+
|
1995
|
+
return this.#flatVerifyWithoutProcessors(file, providedConfig, providedOptions);
|
1965
1996
|
}
|
1966
1997
|
|
1967
1998
|
/**
|
@@ -2062,77 +2093,78 @@ class Linter {
|
|
2062
2093
|
* @returns {(LintMessage|SuppressedLintMessage)[]} The found problems.
|
2063
2094
|
*/
|
2064
2095
|
_verifyWithProcessor(textOrSourceCode, config, options, configForRecursive) {
|
2096
|
+
const slots = internalSlotsMap.get(this);
|
2065
2097
|
const filename = options.filename || "<input>";
|
2066
2098
|
const filenameToExpose = normalizeFilename(filename);
|
2067
2099
|
const physicalFilename = options.physicalFilename || filenameToExpose;
|
2068
2100
|
const text = ensureText(textOrSourceCode);
|
2101
|
+
const file = new VFile(filenameToExpose, text, {
|
2102
|
+
physicalPath: physicalFilename
|
2103
|
+
});
|
2104
|
+
|
2069
2105
|
const preprocess = options.preprocess || (rawText => [rawText]);
|
2070
2106
|
const postprocess = options.postprocess || (messagesList => messagesList.flat());
|
2071
|
-
const filterCodeBlock =
|
2072
|
-
options.filterCodeBlock ||
|
2073
|
-
(blockFilename => blockFilename.endsWith(".js"));
|
2074
|
-
const originalExtname = path.extname(filename);
|
2075
|
-
|
2076
|
-
let blocks;
|
2077
2107
|
|
2078
|
-
|
2079
|
-
|
2080
|
-
|
2108
|
+
const processorService = new ProcessorService();
|
2109
|
+
const preprocessResult = processorService.preprocessSync(file, {
|
2110
|
+
processor: {
|
2111
|
+
preprocess,
|
2112
|
+
postprocess
|
2113
|
+
}
|
2114
|
+
});
|
2081
2115
|
|
2082
|
-
|
2083
|
-
|
2116
|
+
if (!preprocessResult.ok) {
|
2117
|
+
return preprocessResult.errors;
|
2118
|
+
}
|
2084
2119
|
|
2085
|
-
|
2120
|
+
const filterCodeBlock =
|
2121
|
+
options.filterCodeBlock ||
|
2122
|
+
(blockFilePath => blockFilePath.endsWith(".js"));
|
2123
|
+
const originalExtname = path.extname(filename);
|
2086
2124
|
|
2087
|
-
|
2088
|
-
{
|
2089
|
-
ruleId: null,
|
2090
|
-
fatal: true,
|
2091
|
-
severity: 2,
|
2092
|
-
message,
|
2093
|
-
line: ex.lineNumber,
|
2094
|
-
column: ex.column,
|
2095
|
-
nodeType: null
|
2096
|
-
}
|
2097
|
-
];
|
2098
|
-
}
|
2125
|
+
const { files } = preprocessResult;
|
2099
2126
|
|
2100
|
-
const messageLists =
|
2101
|
-
debug("A code block was found: %o", block.
|
2127
|
+
const messageLists = files.map(block => {
|
2128
|
+
debug("A code block was found: %o", block.path ?? "(unnamed)");
|
2102
2129
|
|
2103
2130
|
// Keep the legacy behavior.
|
2104
2131
|
if (typeof block === "string") {
|
2105
2132
|
return this._verifyWithoutProcessors(block, config, options);
|
2106
2133
|
}
|
2107
2134
|
|
2108
|
-
const blockText = block.text;
|
2109
|
-
const blockName = path.join(filename, `${i}_${block.filename}`);
|
2110
|
-
|
2111
2135
|
// Skip this block if filtered.
|
2112
|
-
if (!filterCodeBlock(
|
2136
|
+
if (!filterCodeBlock(block.path, block.body)) {
|
2113
2137
|
debug("This code block was skipped.");
|
2114
2138
|
return [];
|
2115
2139
|
}
|
2116
2140
|
|
2117
2141
|
// Resolve configuration again if the file content or extension was changed.
|
2118
|
-
if (configForRecursive && (text !==
|
2142
|
+
if (configForRecursive && (text !== block.rawBody || path.extname(block.path) !== originalExtname)) {
|
2119
2143
|
debug("Resolving configuration again because the file content or extension was changed.");
|
2120
2144
|
return this._verifyWithConfigArray(
|
2121
|
-
|
2145
|
+
block.rawBody,
|
2122
2146
|
configForRecursive,
|
2123
|
-
{ ...options, filename:
|
2147
|
+
{ ...options, filename: block.path, physicalFilename: block.physicalPath }
|
2124
2148
|
);
|
2125
2149
|
}
|
2126
2150
|
|
2151
|
+
slots.lastSourceCode = null;
|
2152
|
+
|
2127
2153
|
// Does lint.
|
2128
|
-
return this
|
2129
|
-
|
2154
|
+
return this.#eslintrcVerifyWithoutProcessors(
|
2155
|
+
block,
|
2130
2156
|
config,
|
2131
|
-
{ ...options, filename:
|
2157
|
+
{ ...options, filename: block.path, physicalFilename: block.physicalPath }
|
2132
2158
|
);
|
2133
2159
|
});
|
2134
2160
|
|
2135
|
-
return
|
2161
|
+
return processorService.postprocessSync(file, messageLists, {
|
2162
|
+
processor: {
|
2163
|
+
preprocess,
|
2164
|
+
postprocess
|
2165
|
+
}
|
2166
|
+
});
|
2167
|
+
|
2136
2168
|
}
|
2137
2169
|
|
2138
2170
|
/**
|
package/lib/linter/vfile.js
CHANGED
@@ -85,6 +85,13 @@ class VFile {
|
|
85
85
|
*/
|
86
86
|
body;
|
87
87
|
|
88
|
+
/**
|
89
|
+
* The raw body of the file, including a BOM if present.
|
90
|
+
* @type {string|Uint8Array}
|
91
|
+
* @readonly
|
92
|
+
*/
|
93
|
+
rawBody;
|
94
|
+
|
88
95
|
/**
|
89
96
|
* Indicates whether the file has a byte order mark (BOM).
|
90
97
|
* @type {boolean}
|
@@ -104,8 +111,8 @@ class VFile {
|
|
104
111
|
this.physicalPath = physicalPath ?? path;
|
105
112
|
this.bom = hasUnicodeBOM(body);
|
106
113
|
this.body = stripUnicodeBOM(body);
|
114
|
+
this.rawBody = body;
|
107
115
|
}
|
108
|
-
|
109
116
|
}
|
110
117
|
|
111
118
|
module.exports = { VFile };
|
package/lib/rules/id-length.js
CHANGED
@@ -11,6 +11,7 @@
|
|
11
11
|
//------------------------------------------------------------------------------
|
12
12
|
|
13
13
|
const { getGraphemeCount } = require("../shared/string-utils");
|
14
|
+
const { getModuleExportName } = require("./utils/ast-utils");
|
14
15
|
|
15
16
|
//------------------------------------------------------------------------------
|
16
17
|
// Rule Definition
|
@@ -116,7 +117,14 @@ module.exports = {
|
|
116
117
|
}
|
117
118
|
return properties && !parent.computed && parent.key.name === node.name;
|
118
119
|
},
|
120
|
+
ImportSpecifier(parent, node) {
|
121
|
+
return (
|
122
|
+
parent.local === node &&
|
123
|
+
getModuleExportName(parent.imported) !== getModuleExportName(parent.local)
|
124
|
+
);
|
125
|
+
},
|
119
126
|
ImportDefaultSpecifier: true,
|
127
|
+
ImportNamespaceSpecifier: true,
|
120
128
|
RestElement: true,
|
121
129
|
FunctionExpression: true,
|
122
130
|
ArrowFunctionExpression: true,
|