eslint 7.28.0 → 7.29.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/CHANGELOG.md +15 -0
- package/README.md +2 -2
- package/lib/eslint/eslint.js +38 -2
- package/lib/init/npm-utils.js +1 -2
- package/lib/rule-tester/rule-tester.js +69 -13
- package/lib/rules/comma-style.js +1 -2
- package/lib/rules/indent.js +2 -4
- package/lib/rules/no-fallthrough.js +17 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
v7.29.0 - June 18, 2021
|
2
|
+
|
3
|
+
* [`bfbfe5c`](https://github.com/eslint/eslint/commit/bfbfe5c1fd4c39a06d5e159dbe48479ca4305fc0) New: Add only to RuleTester (refs eslint/rfcs#73) (#14677) (Brandon Mills)
|
4
|
+
* [`c2cd7b4`](https://github.com/eslint/eslint/commit/c2cd7b4a18057ca6067bdfc16de771dc5d90c0ea) New: Add ESLint#getRulesMetaForResults() (refs #13654) (#14716) (Nicholas C. Zakas)
|
5
|
+
* [`eea7e0d`](https://github.com/eslint/eslint/commit/eea7e0d09d6ef43d6663cbe424e7974764a5f7fe) Chore: remove duplicate code (#14719) (Nitin Kumar)
|
6
|
+
* [`6a1c7a0`](https://github.com/eslint/eslint/commit/6a1c7a0dac050ea5876972c50563a7eb867b38d3) Fix: allow fallthrough comment inside block (fixes #14701) (#14702) (Kevin Gibbons)
|
7
|
+
* [`a47e5e3`](https://github.com/eslint/eslint/commit/a47e5e30b0da364593b6881f6826c595da8696f5) Docs: Add Mega-Linter to the list of integrations (#14707) (Nicolas Vuillamy)
|
8
|
+
* [`353ddf9`](https://github.com/eslint/eslint/commit/353ddf965078030794419b089994373e27ffc86e) Chore: enable reportUnusedDisableDirectives in eslint-config-eslint (#14699) (薛定谔的猫)
|
9
|
+
* [`757c495`](https://github.com/eslint/eslint/commit/757c49584a5852c468c1b4a0b74ad3aa39d954e5) Chore: add some rules to eslint-config-eslint (#14692) (薛定谔的猫)
|
10
|
+
* [`c93a222`](https://github.com/eslint/eslint/commit/c93a222563177a9b5bc7a59aa106bc0a6d31e063) Docs: fix a broken link (#14697) (Sam Chen)
|
11
|
+
* [`655c118`](https://github.com/eslint/eslint/commit/655c1187fc845bac61ae8d06c556f1a59ee2071b) Sponsors: Sync README with website (ESLint Jenkins)
|
12
|
+
* [`e2bed2e`](https://github.com/eslint/eslint/commit/e2bed2ead22b575d55ccaeed94eecd3a979dd871) Sponsors: Sync README with website (ESLint Jenkins)
|
13
|
+
* [`8490fb4`](https://github.com/eslint/eslint/commit/8490fb42e559ef0b3c34ac60be4e05e0d879a9cb) Sponsors: Sync README with website (ESLint Jenkins)
|
14
|
+
* [`ddbe877`](https://github.com/eslint/eslint/commit/ddbe877c95224e127215d35562a175c6f2b7ba22) Sponsors: Sync README with website (ESLint Jenkins)
|
15
|
+
|
1
16
|
v7.28.0 - June 4, 2021
|
2
17
|
|
3
18
|
* [`1237705`](https://github.com/eslint/eslint/commit/1237705dd08c209c5e3136045ec51a4ba87a3abe) Upgrade: @eslint/eslintrc to 0.4.2 (#14672) (Milos Djermanovic)
|
package/README.md
CHANGED
@@ -281,9 +281,9 @@ The following companies, organizations, and individuals support ESLint's ongoing
|
|
281
281
|
<!--sponsorsstart-->
|
282
282
|
<h3>Platinum Sponsors</h3>
|
283
283
|
<p><a href="https://automattic.com"><img src="https://images.opencollective.com/photomatt/d0ef3e1/logo.png" alt="Automattic" height="undefined"></a></p><h3>Gold Sponsors</h3>
|
284
|
-
<p><a href="https://nx.dev"><img src="https://images.opencollective.com/nx/0efbe42/logo.png" alt="Nx (by Nrwl)" height="96"></a> <a href="https://google.com/chrome"><img src="https://images.opencollective.com/chrome/dc55bd4/logo.png" alt="Chrome's Web Framework & Tools Performance Fund" height="96"></a> <a href="https://www.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a> <a href="https://substack.com/"><img src="https://avatars.githubusercontent.com/u/53023767?v=4" alt="Substack" height="96"></a></p><h3>Silver Sponsors</h3>
|
284
|
+
<p><a href="https://nx.dev"><img src="https://images.opencollective.com/nx/0efbe42/logo.png" alt="Nx (by Nrwl)" height="96"></a> <a href="https://google.com/chrome"><img src="https://images.opencollective.com/chrome/dc55bd4/logo.png" alt="Chrome's Web Framework & Tools Performance Fund" height="96"></a> <a href="https://www.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a> <a href="https://coinbase.com"><img src="https://avatars.githubusercontent.com/u/1885080?v=4" alt="Coinbase" height="96"></a> <a href="https://substack.com/"><img src="https://avatars.githubusercontent.com/u/53023767?v=4" alt="Substack" height="96"></a></p><h3>Silver Sponsors</h3>
|
285
285
|
<p><a href="https://retool.com/"><img src="https://images.opencollective.com/retool/98ea68e/logo.png" alt="Retool" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a></p><h3>Bronze Sponsors</h3>
|
286
|
-
<p><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="null"><img src="https://images.opencollective.com/bugsnag-stability-monitoring/c2cef36/logo.png" alt="Bugsnag Stability Monitoring" height="32"></a> <a href="https://mixpanel.com"><img src="https://images.opencollective.com/mixpanel/cd682f7/logo.png" alt="Mixpanel" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8: free icons, photos, illustrations, and music" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a></p>
|
286
|
+
<p><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="null"><img src="https://images.opencollective.com/bugsnag-stability-monitoring/c2cef36/logo.png" alt="Bugsnag Stability Monitoring" height="32"></a> <a href="https://mixpanel.com"><img src="https://images.opencollective.com/mixpanel/cd682f7/logo.png" alt="Mixpanel" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8: free icons, photos, illustrations, and music" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a> <a href="https://www.practiceignition.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Practice Ignition" height="32"></a></p>
|
287
287
|
<!--sponsorsend-->
|
288
288
|
|
289
289
|
## <a name="technology-sponsors"></a>Technology Sponsors
|
package/lib/eslint/eslint.js
CHANGED
@@ -514,6 +514,39 @@ class ESLint {
|
|
514
514
|
return CLIEngine.getErrorResults(results);
|
515
515
|
}
|
516
516
|
|
517
|
+
/**
|
518
|
+
* Returns meta objects for each rule represented in the lint results.
|
519
|
+
* @param {LintResult[]} results The results to fetch rules meta for.
|
520
|
+
* @returns {Object} A mapping of ruleIds to rule meta objects.
|
521
|
+
*/
|
522
|
+
getRulesMetaForResults(results) {
|
523
|
+
|
524
|
+
const resultRuleIds = new Set();
|
525
|
+
|
526
|
+
// first gather all ruleIds from all results
|
527
|
+
|
528
|
+
for (const result of results) {
|
529
|
+
for (const { ruleId } of result.messages) {
|
530
|
+
resultRuleIds.add(ruleId);
|
531
|
+
}
|
532
|
+
}
|
533
|
+
|
534
|
+
// create a map of all rules in the results
|
535
|
+
|
536
|
+
const { cliEngine } = privateMembersMap.get(this);
|
537
|
+
const rules = cliEngine.getRules();
|
538
|
+
const resultRules = new Map();
|
539
|
+
|
540
|
+
for (const [ruleId, rule] of rules) {
|
541
|
+
if (resultRuleIds.has(ruleId)) {
|
542
|
+
resultRules.set(ruleId, rule);
|
543
|
+
}
|
544
|
+
}
|
545
|
+
|
546
|
+
return createRulesMeta(resultRules);
|
547
|
+
|
548
|
+
}
|
549
|
+
|
517
550
|
/**
|
518
551
|
* Executes the current configuration on an array of file and directory names.
|
519
552
|
* @param {string[]} patterns An array of file and directory names.
|
@@ -552,9 +585,12 @@ class ESLint {
|
|
552
585
|
...unknownOptions
|
553
586
|
} = options || {};
|
554
587
|
|
555
|
-
|
556
|
-
|
588
|
+
const unknownOptionKeys = Object.keys(unknownOptions);
|
589
|
+
|
590
|
+
if (unknownOptionKeys.length > 0) {
|
591
|
+
throw new Error(`'options' must not include the unknown option(s): ${unknownOptionKeys.join(", ")}`);
|
557
592
|
}
|
593
|
+
|
558
594
|
if (filePath !== void 0 && !isNonEmptyString(filePath)) {
|
559
595
|
throw new Error("'options.filePath' must be a non-empty string or undefined");
|
560
596
|
}
|
package/lib/init/npm-utils.js
CHANGED
@@ -50,8 +50,7 @@ function findPackageJson(startDir) {
|
|
50
50
|
*/
|
51
51
|
function installSyncSaveDev(packages) {
|
52
52
|
const packageList = Array.isArray(packages) ? packages : [packages];
|
53
|
-
const npmProcess = spawn.sync("npm", ["i", "--save-dev"].concat(packageList),
|
54
|
-
{ stdio: "inherit" });
|
53
|
+
const npmProcess = spawn.sync("npm", ["i", "--save-dev"].concat(packageList), { stdio: "inherit" });
|
55
54
|
const error = npmProcess.error;
|
56
55
|
|
57
56
|
if (error && error.code === "ENOENT") {
|
@@ -71,6 +71,7 @@ const espreePath = require.resolve("espree");
|
|
71
71
|
* @property {{ [name: string]: any }} [parserOptions] Options for the parser.
|
72
72
|
* @property {{ [name: string]: "readonly" | "writable" | "off" }} [globals] The additional global variables.
|
73
73
|
* @property {{ [name: string]: boolean }} [env] Environments for the test case.
|
74
|
+
* @property {boolean} [only] Run only this test case or the subset of test cases with this property.
|
74
75
|
*/
|
75
76
|
|
76
77
|
/**
|
@@ -86,6 +87,7 @@ const espreePath = require.resolve("espree");
|
|
86
87
|
* @property {{ [name: string]: any }} [parserOptions] Options for the parser.
|
87
88
|
* @property {{ [name: string]: "readonly" | "writable" | "off" }} [globals] The additional global variables.
|
88
89
|
* @property {{ [name: string]: boolean }} [env] Environments for the test case.
|
90
|
+
* @property {boolean} [only] Run only this test case or the subset of test cases with this property.
|
89
91
|
*/
|
90
92
|
|
91
93
|
/**
|
@@ -121,7 +123,8 @@ const RuleTesterParameters = [
|
|
121
123
|
"filename",
|
122
124
|
"options",
|
123
125
|
"errors",
|
124
|
-
"output"
|
126
|
+
"output",
|
127
|
+
"only"
|
125
128
|
];
|
126
129
|
|
127
130
|
/*
|
@@ -282,6 +285,7 @@ function wrapParser(parser) {
|
|
282
285
|
// default separators for testing
|
283
286
|
const DESCRIBE = Symbol("describe");
|
284
287
|
const IT = Symbol("it");
|
288
|
+
const IT_ONLY = Symbol("itOnly");
|
285
289
|
|
286
290
|
/**
|
287
291
|
* This is `it` default handler if `it` don't exist.
|
@@ -400,6 +404,46 @@ class RuleTester {
|
|
400
404
|
this[IT] = value;
|
401
405
|
}
|
402
406
|
|
407
|
+
/**
|
408
|
+
* Adds the `only` property to a test to run it in isolation.
|
409
|
+
* @param {string | ValidTestCase | InvalidTestCase} item A single test to run by itself.
|
410
|
+
* @returns {ValidTestCase | InvalidTestCase} The test with `only` set.
|
411
|
+
*/
|
412
|
+
static only(item) {
|
413
|
+
if (typeof item === "string") {
|
414
|
+
return { code: item, only: true };
|
415
|
+
}
|
416
|
+
|
417
|
+
return { ...item, only: true };
|
418
|
+
}
|
419
|
+
|
420
|
+
static get itOnly() {
|
421
|
+
if (typeof this[IT_ONLY] === "function") {
|
422
|
+
return this[IT_ONLY];
|
423
|
+
}
|
424
|
+
if (typeof this[IT] === "function" && typeof this[IT].only === "function") {
|
425
|
+
return Function.bind.call(this[IT].only, this[IT]);
|
426
|
+
}
|
427
|
+
if (typeof it === "function" && typeof it.only === "function") {
|
428
|
+
return Function.bind.call(it.only, it);
|
429
|
+
}
|
430
|
+
|
431
|
+
if (typeof this[DESCRIBE] === "function" || typeof this[IT] === "function") {
|
432
|
+
throw new Error(
|
433
|
+
"Set `RuleTester.itOnly` to use `only` with a custom test framework.\n" +
|
434
|
+
"See https://eslint.org/docs/developer-guide/nodejs-api#customizing-ruletester for more."
|
435
|
+
);
|
436
|
+
}
|
437
|
+
if (typeof it === "function") {
|
438
|
+
throw new Error("The current test framework does not support exclusive tests with `only`.");
|
439
|
+
}
|
440
|
+
throw new Error("To use `only`, use RuleTester with a test framework that provides `it.only()` like Mocha.");
|
441
|
+
}
|
442
|
+
|
443
|
+
static set itOnly(value) {
|
444
|
+
this[IT_ONLY] = value;
|
445
|
+
}
|
446
|
+
|
403
447
|
/**
|
404
448
|
* Define a rule for one particular run of tests.
|
405
449
|
* @param {string} name The name of the rule to define.
|
@@ -610,7 +654,8 @@ class RuleTester {
|
|
610
654
|
const messages = result.messages;
|
611
655
|
|
612
656
|
assert.strictEqual(messages.length, 0, util.format("Should have no errors but had %d: %s",
|
613
|
-
messages.length,
|
657
|
+
messages.length,
|
658
|
+
util.inspect(messages)));
|
614
659
|
|
615
660
|
assertASTDidntChange(result.beforeAST, result.afterAST);
|
616
661
|
}
|
@@ -665,13 +710,18 @@ class RuleTester {
|
|
665
710
|
}
|
666
711
|
|
667
712
|
assert.strictEqual(messages.length, item.errors, util.format("Should have %d error%s but had %d: %s",
|
668
|
-
item.errors,
|
713
|
+
item.errors,
|
714
|
+
item.errors === 1 ? "" : "s",
|
715
|
+
messages.length,
|
716
|
+
util.inspect(messages)));
|
669
717
|
} else {
|
670
718
|
assert.strictEqual(
|
671
|
-
messages.length, item.errors.length,
|
672
|
-
util.format(
|
719
|
+
messages.length, item.errors.length, util.format(
|
673
720
|
"Should have %d error%s but had %d: %s",
|
674
|
-
item.errors.length,
|
721
|
+
item.errors.length,
|
722
|
+
item.errors.length === 1 ? "" : "s",
|
723
|
+
messages.length,
|
724
|
+
util.inspect(messages)
|
675
725
|
)
|
676
726
|
);
|
677
727
|
|
@@ -885,23 +935,29 @@ class RuleTester {
|
|
885
935
|
RuleTester.describe(ruleName, () => {
|
886
936
|
RuleTester.describe("valid", () => {
|
887
937
|
test.valid.forEach(valid => {
|
888
|
-
RuleTester.
|
889
|
-
|
890
|
-
|
938
|
+
RuleTester[valid.only ? "itOnly" : "it"](
|
939
|
+
sanitize(typeof valid === "object" ? valid.code : valid),
|
940
|
+
() => {
|
941
|
+
testValidTemplate(valid);
|
942
|
+
}
|
943
|
+
);
|
891
944
|
});
|
892
945
|
});
|
893
946
|
|
894
947
|
RuleTester.describe("invalid", () => {
|
895
948
|
test.invalid.forEach(invalid => {
|
896
|
-
RuleTester
|
897
|
-
|
898
|
-
|
949
|
+
RuleTester[invalid.only ? "itOnly" : "it"](
|
950
|
+
sanitize(invalid.code),
|
951
|
+
() => {
|
952
|
+
testInvalidTemplate(invalid);
|
953
|
+
}
|
954
|
+
);
|
899
955
|
});
|
900
956
|
});
|
901
957
|
});
|
902
958
|
}
|
903
959
|
}
|
904
960
|
|
905
|
-
RuleTester[DESCRIBE] = RuleTester[IT] = null;
|
961
|
+
RuleTester[DESCRIBE] = RuleTester[IT] = RuleTester[IT_ONLY] = null;
|
906
962
|
|
907
963
|
module.exports = RuleTester;
|
package/lib/rules/comma-style.js
CHANGED
@@ -207,8 +207,7 @@ module.exports = {
|
|
207
207
|
* they are always valid regardless of an undefined item.
|
208
208
|
*/
|
209
209
|
if (astUtils.isCommaToken(commaToken)) {
|
210
|
-
validateCommaItemSpacing(previousItemToken, commaToken,
|
211
|
-
currentItemToken, reportItem);
|
210
|
+
validateCommaItemSpacing(previousItemToken, commaToken, currentItemToken, reportItem);
|
212
211
|
}
|
213
212
|
|
214
213
|
if (item) {
|
package/lib/rules/indent.js
CHANGED
@@ -1177,8 +1177,7 @@ module.exports = {
|
|
1177
1177
|
offsets.setDesiredOffset(questionMarkToken, firstToken, 1);
|
1178
1178
|
offsets.setDesiredOffset(colonToken, firstToken, 1);
|
1179
1179
|
|
1180
|
-
offsets.setDesiredOffset(firstConsequentToken, firstToken,
|
1181
|
-
firstConsequentToken.type === "Punctuator" &&
|
1180
|
+
offsets.setDesiredOffset(firstConsequentToken, firstToken, firstConsequentToken.type === "Punctuator" &&
|
1182
1181
|
options.offsetTernaryExpressions ? 2 : 1);
|
1183
1182
|
|
1184
1183
|
/*
|
@@ -1204,8 +1203,7 @@ module.exports = {
|
|
1204
1203
|
* If `baz` were aligned with `bar` rather than being offset by 1 from `foo`, `baz` would end up
|
1205
1204
|
* having no expected indentation.
|
1206
1205
|
*/
|
1207
|
-
offsets.setDesiredOffset(firstAlternateToken, firstToken,
|
1208
|
-
firstAlternateToken.type === "Punctuator" &&
|
1206
|
+
offsets.setDesiredOffset(firstAlternateToken, firstToken, firstAlternateToken.type === "Punctuator" &&
|
1209
1207
|
options.offsetTernaryExpressions ? 2 : 1);
|
1210
1208
|
}
|
1211
1209
|
}
|
@@ -11,15 +11,26 @@
|
|
11
11
|
const DEFAULT_FALLTHROUGH_COMMENT = /falls?\s?through/iu;
|
12
12
|
|
13
13
|
/**
|
14
|
-
* Checks whether or not a given
|
15
|
-
* @param {ASTNode}
|
14
|
+
* Checks whether or not a given case has a fallthrough comment.
|
15
|
+
* @param {ASTNode} caseWhichFallsThrough SwitchCase node which falls through.
|
16
|
+
* @param {ASTNode} subsequentCase The case after caseWhichFallsThrough.
|
16
17
|
* @param {RuleContext} context A rule context which stores comments.
|
17
18
|
* @param {RegExp} fallthroughCommentPattern A pattern to match comment to.
|
18
|
-
* @returns {boolean} `true` if the
|
19
|
+
* @returns {boolean} `true` if the case has a valid fallthrough comment.
|
19
20
|
*/
|
20
|
-
function hasFallthroughComment(
|
21
|
+
function hasFallthroughComment(caseWhichFallsThrough, subsequentCase, context, fallthroughCommentPattern) {
|
21
22
|
const sourceCode = context.getSourceCode();
|
22
|
-
|
23
|
+
|
24
|
+
if (caseWhichFallsThrough.consequent.length === 1 && caseWhichFallsThrough.consequent[0].type === "BlockStatement") {
|
25
|
+
const trailingCloseBrace = sourceCode.getLastToken(caseWhichFallsThrough.consequent[0]);
|
26
|
+
const commentInBlock = sourceCode.getCommentsBefore(trailingCloseBrace).pop();
|
27
|
+
|
28
|
+
if (commentInBlock && fallthroughCommentPattern.test(commentInBlock.value)) {
|
29
|
+
return true;
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
const comment = sourceCode.getCommentsBefore(subsequentCase).pop();
|
23
34
|
|
24
35
|
return Boolean(comment && fallthroughCommentPattern.test(comment.value));
|
25
36
|
}
|
@@ -108,7 +119,7 @@ module.exports = {
|
|
108
119
|
* Checks whether or not there is a fallthrough comment.
|
109
120
|
* And reports the previous fallthrough node if that does not exist.
|
110
121
|
*/
|
111
|
-
if (fallthroughCase && !hasFallthroughComment(node, context, fallthroughCommentPattern)) {
|
122
|
+
if (fallthroughCase && !hasFallthroughComment(fallthroughCase, node, context, fallthroughCommentPattern)) {
|
112
123
|
context.report({
|
113
124
|
messageId: node.test ? "case" : "default",
|
114
125
|
node
|