eslint 9.0.0-alpha.0 → 9.0.0-alpha.2

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.
Files changed (89) hide show
  1. package/README.md +6 -1
  2. package/conf/ecma-version.js +16 -0
  3. package/lib/cli-engine/cli-engine.js +1 -1
  4. package/lib/cli-engine/lint-result-cache.js +2 -2
  5. package/lib/cli.js +14 -16
  6. package/lib/eslint/eslint.js +7 -0
  7. package/lib/linter/apply-disable-directives.js +2 -2
  8. package/lib/linter/code-path-analysis/code-path.js +32 -30
  9. package/lib/linter/code-path-analysis/fork-context.js +1 -1
  10. package/lib/linter/config-comment-parser.js +7 -10
  11. package/lib/linter/linter.js +105 -4
  12. package/lib/linter/report-translator.js +2 -2
  13. package/lib/linter/source-code-fixer.js +1 -1
  14. package/lib/rule-tester/rule-tester.js +45 -26
  15. package/lib/rules/array-bracket-newline.js +1 -1
  16. package/lib/rules/array-bracket-spacing.js +1 -1
  17. package/lib/rules/block-scoped-var.js +1 -1
  18. package/lib/rules/callback-return.js +2 -2
  19. package/lib/rules/comma-dangle.js +1 -1
  20. package/lib/rules/comma-style.js +2 -2
  21. package/lib/rules/complexity.js +1 -1
  22. package/lib/rules/constructor-super.js +1 -1
  23. package/lib/rules/default-case.js +1 -1
  24. package/lib/rules/eol-last.js +2 -2
  25. package/lib/rules/function-paren-newline.js +2 -2
  26. package/lib/rules/indent-legacy.js +5 -5
  27. package/lib/rules/indent.js +5 -5
  28. package/lib/rules/index.js +1 -0
  29. package/lib/rules/key-spacing.js +2 -2
  30. package/lib/rules/line-comment-position.js +1 -1
  31. package/lib/rules/lines-around-directive.js +2 -2
  32. package/lib/rules/max-depth.js +1 -1
  33. package/lib/rules/max-len.js +3 -3
  34. package/lib/rules/max-lines.js +3 -3
  35. package/lib/rules/max-nested-callbacks.js +1 -1
  36. package/lib/rules/max-params.js +1 -1
  37. package/lib/rules/max-statements.js +1 -1
  38. package/lib/rules/multiline-comment-style.js +7 -7
  39. package/lib/rules/new-cap.js +1 -1
  40. package/lib/rules/newline-after-var.js +1 -1
  41. package/lib/rules/newline-before-return.js +1 -1
  42. package/lib/rules/no-constant-binary-expression.js +5 -5
  43. package/lib/rules/no-constructor-return.js +1 -1
  44. package/lib/rules/no-dupe-class-members.js +2 -2
  45. package/lib/rules/no-else-return.js +1 -1
  46. package/lib/rules/no-empty-function.js +2 -2
  47. package/lib/rules/no-fallthrough.js +1 -1
  48. package/lib/rules/no-implicit-coercion.js +51 -25
  49. package/lib/rules/no-inner-declarations.js +22 -1
  50. package/lib/rules/no-invalid-this.js +1 -1
  51. package/lib/rules/no-lone-blocks.js +2 -2
  52. package/lib/rules/no-loss-of-precision.js +1 -1
  53. package/lib/rules/no-misleading-character-class.js +174 -65
  54. package/lib/rules/no-multiple-empty-lines.js +1 -1
  55. package/lib/rules/no-restricted-globals.js +1 -1
  56. package/lib/rules/no-restricted-imports.js +54 -44
  57. package/lib/rules/no-restricted-modules.js +2 -2
  58. package/lib/rules/no-return-await.js +1 -1
  59. package/lib/rules/no-this-before-super.js +17 -4
  60. package/lib/rules/no-trailing-spaces.js +2 -3
  61. package/lib/rules/no-unneeded-ternary.js +1 -1
  62. package/lib/rules/no-unsafe-optional-chaining.js +1 -1
  63. package/lib/rules/no-unused-vars.js +6 -8
  64. package/lib/rules/no-useless-assignment.js +566 -0
  65. package/lib/rules/no-useless-backreference.js +1 -1
  66. package/lib/rules/object-curly-spacing.js +3 -3
  67. package/lib/rules/object-property-newline.js +1 -1
  68. package/lib/rules/one-var.js +5 -5
  69. package/lib/rules/padded-blocks.js +7 -7
  70. package/lib/rules/prefer-arrow-callback.js +3 -3
  71. package/lib/rules/prefer-reflect.js +1 -1
  72. package/lib/rules/prefer-regex-literals.js +1 -1
  73. package/lib/rules/prefer-template.js +1 -1
  74. package/lib/rules/radix.js +2 -2
  75. package/lib/rules/semi-style.js +1 -1
  76. package/lib/rules/sort-imports.js +1 -1
  77. package/lib/rules/sort-keys.js +1 -1
  78. package/lib/rules/sort-vars.js +1 -1
  79. package/lib/rules/space-unary-ops.js +1 -1
  80. package/lib/rules/strict.js +1 -1
  81. package/lib/rules/utils/ast-utils.js +7 -7
  82. package/lib/rules/yield-star-spacing.js +1 -1
  83. package/lib/shared/serialization.js +55 -0
  84. package/lib/source-code/source-code.js +4 -4
  85. package/lib/source-code/token-store/index.js +2 -2
  86. package/package.json +7 -7
  87. package/conf/config-schema.js +0 -93
  88. package/lib/shared/config-validator.js +0 -380
  89. package/lib/shared/relative-module-resolver.js +0 -50
@@ -158,20 +158,28 @@ module.exports = {
158
158
  const options = Array.isArray(context.options) ? context.options : [];
159
159
  const isPathAndPatternsObject =
160
160
  typeof options[0] === "object" &&
161
- (Object.prototype.hasOwnProperty.call(options[0], "paths") || Object.prototype.hasOwnProperty.call(options[0], "patterns"));
161
+ (Object.hasOwn(options[0], "paths") || Object.hasOwn(options[0], "patterns"));
162
162
 
163
163
  const restrictedPaths = (isPathAndPatternsObject ? options[0].paths : context.options) || [];
164
- const restrictedPathMessages = restrictedPaths.reduce((memo, importSource) => {
164
+ const groupedRestrictedPaths = restrictedPaths.reduce((memo, importSource) => {
165
+ const path = typeof importSource === "string"
166
+ ? importSource
167
+ : importSource.name;
168
+
169
+ if (!memo[path]) {
170
+ memo[path] = [];
171
+ }
172
+
165
173
  if (typeof importSource === "string") {
166
- memo[importSource] = { message: null };
174
+ memo[path].push({});
167
175
  } else {
168
- memo[importSource.name] = {
176
+ memo[path].push({
169
177
  message: importSource.message,
170
178
  importNames: importSource.importNames
171
- };
179
+ });
172
180
  }
173
181
  return memo;
174
- }, {});
182
+ }, Object.create(null));
175
183
 
176
184
  // Handle patterns too, either as strings or groups
177
185
  let restrictedPatterns = (isPathAndPatternsObject ? options[0].patterns : []) || [];
@@ -203,57 +211,59 @@ module.exports = {
203
211
  * @private
204
212
  */
205
213
  function checkRestrictedPathAndReport(importSource, importNames, node) {
206
- if (!Object.prototype.hasOwnProperty.call(restrictedPathMessages, importSource)) {
214
+ if (!Object.hasOwn(groupedRestrictedPaths, importSource)) {
207
215
  return;
208
216
  }
209
217
 
210
- const customMessage = restrictedPathMessages[importSource].message;
211
- const restrictedImportNames = restrictedPathMessages[importSource].importNames;
218
+ groupedRestrictedPaths[importSource].forEach(restrictedPathEntry => {
219
+ const customMessage = restrictedPathEntry.message;
220
+ const restrictedImportNames = restrictedPathEntry.importNames;
212
221
 
213
- if (restrictedImportNames) {
214
- if (importNames.has("*")) {
215
- const specifierData = importNames.get("*")[0];
222
+ if (restrictedImportNames) {
223
+ if (importNames.has("*")) {
224
+ const specifierData = importNames.get("*")[0];
225
+
226
+ context.report({
227
+ node,
228
+ messageId: customMessage ? "everythingWithCustomMessage" : "everything",
229
+ loc: specifierData.loc,
230
+ data: {
231
+ importSource,
232
+ importNames: restrictedImportNames,
233
+ customMessage
234
+ }
235
+ });
236
+ }
216
237
 
238
+ restrictedImportNames.forEach(importName => {
239
+ if (importNames.has(importName)) {
240
+ const specifiers = importNames.get(importName);
241
+
242
+ specifiers.forEach(specifier => {
243
+ context.report({
244
+ node,
245
+ messageId: customMessage ? "importNameWithCustomMessage" : "importName",
246
+ loc: specifier.loc,
247
+ data: {
248
+ importSource,
249
+ customMessage,
250
+ importName
251
+ }
252
+ });
253
+ });
254
+ }
255
+ });
256
+ } else {
217
257
  context.report({
218
258
  node,
219
- messageId: customMessage ? "everythingWithCustomMessage" : "everything",
220
- loc: specifierData.loc,
259
+ messageId: customMessage ? "pathWithCustomMessage" : "path",
221
260
  data: {
222
261
  importSource,
223
- importNames: restrictedImportNames,
224
262
  customMessage
225
263
  }
226
264
  });
227
265
  }
228
-
229
- restrictedImportNames.forEach(importName => {
230
- if (importNames.has(importName)) {
231
- const specifiers = importNames.get(importName);
232
-
233
- specifiers.forEach(specifier => {
234
- context.report({
235
- node,
236
- messageId: customMessage ? "importNameWithCustomMessage" : "importName",
237
- loc: specifier.loc,
238
- data: {
239
- importSource,
240
- customMessage,
241
- importName
242
- }
243
- });
244
- });
245
- }
246
- });
247
- } else {
248
- context.report({
249
- node,
250
- messageId: customMessage ? "pathWithCustomMessage" : "path",
251
- data: {
252
- importSource,
253
- customMessage
254
- }
255
- });
256
- }
266
+ });
257
267
  }
258
268
 
259
269
  /**
@@ -90,7 +90,7 @@ module.exports = {
90
90
  const options = Array.isArray(context.options) ? context.options : [];
91
91
  const isPathAndPatternsObject =
92
92
  typeof options[0] === "object" &&
93
- (Object.prototype.hasOwnProperty.call(options[0], "paths") || Object.prototype.hasOwnProperty.call(options[0], "patterns"));
93
+ (Object.hasOwn(options[0], "paths") || Object.hasOwn(options[0], "patterns"));
94
94
 
95
95
  const restrictedPaths = (isPathAndPatternsObject ? options[0].paths : context.options) || [];
96
96
  const restrictedPatterns = (isPathAndPatternsObject ? options[0].patterns : []) || [];
@@ -178,7 +178,7 @@ module.exports = {
178
178
  * @private
179
179
  */
180
180
  function isRestrictedPath(name) {
181
- return Object.prototype.hasOwnProperty.call(restrictedPathMessages, name);
181
+ return Object.hasOwn(restrictedPathMessages, name);
182
182
  }
183
183
 
184
184
  return {
@@ -118,7 +118,7 @@ module.exports = {
118
118
  if (node.parent.type === "LogicalExpression" && node === node.parent.right) {
119
119
  return isInTailCallPosition(node.parent);
120
120
  }
121
- if (node.parent.type === "SequenceExpression" && node === node.parent.expressions[node.parent.expressions.length - 1]) {
121
+ if (node.parent.type === "SequenceExpression" && node === node.parent.expressions.at(-1)) {
122
122
  return isInTailCallPosition(node.parent);
123
123
  }
124
124
  return false;
@@ -197,11 +197,26 @@ module.exports = {
197
197
  return;
198
198
  }
199
199
 
200
+ /**
201
+ * A collection of nodes to avoid duplicate reports.
202
+ * @type {Set<ASTNode>}
203
+ */
204
+ const reported = new Set();
205
+
200
206
  codePath.traverseSegments((segment, controller) => {
201
207
  const info = segInfoMap[segment.id];
208
+ const invalidNodes = info.invalidNodes
209
+ .filter(
210
+
211
+ /*
212
+ * Avoid duplicate reports.
213
+ * When there is a `finally`, invalidNodes may contain already reported node.
214
+ */
215
+ node => !reported.has(node)
216
+ );
202
217
 
203
- for (let i = 0; i < info.invalidNodes.length; ++i) {
204
- const invalidNode = info.invalidNodes[i];
218
+ for (const invalidNode of invalidNodes) {
219
+ reported.add(invalidNode);
205
220
 
206
221
  context.report({
207
222
  messageId: "noBeforeSuper",
@@ -273,14 +288,12 @@ module.exports = {
273
288
  const info = segInfoMap[segment.id];
274
289
 
275
290
  if (info.superCalled) {
276
- info.invalidNodes = [];
277
291
  controller.skip();
278
292
  } else if (
279
293
  segment.prevSegments.length > 0 &&
280
294
  segment.prevSegments.every(isCalled)
281
295
  ) {
282
296
  info.superCalled = true;
283
- info.invalidNodes = [];
284
297
  }
285
298
  }
286
299
  );
@@ -129,8 +129,7 @@ module.exports = {
129
129
  comments = sourceCode.getAllComments(),
130
130
  commentLineNumbers = getCommentLineNumbers(comments);
131
131
 
132
- let totalLength = 0,
133
- fixRange = [];
132
+ let totalLength = 0;
134
133
 
135
134
  for (let i = 0, ii = lines.length; i < ii; i++) {
136
135
  const lineNumber = i + 1;
@@ -177,7 +176,7 @@ module.exports = {
177
176
  continue;
178
177
  }
179
178
 
180
- fixRange = [rangeStart, rangeEnd];
179
+ const fixRange = [rangeStart, rangeEnd];
181
180
 
182
181
  if (!ignoreComments || !commentLineNumbers.has(lineNumber)) {
183
182
  report(node, location, fixRange);
@@ -76,7 +76,7 @@ module.exports = {
76
76
  * @returns {string} A string representing an inverted expression
77
77
  */
78
78
  function invertExpression(node) {
79
- if (node.type === "BinaryExpression" && Object.prototype.hasOwnProperty.call(OPERATOR_INVERSES, node.operator)) {
79
+ if (node.type === "BinaryExpression" && Object.hasOwn(OPERATOR_INVERSES, node.operator)) {
80
80
  const operatorToken = sourceCode.getFirstTokenBetween(
81
81
  node.left,
82
82
  node.right,
@@ -94,7 +94,7 @@ module.exports = {
94
94
  break;
95
95
  case "SequenceExpression":
96
96
  checkUndefinedShortCircuit(
97
- node.expressions[node.expressions.length - 1],
97
+ node.expressions.at(-1),
98
98
  reportFunc
99
99
  );
100
100
  break;
@@ -141,7 +141,7 @@ module.exports = {
141
141
  } else if (defType === "Parameter" && config.argsIgnorePattern) {
142
142
  type = "args";
143
143
  pattern = config.argsIgnorePattern.toString();
144
- } else if (defType !== "Parameter" && config.varsIgnorePattern) {
144
+ } else if (defType !== "Parameter" && defType !== "CatchClause" && config.varsIgnorePattern) {
145
145
  type = "vars";
146
146
  pattern = config.varsIgnorePattern.toString();
147
147
  }
@@ -218,7 +218,7 @@ module.exports = {
218
218
  function hasRestSibling(node) {
219
219
  return node.type === "Property" &&
220
220
  node.parent.type === "ObjectPattern" &&
221
- REST_PROPERTY_TYPE.test(node.parent.properties[node.parent.properties.length - 1].type);
221
+ REST_PROPERTY_TYPE.test(node.parent.properties.at(-1).type);
222
222
  }
223
223
 
224
224
  /**
@@ -323,7 +323,7 @@ module.exports = {
323
323
  }
324
324
 
325
325
  if (parent.type === "SequenceExpression") {
326
- const isLastExpression = parent.expressions[parent.expressions.length - 1] === node;
326
+ const isLastExpression = parent.expressions.at(-1) === node;
327
327
 
328
328
  if (!isLastExpression) {
329
329
  return true;
@@ -392,7 +392,7 @@ module.exports = {
392
392
  while (parent && isInside(parent, rhsNode)) {
393
393
  switch (parent.type) {
394
394
  case "SequenceExpression":
395
- if (parent.expressions[parent.expressions.length - 1] !== node) {
395
+ if (parent.expressions.at(-1) !== node) {
396
396
  return false;
397
397
  }
398
398
  break;
@@ -623,9 +623,7 @@ module.exports = {
623
623
  if (config.caughtErrorsIgnorePattern && config.caughtErrorsIgnorePattern.test(def.name.name)) {
624
624
  continue;
625
625
  }
626
- }
627
-
628
- if (type === "Parameter") {
626
+ } else if (type === "Parameter") {
629
627
 
630
628
  // skip any setter argument
631
629
  if ((def.node.parent.type === "Property" || def.node.parent.type === "MethodDefinition") && def.node.parent.kind === "set") {
@@ -688,7 +686,7 @@ module.exports = {
688
686
  let referenceToReport;
689
687
 
690
688
  if (writeReferences.length > 0) {
691
- referenceToReport = writeReferences[writeReferences.length - 1];
689
+ referenceToReport = writeReferences.at(-1);
692
690
  }
693
691
 
694
692
  context.report({