eslint 9.39.0 → 10.0.0-alpha.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 +3 -3
- package/bin/eslint.js +1 -2
- package/lib/api.js +4 -15
- package/lib/cli.js +14 -56
- package/lib/config/config-loader.js +6 -154
- package/lib/eslint/eslint-helpers.js +5 -8
- package/lib/eslint/eslint.js +1 -1
- package/lib/eslint/index.js +0 -2
- package/lib/languages/js/source-code/source-code.js +41 -89
- package/lib/languages/js/source-code/token-store/utils.js +29 -8
- package/lib/linter/apply-disable-directives.js +0 -1
- package/lib/linter/file-context.js +0 -56
- package/lib/linter/file-report.js +0 -4
- package/lib/linter/linter.js +45 -1086
- package/lib/linter/rule-fixer.js +30 -0
- package/lib/options.js +62 -182
- package/lib/rule-tester/rule-tester.js +255 -194
- package/lib/rules/dot-notation.js +2 -2
- package/lib/rules/func-names.js +2 -0
- package/lib/rules/no-eval.js +1 -1
- package/lib/rules/no-invalid-regexp.js +1 -0
- package/lib/rules/no-shadow-restricted-names.js +1 -1
- package/lib/rules/no-unassigned-vars.js +1 -1
- package/lib/rules/no-useless-assignment.js +1 -1
- package/lib/rules/preserve-caught-error.js +1 -1
- package/lib/rules/radix.js +25 -48
- package/lib/services/parser-service.js +0 -1
- package/lib/services/processor-service.js +0 -1
- package/lib/services/warning-service.js +0 -11
- package/lib/shared/flags.js +0 -19
- package/lib/shared/translate-cli-options.js +106 -164
- package/lib/types/index.d.ts +7 -60
- package/lib/types/rules.d.ts +11 -2
- package/lib/types/use-at-your-own-risk.d.ts +1 -54
- package/lib/unsupported-api.js +3 -6
- package/package.json +14 -19
- package/conf/default-cli-options.js +0 -32
- package/lib/cli-engine/cli-engine.js +0 -1109
- package/lib/cli-engine/file-enumerator.js +0 -541
- package/lib/cli-engine/index.js +0 -7
- package/lib/cli-engine/load-rules.js +0 -46
- package/lib/eslint/legacy-eslint.js +0 -786
|
@@ -18,7 +18,8 @@ const assert = require("node:assert"),
|
|
|
18
18
|
{ Config } = require("../config/config"),
|
|
19
19
|
{ Linter, SourceCodeFixer } = require("../linter"),
|
|
20
20
|
{ interpolate, getPlaceholderMatcher } = require("../linter/interpolate"),
|
|
21
|
-
stringify = require("json-stable-stringify-without-jsonify")
|
|
21
|
+
stringify = require("json-stable-stringify-without-jsonify"),
|
|
22
|
+
{ isSerializable } = require("../shared/serialization");
|
|
22
23
|
|
|
23
24
|
const { FlatConfigArray } = require("../config/flat-config-array");
|
|
24
25
|
const {
|
|
@@ -30,7 +31,6 @@ const ajv = require("../shared/ajv")({ strictDefaults: true });
|
|
|
30
31
|
|
|
31
32
|
const parserSymbol = Symbol.for("eslint.RuleTester.parser");
|
|
32
33
|
const { ConfigArraySymbol } = require("@eslint/config-array");
|
|
33
|
-
const { isSerializable } = require("../shared/serialization");
|
|
34
34
|
|
|
35
35
|
const jslang = require("../languages/js");
|
|
36
36
|
const { SourceCode } = require("../languages/js/source-code");
|
|
@@ -78,7 +78,6 @@ const { SourceCode } = require("../languages/js/source-code");
|
|
|
78
78
|
* @typedef {Object} TestCaseError
|
|
79
79
|
* @property {string | RegExp} [message] Message.
|
|
80
80
|
* @property {string} [messageId] Message ID.
|
|
81
|
-
* @property {string} [type] The type of the reported AST node.
|
|
82
81
|
* @property {{ [name: string]: string }} [data] The data used to fill the message template.
|
|
83
82
|
* @property {number} [line] The 1-based line number of the reported start location.
|
|
84
83
|
* @property {number} [column] The 1-based column number of the reported start location.
|
|
@@ -125,7 +124,6 @@ const errorObjectParameters = new Set([
|
|
|
125
124
|
"message",
|
|
126
125
|
"messageId",
|
|
127
126
|
"data",
|
|
128
|
-
"type",
|
|
129
127
|
"line",
|
|
130
128
|
"column",
|
|
131
129
|
"endLine",
|
|
@@ -145,11 +143,6 @@ const suggestionObjectParameters = new Set([
|
|
|
145
143
|
]);
|
|
146
144
|
const friendlySuggestionObjectParameterList = `[${[...suggestionObjectParameters].map(key => `'${key}'`).join(", ")}]`;
|
|
147
145
|
|
|
148
|
-
/*
|
|
149
|
-
* Ignored test case properties when checking for test case duplicates.
|
|
150
|
-
*/
|
|
151
|
-
const duplicationIgnoredParameters = new Set(["name", "errors", "output"]);
|
|
152
|
-
|
|
153
146
|
const forbiddenMethods = [
|
|
154
147
|
"applyInlineConfig",
|
|
155
148
|
"applyLanguageOptions",
|
|
@@ -375,6 +368,211 @@ const metaSchemaDescription = `
|
|
|
375
368
|
\thttps://eslint.org/docs/latest/extend/custom-rules#options-schemas
|
|
376
369
|
`;
|
|
377
370
|
|
|
371
|
+
/*
|
|
372
|
+
* Ignored test case properties when checking for test case duplicates.
|
|
373
|
+
*/
|
|
374
|
+
const duplicationIgnoredParameters = new Set(["name", "errors", "output"]);
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Normalizes a test case item, ensuring it is an object with a 'code' property.
|
|
378
|
+
* If the item is not an object, it returns an object with the 'code' property set to the item.
|
|
379
|
+
* @param {any} item The test case item to normalize.
|
|
380
|
+
* @returns {Object} The normalized test case object.
|
|
381
|
+
*/
|
|
382
|
+
function normalizeTestCase(item) {
|
|
383
|
+
return item && typeof item === "object" ? item : { code: item };
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Asserts that the `errors` property of an invalid test case is valid.
|
|
388
|
+
* @param {number | string[]} errors The `errors` property of the invalid test case.
|
|
389
|
+
* @param {string} ruleName The name of the rule being tested.
|
|
390
|
+
* @returns {void}
|
|
391
|
+
*/
|
|
392
|
+
function assertErrorsProperty(errors, ruleName) {
|
|
393
|
+
const isNumber = typeof errors === "number";
|
|
394
|
+
const isArray = Array.isArray(errors);
|
|
395
|
+
|
|
396
|
+
if (!isNumber && !isArray) {
|
|
397
|
+
if (errors === void 0) {
|
|
398
|
+
assert.fail(
|
|
399
|
+
`Did not specify errors for an invalid test of ${ruleName}`,
|
|
400
|
+
);
|
|
401
|
+
} else {
|
|
402
|
+
assert.fail(
|
|
403
|
+
`Invalid 'errors' property for invalid test of ${ruleName}: expected a number or an array but got ${
|
|
404
|
+
errors === null ? "null" : typeof errors
|
|
405
|
+
}`,
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
if (isArray) {
|
|
411
|
+
assert.ok(
|
|
412
|
+
errors.length !== 0,
|
|
413
|
+
"Invalid cases must have at least one error",
|
|
414
|
+
);
|
|
415
|
+
} else {
|
|
416
|
+
assert.ok(
|
|
417
|
+
errors > 0,
|
|
418
|
+
"Invalid cases must have 'error' value greater than 0",
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Check if this test case is a duplicate of one we have seen before.
|
|
425
|
+
* @param {Object} item test case object
|
|
426
|
+
* @param {Set<string>} seenTestCases set of serialized test cases we have seen so far (managed by this function)
|
|
427
|
+
* @returns {void}
|
|
428
|
+
*/
|
|
429
|
+
function checkDuplicateTestCase(item, seenTestCases) {
|
|
430
|
+
if (!isSerializable(item)) {
|
|
431
|
+
/*
|
|
432
|
+
* If we can't serialize a test case (because it contains a function, RegExp, etc), skip the check.
|
|
433
|
+
* This might happen with properties like: options, plugins, settings, languageOptions.parser, languageOptions.parserOptions.
|
|
434
|
+
*/
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
const serializedTestCase = stringify(item, {
|
|
439
|
+
replacer(key, value) {
|
|
440
|
+
// "this" is the currently stringified object --> only ignore top-level properties
|
|
441
|
+
return item !== this || !duplicationIgnoredParameters.has(key)
|
|
442
|
+
? value
|
|
443
|
+
: void 0;
|
|
444
|
+
},
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
assert(
|
|
448
|
+
!seenTestCases.has(serializedTestCase),
|
|
449
|
+
"detected duplicate test case",
|
|
450
|
+
);
|
|
451
|
+
seenTestCases.add(serializedTestCase);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Asserts that a rule is valid.
|
|
456
|
+
* A valid rule must be an object with a `create` method.
|
|
457
|
+
* @param {Object} rule The rule to check.
|
|
458
|
+
* @param {string} ruleName The name of the rule.
|
|
459
|
+
* @returns {void}
|
|
460
|
+
* @throws {AssertionError} If the rule is not valid.
|
|
461
|
+
*/
|
|
462
|
+
function assertRule(rule, ruleName) {
|
|
463
|
+
assert.ok(
|
|
464
|
+
rule && typeof rule === "object" && typeof rule.create === "function",
|
|
465
|
+
`Rule ${ruleName} must be an object with a \`create\` method`,
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Asserts that a test scenario object is valid.
|
|
471
|
+
* A valid test scenario object must have `valid` and `invalid` properties, both of
|
|
472
|
+
* which must be arrays.
|
|
473
|
+
* @param {Object} test The test scenario object to check.
|
|
474
|
+
* @param {string} ruleName The name of the rule being tested.
|
|
475
|
+
* @returns {void}
|
|
476
|
+
* @throws {AssertionError} If the test scenario object is not valid.
|
|
477
|
+
*/
|
|
478
|
+
function assertTest(test, ruleName) {
|
|
479
|
+
assert.ok(
|
|
480
|
+
test && typeof test === "object",
|
|
481
|
+
`Test Scenarios for rule ${ruleName} : Could not find test scenario object`,
|
|
482
|
+
);
|
|
483
|
+
|
|
484
|
+
const hasValid = Array.isArray(test.valid);
|
|
485
|
+
const hasInvalid = Array.isArray(test.invalid);
|
|
486
|
+
|
|
487
|
+
assert.ok(
|
|
488
|
+
hasValid,
|
|
489
|
+
`Test Scenarios for rule ${ruleName} is invalid: Could not find any valid test scenarios`,
|
|
490
|
+
);
|
|
491
|
+
|
|
492
|
+
assert.ok(
|
|
493
|
+
hasInvalid,
|
|
494
|
+
`Test Scenarios for rule ${ruleName} is invalid: Could not find any invalid test scenarios`,
|
|
495
|
+
);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Asserts that the common properties of a valid/invalid test case have the correct types.
|
|
500
|
+
* @param {Object} item The test case object to check.
|
|
501
|
+
* @returns {void}
|
|
502
|
+
*/
|
|
503
|
+
function assertTestCommonProperties(item) {
|
|
504
|
+
assert.ok(
|
|
505
|
+
typeof item.code === "string",
|
|
506
|
+
"Test case must specify a string value for 'code'",
|
|
507
|
+
);
|
|
508
|
+
|
|
509
|
+
// optional properties
|
|
510
|
+
if (item.name) {
|
|
511
|
+
assert.ok(
|
|
512
|
+
typeof item.name === "string",
|
|
513
|
+
"Optional test case property 'name' must be a string",
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
if (hasOwnProperty(item, "only")) {
|
|
517
|
+
assert.ok(
|
|
518
|
+
typeof item.only === "boolean",
|
|
519
|
+
"Optional test case property 'only' must be a boolean",
|
|
520
|
+
);
|
|
521
|
+
}
|
|
522
|
+
if (hasOwnProperty(item, "filename")) {
|
|
523
|
+
assert.ok(
|
|
524
|
+
typeof item.filename === "string",
|
|
525
|
+
"Optional test case property 'filename' must be a string",
|
|
526
|
+
);
|
|
527
|
+
}
|
|
528
|
+
if (hasOwnProperty(item, "options")) {
|
|
529
|
+
assert.ok(
|
|
530
|
+
Array.isArray(item.options),
|
|
531
|
+
"Optional test case property 'options' must be an array",
|
|
532
|
+
);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Asserts that a valid test case object is valid.
|
|
538
|
+
* A valid test case must specify a string value for 'code'.
|
|
539
|
+
* Optional properties are checked for correct types.
|
|
540
|
+
* @param {Object} item The valid test case object to check.
|
|
541
|
+
* @param {Set<string>} seenTestCases Set of serialized test cases to check for duplicates.
|
|
542
|
+
* @returns {void}
|
|
543
|
+
* @throws {AssertionError} If the test case is not valid.
|
|
544
|
+
*/
|
|
545
|
+
function assertValidTestCase(item, seenTestCases) {
|
|
546
|
+
assertTestCommonProperties(item);
|
|
547
|
+
checkDuplicateTestCase(item, seenTestCases);
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* Asserts that the invalid test case object is valid.
|
|
552
|
+
* An invalid test case must specify a string value for 'code' and must have 'errors' property.
|
|
553
|
+
* Optional properties are checked for correct types.
|
|
554
|
+
* @param {Object} item The invalid test case object to check.
|
|
555
|
+
* @param {Set<string>} seenTestCases Set of serialized test cases to check for duplicates.
|
|
556
|
+
* @param {string} ruleName The name of the rule being tested.
|
|
557
|
+
* @returns {void}
|
|
558
|
+
* @throws {AssertionError} If the test case is not valid.
|
|
559
|
+
*/
|
|
560
|
+
function assertInvalidTestCase(item, seenTestCases, ruleName) {
|
|
561
|
+
assertTestCommonProperties(item);
|
|
562
|
+
|
|
563
|
+
assertErrorsProperty(item.errors, ruleName);
|
|
564
|
+
|
|
565
|
+
// 'output' is optional, but if it exists it must be a string or null
|
|
566
|
+
if (hasOwnProperty(item, "output")) {
|
|
567
|
+
assert.ok(
|
|
568
|
+
item.output === null || typeof item.output === "string",
|
|
569
|
+
"Test property 'output', if specified, must be a string or null. If no autofix is expected, then omit the 'output' property or set it to null.",
|
|
570
|
+
);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
checkDuplicateTestCase(item, seenTestCases);
|
|
574
|
+
}
|
|
575
|
+
|
|
378
576
|
//------------------------------------------------------------------------------
|
|
379
577
|
// Public Interface
|
|
380
578
|
//------------------------------------------------------------------------------
|
|
@@ -564,45 +762,11 @@ class RuleTester {
|
|
|
564
762
|
*/
|
|
565
763
|
run(ruleName, rule, test) {
|
|
566
764
|
const testerConfig = this.testerConfig,
|
|
567
|
-
requiredScenarios = ["valid", "invalid"],
|
|
568
|
-
scenarioErrors = [],
|
|
569
765
|
linter = this.linter,
|
|
570
766
|
ruleId = `rule-to-test/${ruleName}`;
|
|
571
767
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
if (
|
|
576
|
-
!rule ||
|
|
577
|
-
typeof rule !== "object" ||
|
|
578
|
-
typeof rule.create !== "function"
|
|
579
|
-
) {
|
|
580
|
-
throw new TypeError(
|
|
581
|
-
"Rule must be an object with a `create` method",
|
|
582
|
-
);
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
if (!test || typeof test !== "object") {
|
|
586
|
-
throw new TypeError(
|
|
587
|
-
`Test Scenarios for rule ${ruleName} : Could not find test scenario object`,
|
|
588
|
-
);
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
requiredScenarios.forEach(scenarioType => {
|
|
592
|
-
if (!test[scenarioType]) {
|
|
593
|
-
scenarioErrors.push(
|
|
594
|
-
`Could not find any ${scenarioType} test scenarios`,
|
|
595
|
-
);
|
|
596
|
-
}
|
|
597
|
-
});
|
|
598
|
-
|
|
599
|
-
if (scenarioErrors.length > 0) {
|
|
600
|
-
throw new Error(
|
|
601
|
-
[`Test Scenarios for rule ${ruleName} is invalid:`]
|
|
602
|
-
.concat(scenarioErrors)
|
|
603
|
-
.join("\n"),
|
|
604
|
-
);
|
|
605
|
-
}
|
|
768
|
+
assertRule(rule, ruleName);
|
|
769
|
+
assertTest(test, ruleName);
|
|
606
770
|
|
|
607
771
|
const baseConfig = [
|
|
608
772
|
{
|
|
@@ -651,14 +815,14 @@ class RuleTester {
|
|
|
651
815
|
|
|
652
816
|
/**
|
|
653
817
|
* Runs a hook on the given item when it's assigned to the given property
|
|
654
|
-
* @param {
|
|
818
|
+
* @param {Object} item Item to run the hook on
|
|
655
819
|
* @param {string} prop The property having the hook assigned to
|
|
656
820
|
* @throws {Error} If the property is not a function or that function throws an error
|
|
657
821
|
* @returns {void}
|
|
658
822
|
* @private
|
|
659
823
|
*/
|
|
660
824
|
function runHook(item, prop) {
|
|
661
|
-
if (
|
|
825
|
+
if (hasOwnProperty(item, prop)) {
|
|
662
826
|
assert.strictEqual(
|
|
663
827
|
typeof item[prop],
|
|
664
828
|
"function",
|
|
@@ -667,22 +831,26 @@ class RuleTester {
|
|
|
667
831
|
item[prop]();
|
|
668
832
|
}
|
|
669
833
|
}
|
|
670
|
-
|
|
671
834
|
/**
|
|
672
835
|
* Run the rule for the given item
|
|
673
|
-
* @param {
|
|
836
|
+
* @param {Object} item Item to run the rule against
|
|
674
837
|
* @throws {Error} If an invalid schema.
|
|
675
838
|
* @returns {Object} Eslint run result
|
|
676
839
|
* @private
|
|
677
840
|
*/
|
|
678
841
|
function runRuleForItem(item) {
|
|
842
|
+
const code = item.code;
|
|
843
|
+
const filename = hasOwnProperty(item, "filename")
|
|
844
|
+
? item.filename
|
|
845
|
+
: void 0;
|
|
846
|
+
const options = hasOwnProperty(item, "options") ? item.options : [];
|
|
679
847
|
const flatConfigArrayOptions = {
|
|
680
848
|
baseConfig,
|
|
681
849
|
};
|
|
682
850
|
|
|
683
|
-
if (
|
|
851
|
+
if (filename) {
|
|
684
852
|
flatConfigArrayOptions.basePath =
|
|
685
|
-
path.parse(
|
|
853
|
+
path.parse(filename).root || void 0;
|
|
686
854
|
}
|
|
687
855
|
|
|
688
856
|
const configs = new FlatConfigArray(
|
|
@@ -713,54 +881,27 @@ class RuleTester {
|
|
|
713
881
|
return calculatedConfig;
|
|
714
882
|
};
|
|
715
883
|
|
|
716
|
-
let
|
|
717
|
-
|
|
718
|
-
if (typeof item === "string") {
|
|
719
|
-
code = item;
|
|
720
|
-
} else {
|
|
721
|
-
code = item.code;
|
|
884
|
+
let output, beforeAST, afterAST;
|
|
722
885
|
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
for (const parameter of RuleTesterParameters) {
|
|
730
|
-
delete itemConfig[parameter];
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
/*
|
|
734
|
-
* Create the config object from the tester config and this item
|
|
735
|
-
* specific configurations.
|
|
736
|
-
*/
|
|
737
|
-
configs.push(itemConfig);
|
|
738
|
-
}
|
|
886
|
+
/*
|
|
887
|
+
* Assumes everything on the item is a config except for the
|
|
888
|
+
* parameters used by this tester
|
|
889
|
+
*/
|
|
890
|
+
const itemConfig = { ...item };
|
|
739
891
|
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
typeof item.only === "boolean",
|
|
743
|
-
"Optional test case property 'only' must be a boolean",
|
|
744
|
-
);
|
|
745
|
-
}
|
|
746
|
-
if (hasOwnProperty(item, "filename")) {
|
|
747
|
-
assert.ok(
|
|
748
|
-
typeof item.filename === "string",
|
|
749
|
-
"Optional test case property 'filename' must be a string",
|
|
750
|
-
);
|
|
751
|
-
filename = item.filename;
|
|
892
|
+
for (const parameter of RuleTesterParameters) {
|
|
893
|
+
delete itemConfig[parameter];
|
|
752
894
|
}
|
|
753
895
|
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
}
|
|
896
|
+
/*
|
|
897
|
+
* Create the config object from the tester config and this item
|
|
898
|
+
* specific configurations.
|
|
899
|
+
*/
|
|
900
|
+
configs.push(itemConfig);
|
|
760
901
|
|
|
761
902
|
configs.push({
|
|
762
903
|
rules: {
|
|
763
|
-
[ruleId]:
|
|
904
|
+
[ruleId]: [1, ...options],
|
|
764
905
|
},
|
|
765
906
|
});
|
|
766
907
|
|
|
@@ -939,64 +1080,14 @@ class RuleTester {
|
|
|
939
1080
|
}
|
|
940
1081
|
}
|
|
941
1082
|
|
|
942
|
-
/**
|
|
943
|
-
* Check if this test case is a duplicate of one we have seen before.
|
|
944
|
-
* @param {string|Object} item test case object
|
|
945
|
-
* @param {Set<string>} seenTestCases set of serialized test cases we have seen so far (managed by this function)
|
|
946
|
-
* @returns {void}
|
|
947
|
-
* @private
|
|
948
|
-
*/
|
|
949
|
-
function checkDuplicateTestCase(item, seenTestCases) {
|
|
950
|
-
if (!isSerializable(item)) {
|
|
951
|
-
/*
|
|
952
|
-
* If we can't serialize a test case (because it contains a function, RegExp, etc), skip the check.
|
|
953
|
-
* This might happen with properties like: options, plugins, settings, languageOptions.parser, languageOptions.parserOptions.
|
|
954
|
-
*/
|
|
955
|
-
return;
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
const normalizedItem =
|
|
959
|
-
typeof item === "string" ? { code: item } : item;
|
|
960
|
-
const serializedTestCase = stringify(normalizedItem, {
|
|
961
|
-
replacer(key, value) {
|
|
962
|
-
// "this" is the currently stringified object --> only ignore top-level properties
|
|
963
|
-
return normalizedItem !== this ||
|
|
964
|
-
!duplicationIgnoredParameters.has(key)
|
|
965
|
-
? value
|
|
966
|
-
: void 0;
|
|
967
|
-
},
|
|
968
|
-
});
|
|
969
|
-
|
|
970
|
-
assert(
|
|
971
|
-
!seenTestCases.has(serializedTestCase),
|
|
972
|
-
"detected duplicate test case",
|
|
973
|
-
);
|
|
974
|
-
seenTestCases.add(serializedTestCase);
|
|
975
|
-
}
|
|
976
|
-
|
|
977
1083
|
/**
|
|
978
1084
|
* Check if the template is valid or not
|
|
979
1085
|
* all valid cases go through this
|
|
980
|
-
* @param {
|
|
1086
|
+
* @param {Object} item Item to run the rule against
|
|
981
1087
|
* @returns {void}
|
|
982
1088
|
* @private
|
|
983
1089
|
*/
|
|
984
1090
|
function testValidTemplate(item) {
|
|
985
|
-
const code = typeof item === "object" ? item.code : item;
|
|
986
|
-
|
|
987
|
-
assert.ok(
|
|
988
|
-
typeof code === "string",
|
|
989
|
-
"Test case must specify a string value for 'code'",
|
|
990
|
-
);
|
|
991
|
-
if (item.name) {
|
|
992
|
-
assert.ok(
|
|
993
|
-
typeof item.name === "string",
|
|
994
|
-
"Optional test case property 'name' must be a string",
|
|
995
|
-
);
|
|
996
|
-
}
|
|
997
|
-
|
|
998
|
-
checkDuplicateTestCase(item, seenValidTestCases);
|
|
999
|
-
|
|
1000
1091
|
const result = runRuleForItem(item);
|
|
1001
1092
|
const messages = result.messages;
|
|
1002
1093
|
|
|
@@ -1037,32 +1128,11 @@ class RuleTester {
|
|
|
1037
1128
|
/**
|
|
1038
1129
|
* Check if the template is invalid or not
|
|
1039
1130
|
* all invalid cases go through this.
|
|
1040
|
-
* @param {
|
|
1131
|
+
* @param {Object} item Item to run the rule against
|
|
1041
1132
|
* @returns {void}
|
|
1042
1133
|
* @private
|
|
1043
1134
|
*/
|
|
1044
1135
|
function testInvalidTemplate(item) {
|
|
1045
|
-
assert.ok(
|
|
1046
|
-
typeof item.code === "string",
|
|
1047
|
-
"Test case must specify a string value for 'code'",
|
|
1048
|
-
);
|
|
1049
|
-
if (item.name) {
|
|
1050
|
-
assert.ok(
|
|
1051
|
-
typeof item.name === "string",
|
|
1052
|
-
"Optional test case property 'name' must be a string",
|
|
1053
|
-
);
|
|
1054
|
-
}
|
|
1055
|
-
assert.ok(
|
|
1056
|
-
item.errors || item.errors === 0,
|
|
1057
|
-
`Did not specify errors for an invalid test of ${ruleName}`,
|
|
1058
|
-
);
|
|
1059
|
-
|
|
1060
|
-
if (Array.isArray(item.errors) && item.errors.length === 0) {
|
|
1061
|
-
assert.fail("Invalid cases must have at least one error");
|
|
1062
|
-
}
|
|
1063
|
-
|
|
1064
|
-
checkDuplicateTestCase(item, seenInvalidTestCases);
|
|
1065
|
-
|
|
1066
1136
|
const ruleHasMetaMessages =
|
|
1067
1137
|
hasOwnProperty(rule, "meta") &&
|
|
1068
1138
|
hasOwnProperty(rule.meta, "messages");
|
|
@@ -1095,12 +1165,6 @@ class RuleTester {
|
|
|
1095
1165
|
}
|
|
1096
1166
|
|
|
1097
1167
|
if (typeof item.errors === "number") {
|
|
1098
|
-
if (item.errors === 0) {
|
|
1099
|
-
assert.fail(
|
|
1100
|
-
"Invalid cases must have 'error' value greater than 0",
|
|
1101
|
-
);
|
|
1102
|
-
}
|
|
1103
|
-
|
|
1104
1168
|
assert.strictEqual(
|
|
1105
1169
|
messages.length,
|
|
1106
1170
|
item.errors,
|
|
@@ -1148,8 +1212,7 @@ class RuleTester {
|
|
|
1148
1212
|
} else if (typeof error === "object" && error !== null) {
|
|
1149
1213
|
/*
|
|
1150
1214
|
* Error object.
|
|
1151
|
-
* This may have a message, messageId, data,
|
|
1152
|
-
* column.
|
|
1215
|
+
* This may have a message, messageId, data, line, and/or column.
|
|
1153
1216
|
*/
|
|
1154
1217
|
|
|
1155
1218
|
Object.keys(error).forEach(propertyName => {
|
|
@@ -1231,14 +1294,6 @@ class RuleTester {
|
|
|
1231
1294
|
);
|
|
1232
1295
|
}
|
|
1233
1296
|
|
|
1234
|
-
if (error.type) {
|
|
1235
|
-
assert.strictEqual(
|
|
1236
|
-
message.nodeType,
|
|
1237
|
-
error.type,
|
|
1238
|
-
`Error type should be ${error.type}, found ${message.nodeType}`,
|
|
1239
|
-
);
|
|
1240
|
-
}
|
|
1241
|
-
|
|
1242
1297
|
const actualLocation = {};
|
|
1243
1298
|
const expectedLocation = {};
|
|
1244
1299
|
|
|
@@ -1533,19 +1588,18 @@ class RuleTester {
|
|
|
1533
1588
|
this.constructor.describe(ruleName, () => {
|
|
1534
1589
|
if (test.valid.length > 0) {
|
|
1535
1590
|
this.constructor.describe("valid", () => {
|
|
1591
|
+
const seenTestCases = new Set();
|
|
1536
1592
|
test.valid.forEach(valid => {
|
|
1593
|
+
const item = normalizeTestCase(valid);
|
|
1537
1594
|
this.constructor[valid.only ? "itOnly" : "it"](
|
|
1538
|
-
sanitize(
|
|
1539
|
-
typeof valid === "object"
|
|
1540
|
-
? valid.name || valid.code
|
|
1541
|
-
: valid,
|
|
1542
|
-
),
|
|
1595
|
+
sanitize(item.name || item.code),
|
|
1543
1596
|
() => {
|
|
1544
1597
|
try {
|
|
1545
|
-
runHook(
|
|
1546
|
-
|
|
1598
|
+
runHook(item, "before");
|
|
1599
|
+
assertValidTestCase(item, seenTestCases);
|
|
1600
|
+
testValidTemplate(item);
|
|
1547
1601
|
} finally {
|
|
1548
|
-
runHook(
|
|
1602
|
+
runHook(item, "after");
|
|
1549
1603
|
}
|
|
1550
1604
|
},
|
|
1551
1605
|
);
|
|
@@ -1555,15 +1609,22 @@ class RuleTester {
|
|
|
1555
1609
|
|
|
1556
1610
|
if (test.invalid.length > 0) {
|
|
1557
1611
|
this.constructor.describe("invalid", () => {
|
|
1612
|
+
const seenTestCases = new Set();
|
|
1558
1613
|
test.invalid.forEach(invalid => {
|
|
1559
|
-
|
|
1560
|
-
|
|
1614
|
+
const item = normalizeTestCase(invalid);
|
|
1615
|
+
this.constructor[item.only ? "itOnly" : "it"](
|
|
1616
|
+
sanitize(item.name || item.code),
|
|
1561
1617
|
() => {
|
|
1562
1618
|
try {
|
|
1563
|
-
runHook(
|
|
1564
|
-
|
|
1619
|
+
runHook(item, "before");
|
|
1620
|
+
assertInvalidTestCase(
|
|
1621
|
+
item,
|
|
1622
|
+
seenTestCases,
|
|
1623
|
+
ruleName,
|
|
1624
|
+
);
|
|
1625
|
+
testInvalidTemplate(item);
|
|
1565
1626
|
} finally {
|
|
1566
|
-
runHook(
|
|
1627
|
+
runHook(item, "after");
|
|
1567
1628
|
}
|
|
1568
1629
|
},
|
|
1569
1630
|
);
|
|
@@ -76,7 +76,7 @@ module.exports = {
|
|
|
76
76
|
/**
|
|
77
77
|
* Check if the property is valid dot notation
|
|
78
78
|
* @param {ASTNode} node The dot notation node
|
|
79
|
-
* @param {string} value Value which is to be checked
|
|
79
|
+
* @param {string|boolean|null} value Value which is to be checked
|
|
80
80
|
* @returns {void}
|
|
81
81
|
*/
|
|
82
82
|
function checkComputedProperty(node, value) {
|
|
@@ -125,7 +125,7 @@ module.exports = {
|
|
|
125
125
|
}
|
|
126
126
|
yield fixer.replaceTextRange(
|
|
127
127
|
[leftBracket.range[0], rightBracket.range[1]],
|
|
128
|
-
value,
|
|
128
|
+
String(value),
|
|
129
129
|
);
|
|
130
130
|
|
|
131
131
|
// Insert a space after the property if it will be connected to the next token.
|
package/lib/rules/func-names.js
CHANGED
|
@@ -43,6 +43,7 @@ module.exports = {
|
|
|
43
43
|
enum: ["always", "as-needed", "never"],
|
|
44
44
|
},
|
|
45
45
|
},
|
|
46
|
+
type: "array",
|
|
46
47
|
items: [
|
|
47
48
|
{
|
|
48
49
|
$ref: "#/definitions/value",
|
|
@@ -57,6 +58,7 @@ module.exports = {
|
|
|
57
58
|
additionalProperties: false,
|
|
58
59
|
},
|
|
59
60
|
],
|
|
61
|
+
additionalItems: false,
|
|
60
62
|
},
|
|
61
63
|
|
|
62
64
|
messages: {
|
package/lib/rules/no-eval.js
CHANGED
|
@@ -158,7 +158,7 @@ module.exports = {
|
|
|
158
158
|
docs: {
|
|
159
159
|
description:
|
|
160
160
|
"Disallow losing originally caught error when re-throwing custom errors",
|
|
161
|
-
recommended:
|
|
161
|
+
recommended: true,
|
|
162
162
|
url: "https://eslint.org/docs/latest/rules/preserve-caught-error", // URL to the documentation page for this rule
|
|
163
163
|
},
|
|
164
164
|
/*
|