eslint 10.0.0-alpha.0 → 10.0.0-beta.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 +1 -1
- package/lib/api.js +2 -2
- package/lib/cli-engine/formatters/stylish.js +65 -34
- package/lib/cli.js +18 -8
- package/lib/eslint/eslint.js +4 -2
- package/lib/languages/js/index.js +1 -0
- package/lib/languages/js/source-code/source-code.js +27 -165
- package/lib/languages/js/source-code/token-store/index.js +0 -26
- package/lib/linter/linter.js +1 -0
- package/lib/rule-tester/rule-tester.js +117 -43
- package/lib/rules/array-bracket-spacing.js +4 -4
- package/lib/rules/block-spacing.js +1 -1
- package/lib/rules/comma-spacing.js +2 -5
- package/lib/rules/computed-property-spacing.js +4 -4
- package/lib/rules/keyword-spacing.js +4 -4
- package/lib/rules/no-extra-parens.js +1 -1
- package/lib/rules/no-restricted-imports.js +56 -14
- package/lib/rules/no-spaced-func.js +1 -1
- package/lib/rules/no-useless-assignment.js +8 -5
- package/lib/rules/no-useless-constructor.js +13 -3
- package/lib/rules/no-whitespace-before-property.js +1 -1
- package/lib/rules/object-curly-spacing.js +2 -8
- package/lib/rules/require-yield.js +11 -1
- package/lib/rules/rest-spread-spacing.js +1 -4
- package/lib/rules/semi-spacing.js +2 -2
- package/lib/rules/space-before-blocks.js +1 -1
- package/lib/rules/space-before-function-paren.js +1 -4
- package/lib/rules/space-in-parens.js +4 -4
- package/lib/rules/space-infix-ops.js +4 -7
- package/lib/rules/switch-colon-spacing.js +1 -1
- package/lib/rules/template-tag-spacing.js +1 -1
- package/lib/rules/utils/ast-utils.js +117 -22
- package/lib/rules/yield-star-spacing.js +1 -2
- package/lib/types/index.d.ts +59 -36
- package/lib/types/use-at-your-own-risk.d.ts +1 -1
- package/package.json +5 -6
|
@@ -387,9 +387,10 @@ function normalizeTestCase(item) {
|
|
|
387
387
|
* Asserts that the `errors` property of an invalid test case is valid.
|
|
388
388
|
* @param {number | string[]} errors The `errors` property of the invalid test case.
|
|
389
389
|
* @param {string} ruleName The name of the rule being tested.
|
|
390
|
+
* @param {Object} [assertionOptions] The assertion options for the test case.
|
|
390
391
|
* @returns {void}
|
|
391
392
|
*/
|
|
392
|
-
function assertErrorsProperty(errors, ruleName) {
|
|
393
|
+
function assertErrorsProperty(errors, ruleName, assertionOptions = {}) {
|
|
393
394
|
const isNumber = typeof errors === "number";
|
|
394
395
|
const isArray = Array.isArray(errors);
|
|
395
396
|
|
|
@@ -407,12 +408,75 @@ function assertErrorsProperty(errors, ruleName) {
|
|
|
407
408
|
}
|
|
408
409
|
}
|
|
409
410
|
|
|
411
|
+
const { requireMessage = false, requireLocation = false } =
|
|
412
|
+
assertionOptions;
|
|
413
|
+
|
|
410
414
|
if (isArray) {
|
|
411
415
|
assert.ok(
|
|
412
416
|
errors.length !== 0,
|
|
413
417
|
"Invalid cases must have at least one error",
|
|
414
418
|
);
|
|
419
|
+
|
|
420
|
+
for (const [number, error] of errors.entries()) {
|
|
421
|
+
if (typeof error === "string" || error instanceof RegExp) {
|
|
422
|
+
// Just an error message.
|
|
423
|
+
assert.ok(
|
|
424
|
+
requireMessage !== "messageId" && !requireLocation,
|
|
425
|
+
`errors[${number}] should be an object when 'assertionOptions.requireMessage' is 'messageId' or 'assertionOptions.requireLocation' is true.`,
|
|
426
|
+
);
|
|
427
|
+
} else if (typeof error === "object" && error !== null) {
|
|
428
|
+
/*
|
|
429
|
+
* Error object.
|
|
430
|
+
* This may have a message, messageId, data, line, and/or column.
|
|
431
|
+
*/
|
|
432
|
+
|
|
433
|
+
for (const propertyName of Object.keys(error)) {
|
|
434
|
+
assert.ok(
|
|
435
|
+
errorObjectParameters.has(propertyName),
|
|
436
|
+
`Invalid error property name '${propertyName}'. Expected one of ${friendlyErrorObjectParameterList}.`,
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
if (requireMessage === "message") {
|
|
441
|
+
assert.ok(
|
|
442
|
+
!hasOwnProperty(error, "messageId") &&
|
|
443
|
+
hasOwnProperty(error, "message"),
|
|
444
|
+
`errors[${number}] should specify 'message' (and not 'messageId') when 'assertionOptions.requireMessage' is 'message'.`,
|
|
445
|
+
);
|
|
446
|
+
} else if (requireMessage === "messageId") {
|
|
447
|
+
assert.ok(
|
|
448
|
+
!hasOwnProperty(error, "message") &&
|
|
449
|
+
hasOwnProperty(error, "messageId"),
|
|
450
|
+
`errors[${number}] should specify 'messageId' (and not 'message') when 'assertionOptions.requireMessage' is 'messageId'.`,
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (hasOwnProperty(error, "message")) {
|
|
455
|
+
assert.ok(
|
|
456
|
+
!hasOwnProperty(error, "messageId"),
|
|
457
|
+
`errors[${number}] should not specify both 'message' and 'messageId'.`,
|
|
458
|
+
);
|
|
459
|
+
assert.ok(
|
|
460
|
+
!hasOwnProperty(error, "data"),
|
|
461
|
+
`errors[${number}] should not specify both 'data' and 'message'.`,
|
|
462
|
+
);
|
|
463
|
+
} else {
|
|
464
|
+
assert.ok(
|
|
465
|
+
hasOwnProperty(error, "messageId"),
|
|
466
|
+
`errors[${number}] must specify either 'messageId' or 'message'.`,
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
} else {
|
|
470
|
+
assert.fail(
|
|
471
|
+
`errors[${number}] must be a string, RegExp, or an object.`,
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
415
475
|
} else {
|
|
476
|
+
assert.ok(
|
|
477
|
+
!requireMessage && !requireLocation,
|
|
478
|
+
"Invalid cases must have 'errors' value as an array",
|
|
479
|
+
);
|
|
416
480
|
assert.ok(
|
|
417
481
|
errors > 0,
|
|
418
482
|
"Invalid cases must have 'error' value greater than 0",
|
|
@@ -543,6 +607,16 @@ function assertTestCommonProperties(item) {
|
|
|
543
607
|
* @throws {AssertionError} If the test case is not valid.
|
|
544
608
|
*/
|
|
545
609
|
function assertValidTestCase(item, seenTestCases) {
|
|
610
|
+
// must not have properties of invalid test cases
|
|
611
|
+
assert.ok(
|
|
612
|
+
item.errors === void 0,
|
|
613
|
+
"Valid test case must not have 'errors' property",
|
|
614
|
+
);
|
|
615
|
+
assert.ok(
|
|
616
|
+
item.output === void 0,
|
|
617
|
+
"Valid test case must not have 'output' property",
|
|
618
|
+
);
|
|
619
|
+
|
|
546
620
|
assertTestCommonProperties(item);
|
|
547
621
|
checkDuplicateTestCase(item, seenTestCases);
|
|
548
622
|
}
|
|
@@ -554,13 +628,19 @@ function assertValidTestCase(item, seenTestCases) {
|
|
|
554
628
|
* @param {Object} item The invalid test case object to check.
|
|
555
629
|
* @param {Set<string>} seenTestCases Set of serialized test cases to check for duplicates.
|
|
556
630
|
* @param {string} ruleName The name of the rule being tested.
|
|
631
|
+
* @param {Object} [assertionOptions] The assertion options for the test case.
|
|
557
632
|
* @returns {void}
|
|
558
633
|
* @throws {AssertionError} If the test case is not valid.
|
|
559
634
|
*/
|
|
560
|
-
function assertInvalidTestCase(
|
|
635
|
+
function assertInvalidTestCase(
|
|
636
|
+
item,
|
|
637
|
+
seenTestCases,
|
|
638
|
+
ruleName,
|
|
639
|
+
assertionOptions = {},
|
|
640
|
+
) {
|
|
561
641
|
assertTestCommonProperties(item);
|
|
562
642
|
|
|
563
|
-
assertErrorsProperty(item.errors, ruleName);
|
|
643
|
+
assertErrorsProperty(item.errors, ruleName, assertionOptions);
|
|
564
644
|
|
|
565
645
|
// 'output' is optional, but if it exists it must be a string or null
|
|
566
646
|
if (hasOwnProperty(item, "output")) {
|
|
@@ -753,6 +833,10 @@ class RuleTester {
|
|
|
753
833
|
* @param {string} ruleName The name of the rule to run.
|
|
754
834
|
* @param {RuleDefinition} rule The rule to test.
|
|
755
835
|
* @param {{
|
|
836
|
+
* assertionOptions?: {
|
|
837
|
+
* requireMessage?: boolean | "message" | "messageId",
|
|
838
|
+
* requireLocation?: boolean
|
|
839
|
+
* },
|
|
756
840
|
* valid: (ValidTestCase | string)[],
|
|
757
841
|
* invalid: InvalidTestCase[]
|
|
758
842
|
* }} test The collection of tests to run.
|
|
@@ -1133,6 +1217,9 @@ class RuleTester {
|
|
|
1133
1217
|
* @private
|
|
1134
1218
|
*/
|
|
1135
1219
|
function testInvalidTemplate(item) {
|
|
1220
|
+
const { requireMessage = false, requireLocation = false } =
|
|
1221
|
+
test.assertionOptions ?? {};
|
|
1222
|
+
|
|
1136
1223
|
const ruleHasMetaMessages =
|
|
1137
1224
|
hasOwnProperty(rule, "meta") &&
|
|
1138
1225
|
hasOwnProperty(rule.meta, "messages");
|
|
@@ -1142,6 +1229,11 @@ class RuleTester {
|
|
|
1142
1229
|
.join(", ")}]`
|
|
1143
1230
|
: null;
|
|
1144
1231
|
|
|
1232
|
+
assert.ok(
|
|
1233
|
+
ruleHasMetaMessages || requireMessage !== "messageId",
|
|
1234
|
+
`Assertion options can not use 'requireMessage: "messageId"' if rule under test doesn't define 'meta.messages'.`,
|
|
1235
|
+
);
|
|
1236
|
+
|
|
1145
1237
|
const result = runRuleForItem(item);
|
|
1146
1238
|
const messages = result.messages;
|
|
1147
1239
|
|
|
@@ -1215,22 +1307,7 @@ class RuleTester {
|
|
|
1215
1307
|
* This may have a message, messageId, data, line, and/or column.
|
|
1216
1308
|
*/
|
|
1217
1309
|
|
|
1218
|
-
Object.keys(error).forEach(propertyName => {
|
|
1219
|
-
assert.ok(
|
|
1220
|
-
errorObjectParameters.has(propertyName),
|
|
1221
|
-
`Invalid error property name '${propertyName}'. Expected one of ${friendlyErrorObjectParameterList}.`,
|
|
1222
|
-
);
|
|
1223
|
-
});
|
|
1224
|
-
|
|
1225
1310
|
if (hasOwnProperty(error, "message")) {
|
|
1226
|
-
assert.ok(
|
|
1227
|
-
!hasOwnProperty(error, "messageId"),
|
|
1228
|
-
"Error should not specify both 'message' and a 'messageId'.",
|
|
1229
|
-
);
|
|
1230
|
-
assert.ok(
|
|
1231
|
-
!hasOwnProperty(error, "data"),
|
|
1232
|
-
"Error should not specify both 'data' and 'message'.",
|
|
1233
|
-
);
|
|
1234
1311
|
assertMessageMatches(
|
|
1235
1312
|
message.message,
|
|
1236
1313
|
error.message,
|
|
@@ -1288,33 +1365,34 @@ class RuleTester {
|
|
|
1288
1365
|
`Hydrated message "${rehydratedMessage}" does not match "${message.message}"`,
|
|
1289
1366
|
);
|
|
1290
1367
|
}
|
|
1291
|
-
} else {
|
|
1292
|
-
assert.fail(
|
|
1293
|
-
"Test error must specify either a 'messageId' or 'message'.",
|
|
1294
|
-
);
|
|
1295
1368
|
}
|
|
1296
1369
|
|
|
1370
|
+
const locationProperties = [
|
|
1371
|
+
"line",
|
|
1372
|
+
"column",
|
|
1373
|
+
"endLine",
|
|
1374
|
+
"endColumn",
|
|
1375
|
+
];
|
|
1297
1376
|
const actualLocation = {};
|
|
1298
1377
|
const expectedLocation = {};
|
|
1299
1378
|
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
if (hasOwnProperty(error, "column")) {
|
|
1306
|
-
actualLocation.column = message.column;
|
|
1307
|
-
expectedLocation.column = error.column;
|
|
1308
|
-
}
|
|
1309
|
-
|
|
1310
|
-
if (hasOwnProperty(error, "endLine")) {
|
|
1311
|
-
actualLocation.endLine = message.endLine;
|
|
1312
|
-
expectedLocation.endLine = error.endLine;
|
|
1379
|
+
for (const key of locationProperties) {
|
|
1380
|
+
if (hasOwnProperty(error, key)) {
|
|
1381
|
+
actualLocation[key] = message[key];
|
|
1382
|
+
expectedLocation[key] = error[key];
|
|
1383
|
+
}
|
|
1313
1384
|
}
|
|
1314
1385
|
|
|
1315
|
-
if (
|
|
1316
|
-
|
|
1317
|
-
|
|
1386
|
+
if (requireLocation) {
|
|
1387
|
+
const missingKeys = locationProperties.filter(
|
|
1388
|
+
key =>
|
|
1389
|
+
!hasOwnProperty(error, key) &&
|
|
1390
|
+
hasOwnProperty(message, key),
|
|
1391
|
+
);
|
|
1392
|
+
assert.ok(
|
|
1393
|
+
missingKeys.length === 0,
|
|
1394
|
+
`Error is missing expected location properties: ${missingKeys.join(", ")}`,
|
|
1395
|
+
);
|
|
1318
1396
|
}
|
|
1319
1397
|
|
|
1320
1398
|
if (Object.keys(expectedLocation).length > 0) {
|
|
@@ -1540,11 +1618,6 @@ class RuleTester {
|
|
|
1540
1618
|
}
|
|
1541
1619
|
}
|
|
1542
1620
|
}
|
|
1543
|
-
} else {
|
|
1544
|
-
// Message was an unexpected type
|
|
1545
|
-
assert.fail(
|
|
1546
|
-
`Error should be a string, object, or RegExp, but found (${util.inspect(message)})`,
|
|
1547
|
-
);
|
|
1548
1621
|
}
|
|
1549
1622
|
}
|
|
1550
1623
|
}
|
|
@@ -1621,6 +1694,7 @@ class RuleTester {
|
|
|
1621
1694
|
item,
|
|
1622
1695
|
seenTestCases,
|
|
1623
1696
|
ruleName,
|
|
1697
|
+
test.assertionOptions,
|
|
1624
1698
|
);
|
|
1625
1699
|
testInvalidTemplate(item);
|
|
1626
1700
|
} finally {
|
|
@@ -258,13 +258,13 @@ module.exports = {
|
|
|
258
258
|
if (astUtils.isTokenOnSameLine(first, second)) {
|
|
259
259
|
if (
|
|
260
260
|
openingBracketMustBeSpaced &&
|
|
261
|
-
!sourceCode.
|
|
261
|
+
!sourceCode.isSpaceBetween(first, second)
|
|
262
262
|
) {
|
|
263
263
|
reportRequiredBeginningSpace(node, first);
|
|
264
264
|
}
|
|
265
265
|
if (
|
|
266
266
|
!openingBracketMustBeSpaced &&
|
|
267
|
-
sourceCode.
|
|
267
|
+
sourceCode.isSpaceBetween(first, second)
|
|
268
268
|
) {
|
|
269
269
|
reportNoBeginningSpace(node, first);
|
|
270
270
|
}
|
|
@@ -276,13 +276,13 @@ module.exports = {
|
|
|
276
276
|
) {
|
|
277
277
|
if (
|
|
278
278
|
closingBracketMustBeSpaced &&
|
|
279
|
-
!sourceCode.
|
|
279
|
+
!sourceCode.isSpaceBetween(penultimate, last)
|
|
280
280
|
) {
|
|
281
281
|
reportRequiredEndingSpace(node, last);
|
|
282
282
|
}
|
|
283
283
|
if (
|
|
284
284
|
!closingBracketMustBeSpaced &&
|
|
285
|
-
sourceCode.
|
|
285
|
+
sourceCode.isSpaceBetween(penultimate, last)
|
|
286
286
|
) {
|
|
287
287
|
reportNoEndingSpace(node, last);
|
|
288
288
|
}
|
|
@@ -178,10 +178,7 @@ module.exports = {
|
|
|
178
178
|
!commaTokensToIgnore.includes(token) &&
|
|
179
179
|
astUtils.isTokenOnSameLine(previousToken, token) &&
|
|
180
180
|
options.before !==
|
|
181
|
-
sourceCode.
|
|
182
|
-
previousToken,
|
|
183
|
-
token,
|
|
184
|
-
)
|
|
181
|
+
sourceCode.isSpaceBetween(previousToken, token)
|
|
185
182
|
) {
|
|
186
183
|
report(token, "before", previousToken);
|
|
187
184
|
}
|
|
@@ -195,7 +192,7 @@ module.exports = {
|
|
|
195
192
|
!(!options.after && nextToken.type === "Line") && // special case, allow space before line comment
|
|
196
193
|
astUtils.isTokenOnSameLine(token, nextToken) &&
|
|
197
194
|
options.after !==
|
|
198
|
-
sourceCode.
|
|
195
|
+
sourceCode.isSpaceBetween(token, nextToken)
|
|
199
196
|
) {
|
|
200
197
|
report(token, "after", nextToken);
|
|
201
198
|
}
|
|
@@ -203,13 +203,13 @@ module.exports = {
|
|
|
203
203
|
if (astUtils.isTokenOnSameLine(before, first)) {
|
|
204
204
|
if (propertyNameMustBeSpaced) {
|
|
205
205
|
if (
|
|
206
|
-
!sourceCode.
|
|
206
|
+
!sourceCode.isSpaceBetween(before, first) &&
|
|
207
207
|
astUtils.isTokenOnSameLine(before, first)
|
|
208
208
|
) {
|
|
209
209
|
reportRequiredBeginningSpace(node, before);
|
|
210
210
|
}
|
|
211
211
|
} else {
|
|
212
|
-
if (sourceCode.
|
|
212
|
+
if (sourceCode.isSpaceBetween(before, first)) {
|
|
213
213
|
reportNoBeginningSpace(node, before, first);
|
|
214
214
|
}
|
|
215
215
|
}
|
|
@@ -218,13 +218,13 @@ module.exports = {
|
|
|
218
218
|
if (astUtils.isTokenOnSameLine(last, after)) {
|
|
219
219
|
if (propertyNameMustBeSpaced) {
|
|
220
220
|
if (
|
|
221
|
-
!sourceCode.
|
|
221
|
+
!sourceCode.isSpaceBetween(last, after) &&
|
|
222
222
|
astUtils.isTokenOnSameLine(last, after)
|
|
223
223
|
) {
|
|
224
224
|
reportRequiredEndingSpace(node, after);
|
|
225
225
|
}
|
|
226
226
|
} else {
|
|
227
|
-
if (sourceCode.
|
|
227
|
+
if (sourceCode.isSpaceBetween(last, after)) {
|
|
228
228
|
reportNoEndingSpace(node, after, last);
|
|
229
229
|
}
|
|
230
230
|
}
|
|
@@ -163,7 +163,7 @@ module.exports = {
|
|
|
163
163
|
!isOpenParenOfTemplate(prevToken) &&
|
|
164
164
|
!tokensToIgnore.has(prevToken) &&
|
|
165
165
|
astUtils.isTokenOnSameLine(prevToken, token) &&
|
|
166
|
-
!sourceCode.
|
|
166
|
+
!sourceCode.isSpaceBetween(prevToken, token)
|
|
167
167
|
) {
|
|
168
168
|
context.report({
|
|
169
169
|
loc: token.loc,
|
|
@@ -192,7 +192,7 @@ module.exports = {
|
|
|
192
192
|
!isOpenParenOfTemplate(prevToken) &&
|
|
193
193
|
!tokensToIgnore.has(prevToken) &&
|
|
194
194
|
astUtils.isTokenOnSameLine(prevToken, token) &&
|
|
195
|
-
sourceCode.
|
|
195
|
+
sourceCode.isSpaceBetween(prevToken, token)
|
|
196
196
|
) {
|
|
197
197
|
context.report({
|
|
198
198
|
loc: { start: prevToken.loc.end, end: token.loc.start },
|
|
@@ -224,7 +224,7 @@ module.exports = {
|
|
|
224
224
|
!isCloseParenOfTemplate(nextToken) &&
|
|
225
225
|
!tokensToIgnore.has(nextToken) &&
|
|
226
226
|
astUtils.isTokenOnSameLine(token, nextToken) &&
|
|
227
|
-
!sourceCode.
|
|
227
|
+
!sourceCode.isSpaceBetween(token, nextToken)
|
|
228
228
|
) {
|
|
229
229
|
context.report({
|
|
230
230
|
loc: token.loc,
|
|
@@ -253,7 +253,7 @@ module.exports = {
|
|
|
253
253
|
!isCloseParenOfTemplate(nextToken) &&
|
|
254
254
|
!tokensToIgnore.has(nextToken) &&
|
|
255
255
|
astUtils.isTokenOnSameLine(token, nextToken) &&
|
|
256
|
-
sourceCode.
|
|
256
|
+
sourceCode.isSpaceBetween(token, nextToken)
|
|
257
257
|
) {
|
|
258
258
|
context.report({
|
|
259
259
|
loc: { start: token.loc.end, end: nextToken.loc.start },
|
|
@@ -10,6 +10,30 @@
|
|
|
10
10
|
|
|
11
11
|
const astUtils = require("./utils/ast-utils");
|
|
12
12
|
|
|
13
|
+
//------------------------------------------------------------------------------
|
|
14
|
+
// Helpers
|
|
15
|
+
//------------------------------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Format import names for error messages.
|
|
19
|
+
* @param {string[]} importNames The import names to format.
|
|
20
|
+
* @returns {string} The formatted import names.
|
|
21
|
+
*/
|
|
22
|
+
function formatImportNames(importNames) {
|
|
23
|
+
return new Intl.ListFormat("en-US").format(
|
|
24
|
+
importNames.map(name => `'${name}'`),
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Returns "is" or "are" based on the number of import names.
|
|
30
|
+
* @param {string[]} importNames The import names to check.
|
|
31
|
+
* @returns {string} "is" if one import name, otherwise "are".
|
|
32
|
+
*/
|
|
33
|
+
function isOrAre(importNames) {
|
|
34
|
+
return importNames.length === 1 ? "is" : "are";
|
|
35
|
+
}
|
|
36
|
+
|
|
13
37
|
//------------------------------------------------------------------------------
|
|
14
38
|
// Rule Definition
|
|
15
39
|
//------------------------------------------------------------------------------
|
|
@@ -175,22 +199,22 @@ module.exports = {
|
|
|
175
199
|
"'{{importName}}' import from '{{importSource}}' is restricted from being used by a pattern. {{customMessage}}",
|
|
176
200
|
|
|
177
201
|
patternAndEverything:
|
|
178
|
-
"* import is invalid because
|
|
202
|
+
"* import is invalid because {{importNames}} from '{{importSource}}' {{isOrAre}} restricted from being used by a pattern.",
|
|
179
203
|
|
|
180
204
|
patternAndEverythingWithRegexImportName:
|
|
181
205
|
"* import is invalid because import name matching '{{importNames}}' pattern from '{{importSource}}' is restricted from being used.",
|
|
182
206
|
patternAndEverythingWithCustomMessage:
|
|
183
207
|
// eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
|
|
184
|
-
"* import is invalid because
|
|
208
|
+
"* import is invalid because {{importNames}} from '{{importSource}}' {{isOrAre}} restricted from being used by a pattern. {{customMessage}}",
|
|
185
209
|
patternAndEverythingWithRegexImportNameAndCustomMessage:
|
|
186
210
|
// eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
|
|
187
211
|
"* import is invalid because import name matching '{{importNames}}' pattern from '{{importSource}}' is restricted from being used. {{customMessage}}",
|
|
188
212
|
|
|
189
213
|
everything:
|
|
190
|
-
"* import is invalid because
|
|
214
|
+
"* import is invalid because {{importNames}} from '{{importSource}}' {{isOrAre}} restricted.",
|
|
191
215
|
everythingWithCustomMessage:
|
|
192
216
|
// eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
|
|
193
|
-
"* import is invalid because
|
|
217
|
+
"* import is invalid because {{importNames}} from '{{importSource}}' {{isOrAre}} restricted. {{customMessage}}",
|
|
194
218
|
|
|
195
219
|
importName:
|
|
196
220
|
"'{{importName}}' import from '{{importSource}}' is restricted.",
|
|
@@ -199,16 +223,16 @@ module.exports = {
|
|
|
199
223
|
"'{{importName}}' import from '{{importSource}}' is restricted. {{customMessage}}",
|
|
200
224
|
|
|
201
225
|
allowedImportName:
|
|
202
|
-
"'{{importName}}' import from '{{importSource}}' is restricted because only
|
|
226
|
+
"'{{importName}}' import from '{{importSource}}' is restricted because only {{allowedImportNames}} {{isOrAre}} allowed.",
|
|
203
227
|
allowedImportNameWithCustomMessage:
|
|
204
228
|
// eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
|
|
205
|
-
"'{{importName}}' import from '{{importSource}}' is restricted because only
|
|
229
|
+
"'{{importName}}' import from '{{importSource}}' is restricted because only {{allowedImportNames}} {{isOrAre}} allowed. {{customMessage}}",
|
|
206
230
|
|
|
207
231
|
everythingWithAllowImportNames:
|
|
208
|
-
"* import is invalid because only
|
|
232
|
+
"* import is invalid because only {{allowedImportNames}} from '{{importSource}}' {{isOrAre}} allowed.",
|
|
209
233
|
everythingWithAllowImportNamesAndCustomMessage:
|
|
210
234
|
// eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
|
|
211
|
-
"* import is invalid because only
|
|
235
|
+
"* import is invalid because only {{allowedImportNames}} from '{{importSource}}' {{isOrAre}} allowed. {{customMessage}}",
|
|
212
236
|
|
|
213
237
|
allowedImportNamePattern:
|
|
214
238
|
"'{{importName}}' import from '{{importSource}}' is restricted because only imports that match the pattern '{{allowedImportNamePattern}}' are allowed from '{{importSource}}'.",
|
|
@@ -452,7 +476,10 @@ module.exports = {
|
|
|
452
476
|
loc: specifier.loc,
|
|
453
477
|
data: {
|
|
454
478
|
importSource,
|
|
455
|
-
importNames:
|
|
479
|
+
importNames: formatImportNames(
|
|
480
|
+
restrictedImportNames,
|
|
481
|
+
),
|
|
482
|
+
isOrAre: isOrAre(restrictedImportNames),
|
|
456
483
|
customMessage,
|
|
457
484
|
},
|
|
458
485
|
});
|
|
@@ -465,7 +492,11 @@ module.exports = {
|
|
|
465
492
|
loc: specifier.loc,
|
|
466
493
|
data: {
|
|
467
494
|
importSource,
|
|
468
|
-
allowedImportNames
|
|
495
|
+
allowedImportNames:
|
|
496
|
+
formatImportNames(
|
|
497
|
+
allowedImportNames,
|
|
498
|
+
),
|
|
499
|
+
isOrAre: isOrAre(allowedImportNames),
|
|
469
500
|
customMessage,
|
|
470
501
|
},
|
|
471
502
|
});
|
|
@@ -525,7 +556,11 @@ module.exports = {
|
|
|
525
556
|
importSource,
|
|
526
557
|
customMessage,
|
|
527
558
|
importName,
|
|
528
|
-
allowedImportNames
|
|
559
|
+
allowedImportNames:
|
|
560
|
+
formatImportNames(
|
|
561
|
+
allowedImportNames,
|
|
562
|
+
),
|
|
563
|
+
isOrAre: isOrAre(allowedImportNames),
|
|
529
564
|
},
|
|
530
565
|
});
|
|
531
566
|
});
|
|
@@ -612,7 +647,10 @@ module.exports = {
|
|
|
612
647
|
loc: specifier.loc,
|
|
613
648
|
data: {
|
|
614
649
|
importSource,
|
|
615
|
-
importNames:
|
|
650
|
+
importNames: formatImportNames(
|
|
651
|
+
restrictedImportNames,
|
|
652
|
+
),
|
|
653
|
+
isOrAre: isOrAre(restrictedImportNames),
|
|
616
654
|
customMessage,
|
|
617
655
|
},
|
|
618
656
|
});
|
|
@@ -625,7 +663,9 @@ module.exports = {
|
|
|
625
663
|
loc: specifier.loc,
|
|
626
664
|
data: {
|
|
627
665
|
importSource,
|
|
628
|
-
allowedImportNames
|
|
666
|
+
allowedImportNames:
|
|
667
|
+
formatImportNames(allowedImportNames),
|
|
668
|
+
isOrAre: isOrAre(allowedImportNames),
|
|
629
669
|
customMessage,
|
|
630
670
|
},
|
|
631
671
|
});
|
|
@@ -713,7 +753,9 @@ module.exports = {
|
|
|
713
753
|
importSource,
|
|
714
754
|
customMessage,
|
|
715
755
|
importName,
|
|
716
|
-
allowedImportNames
|
|
756
|
+
allowedImportNames:
|
|
757
|
+
formatImportNames(allowedImportNames),
|
|
758
|
+
isOrAre: isOrAre(allowedImportNames),
|
|
717
759
|
},
|
|
718
760
|
});
|
|
719
761
|
});
|
|
@@ -336,9 +336,12 @@ module.exports = {
|
|
|
336
336
|
}
|
|
337
337
|
|
|
338
338
|
if (
|
|
339
|
-
targetAssignment.variable.references.some(
|
|
340
|
-
|
|
341
|
-
|
|
339
|
+
targetAssignment.variable.references.some(ref => {
|
|
340
|
+
const type = ref.identifier.type;
|
|
341
|
+
return (
|
|
342
|
+
type !== "Identifier" && type !== "JSXIdentifier"
|
|
343
|
+
);
|
|
344
|
+
})
|
|
342
345
|
) {
|
|
343
346
|
/**
|
|
344
347
|
* Skip checking for a variable that has at least one non-identifier reference.
|
|
@@ -529,7 +532,7 @@ module.exports = {
|
|
|
529
532
|
TryStatement(node) {
|
|
530
533
|
scopeStack.tryStatementBlocks.push(node.block);
|
|
531
534
|
},
|
|
532
|
-
Identifier(node) {
|
|
535
|
+
"Identifier, JSXIdentifier"(node) {
|
|
533
536
|
for (const segment of scopeStack.currentSegments) {
|
|
534
537
|
const segmentInfo = scopeStack.segments[segment.id];
|
|
535
538
|
|
|
@@ -539,7 +542,7 @@ module.exports = {
|
|
|
539
542
|
segmentInfo.last = node;
|
|
540
543
|
}
|
|
541
544
|
},
|
|
542
|
-
"
|
|
545
|
+
"VariableDeclarator[init!=null], AssignmentExpression, UpdateExpression:exit"(
|
|
543
546
|
node,
|
|
544
547
|
) {
|
|
545
548
|
if (scopeStack.currentSegments.size === 0) {
|
|
@@ -185,6 +185,8 @@ module.exports = {
|
|
|
185
185
|
},
|
|
186
186
|
|
|
187
187
|
create(context) {
|
|
188
|
+
const { sourceCode } = context;
|
|
189
|
+
|
|
188
190
|
/**
|
|
189
191
|
* Checks whether a node is a redundant constructor
|
|
190
192
|
* @param {ASTNode} node node to check
|
|
@@ -211,6 +213,14 @@ module.exports = {
|
|
|
211
213
|
const body = node.value.body.body;
|
|
212
214
|
const ctorParams = node.value.params;
|
|
213
215
|
const superClass = node.parent.parent.superClass;
|
|
216
|
+
const parenToken = sourceCode.getFirstToken(
|
|
217
|
+
node,
|
|
218
|
+
astUtils.isOpeningParenToken,
|
|
219
|
+
);
|
|
220
|
+
const loc = {
|
|
221
|
+
start: node.loc.start,
|
|
222
|
+
end: sourceCode.getTokenBefore(parenToken).loc.end,
|
|
223
|
+
};
|
|
214
224
|
|
|
215
225
|
if (
|
|
216
226
|
superClass
|
|
@@ -218,19 +228,19 @@ module.exports = {
|
|
|
218
228
|
: body.length === 0
|
|
219
229
|
) {
|
|
220
230
|
context.report({
|
|
221
|
-
|
|
231
|
+
loc,
|
|
222
232
|
messageId: "noUselessConstructor",
|
|
223
233
|
suggest: [
|
|
224
234
|
{
|
|
225
235
|
messageId: "removeConstructor",
|
|
226
236
|
*fix(fixer) {
|
|
227
237
|
const nextToken =
|
|
228
|
-
|
|
238
|
+
sourceCode.getTokenAfter(node);
|
|
229
239
|
const addSemiColon =
|
|
230
240
|
nextToken.type === "Punctuator" &&
|
|
231
241
|
nextToken.value === "[" &&
|
|
232
242
|
astUtils.needsPrecedingSemicolon(
|
|
233
|
-
|
|
243
|
+
sourceCode,
|
|
234
244
|
node,
|
|
235
245
|
);
|
|
236
246
|
|
|
@@ -141,7 +141,7 @@ module.exports = {
|
|
|
141
141
|
leftToken = sourceCode.getTokenBefore(rightToken, 1);
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
if (sourceCode.
|
|
144
|
+
if (sourceCode.isSpaceBetween(leftToken, rightToken)) {
|
|
145
145
|
reportError(node, leftToken, rightToken);
|
|
146
146
|
}
|
|
147
147
|
},
|
|
@@ -204,10 +204,7 @@ module.exports = {
|
|
|
204
204
|
*/
|
|
205
205
|
function validateBraceSpacing(node, first, second, penultimate, last) {
|
|
206
206
|
if (astUtils.isTokenOnSameLine(first, second)) {
|
|
207
|
-
const firstSpaced = sourceCode.
|
|
208
|
-
first,
|
|
209
|
-
second,
|
|
210
|
-
);
|
|
207
|
+
const firstSpaced = sourceCode.isSpaceBetween(first, second);
|
|
211
208
|
|
|
212
209
|
if (options.spaced && !firstSpaced) {
|
|
213
210
|
reportRequiredBeginningSpace(node, first);
|
|
@@ -236,10 +233,7 @@ module.exports = {
|
|
|
236
233
|
? !options.spaced
|
|
237
234
|
: options.spaced;
|
|
238
235
|
|
|
239
|
-
const lastSpaced = sourceCode.
|
|
240
|
-
penultimate,
|
|
241
|
-
last,
|
|
242
|
-
);
|
|
236
|
+
const lastSpaced = sourceCode.isSpaceBetween(penultimate, last);
|
|
243
237
|
|
|
244
238
|
if (closingCurlyBraceMustBeSpaced && !lastSpaced) {
|
|
245
239
|
reportRequiredEndingSpace(node, last);
|