eslint 10.2.1 → 10.4.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.
Files changed (52) hide show
  1. package/README.md +3 -3
  2. package/lib/config/config-loader.js +1 -1
  3. package/lib/config-api.js +7 -1
  4. package/lib/eslint/eslint.js +29 -6
  5. package/lib/linter/code-path-analysis/code-path-analyzer.js +7 -7
  6. package/lib/linter/code-path-analysis/debug-helpers.js +12 -1
  7. package/lib/linter/code-path-analysis/id-generator.js +1 -2
  8. package/lib/rules/capitalized-comments.js +3 -1
  9. package/lib/rules/class-methods-use-this.js +1 -2
  10. package/lib/rules/default-param-last.js +1 -2
  11. package/lib/rules/eqeqeq.js +3 -1
  12. package/lib/rules/for-direction.js +55 -11
  13. package/lib/rules/func-name-matching.js +2 -0
  14. package/lib/rules/func-style.js +1 -2
  15. package/lib/rules/init-declarations.js +7 -8
  16. package/lib/rules/logical-assignment-operators.js +4 -1
  17. package/lib/rules/max-classes-per-file.js +4 -2
  18. package/lib/rules/max-depth.js +3 -0
  19. package/lib/rules/max-lines-per-function.js +3 -0
  20. package/lib/rules/max-lines.js +3 -0
  21. package/lib/rules/max-nested-callbacks.js +3 -0
  22. package/lib/rules/max-params.js +4 -2
  23. package/lib/rules/max-statements.js +3 -0
  24. package/lib/rules/no-array-constructor.js +1 -2
  25. package/lib/rules/no-dupe-class-members.js +1 -2
  26. package/lib/rules/no-duplicate-imports.js +1 -2
  27. package/lib/rules/no-empty-function.js +1 -2
  28. package/lib/rules/no-invalid-this.js +1 -2
  29. package/lib/rules/no-loop-func.js +1 -2
  30. package/lib/rules/no-loss-of-precision.js +1 -2
  31. package/lib/rules/no-magic-numbers.js +29 -24
  32. package/lib/rules/no-restricted-exports.js +8 -8
  33. package/lib/rules/no-restricted-globals.js +1 -2
  34. package/lib/rules/no-restricted-imports.js +1 -2
  35. package/lib/rules/no-restricted-properties.js +2 -0
  36. package/lib/rules/no-restricted-syntax.js +2 -0
  37. package/lib/rules/no-shadow.js +1 -2
  38. package/lib/rules/no-unassigned-vars.js +1 -2
  39. package/lib/rules/no-unused-expressions.js +1 -2
  40. package/lib/rules/no-unused-private-class-members.js +201 -1
  41. package/lib/rules/no-unused-vars.js +50 -53
  42. package/lib/rules/no-use-before-define.js +1 -2
  43. package/lib/rules/no-useless-concat.js +2 -2
  44. package/lib/rules/no-useless-constructor.js +4 -4
  45. package/lib/rules/no-var.js +1 -2
  46. package/lib/rules/object-shorthand.js +3 -1
  47. package/lib/rules/one-var.js +3 -1
  48. package/lib/rules/prefer-arrow-callback.js +1 -2
  49. package/lib/rules/require-await.js +6 -4
  50. package/lib/rules/utils/ast-utils.js +36 -4
  51. package/lib/types/config-api.d.ts +2 -1
  52. package/package.json +8 -7
@@ -91,11 +91,10 @@ function isAncestorTSIndexedAccessType(node) {
91
91
  module.exports = {
92
92
  meta: {
93
93
  type: "suggestion",
94
- dialects: ["typescript", "javascript"],
95
- language: "javascript",
96
94
 
97
95
  docs: {
98
96
  description: "Disallow magic numbers",
97
+ dialects: ["JavaScript", "TypeScript"],
99
98
  recommended: false,
100
99
  frozen: true,
101
100
  url: "https://eslint.org/docs/latest/rules/no-magic-numbers",
@@ -107,11 +106,9 @@ module.exports = {
107
106
  properties: {
108
107
  detectObjects: {
109
108
  type: "boolean",
110
- default: false,
111
109
  },
112
110
  enforceConst: {
113
111
  type: "boolean",
114
- default: false,
115
112
  },
116
113
  ignore: {
117
114
  type: "array",
@@ -128,37 +125,45 @@ module.exports = {
128
125
  },
129
126
  ignoreArrayIndexes: {
130
127
  type: "boolean",
131
- default: false,
132
128
  },
133
129
  ignoreDefaultValues: {
134
130
  type: "boolean",
135
- default: false,
136
131
  },
137
132
  ignoreClassFieldInitialValues: {
138
133
  type: "boolean",
139
- default: false,
140
134
  },
141
135
  ignoreEnums: {
142
136
  type: "boolean",
143
- default: false,
144
137
  },
145
138
  ignoreNumericLiteralTypes: {
146
139
  type: "boolean",
147
- default: false,
148
140
  },
149
141
  ignoreReadonlyClassProperties: {
150
142
  type: "boolean",
151
- default: false,
152
143
  },
153
144
  ignoreTypeIndexes: {
154
145
  type: "boolean",
155
- default: false,
156
146
  },
157
147
  },
158
148
  additionalProperties: false,
159
149
  },
160
150
  ],
161
151
 
152
+ defaultOptions: [
153
+ {
154
+ detectObjects: false,
155
+ enforceConst: false,
156
+ ignore: [],
157
+ ignoreArrayIndexes: false,
158
+ ignoreDefaultValues: false,
159
+ ignoreClassFieldInitialValues: false,
160
+ ignoreEnums: false,
161
+ ignoreNumericLiteralTypes: false,
162
+ ignoreReadonlyClassProperties: false,
163
+ ignoreTypeIndexes: false,
164
+ },
165
+ ],
166
+
162
167
  messages: {
163
168
  useConst: "Number constants declarations must use 'const'.",
164
169
  noMagic: "No magic number: {{raw}}.",
@@ -166,19 +171,19 @@ module.exports = {
166
171
  },
167
172
 
168
173
  create(context) {
169
- const config = context.options[0] || {},
170
- detectObjects = !!config.detectObjects,
171
- enforceConst = !!config.enforceConst,
172
- ignore = new Set((config.ignore || []).map(normalizeIgnoreValue)),
173
- ignoreArrayIndexes = !!config.ignoreArrayIndexes,
174
- ignoreDefaultValues = !!config.ignoreDefaultValues,
175
- ignoreClassFieldInitialValues =
176
- !!config.ignoreClassFieldInitialValues,
177
- ignoreEnums = !!config.ignoreEnums,
178
- ignoreNumericLiteralTypes = !!config.ignoreNumericLiteralTypes,
179
- ignoreReadonlyClassProperties =
180
- !!config.ignoreReadonlyClassProperties,
181
- ignoreTypeIndexes = !!config.ignoreTypeIndexes;
174
+ const {
175
+ detectObjects,
176
+ enforceConst,
177
+ ignore: rawIgnore,
178
+ ignoreArrayIndexes,
179
+ ignoreDefaultValues,
180
+ ignoreClassFieldInitialValues,
181
+ ignoreEnums,
182
+ ignoreNumericLiteralTypes,
183
+ ignoreReadonlyClassProperties,
184
+ ignoreTypeIndexes,
185
+ } = context.options[0];
186
+ const ignore = new Set(rawIgnore.map(normalizeIgnoreValue));
182
187
 
183
188
  const okTypes = detectObjects
184
189
  ? []
@@ -92,6 +92,8 @@ module.exports = {
92
92
  },
93
93
  ],
94
94
 
95
+ defaultOptions: [{}],
96
+
95
97
  messages: {
96
98
  restrictedNamed:
97
99
  "'{{name}}' is restricted from being used as an exported name.",
@@ -100,14 +102,12 @@ module.exports = {
100
102
  },
101
103
 
102
104
  create(context) {
103
- const restrictedNames = new Set(
104
- context.options[0] && context.options[0].restrictedNamedExports,
105
- );
106
- const restrictedNamePattern =
107
- context.options[0] &&
108
- context.options[0].restrictedNamedExportsPattern;
109
- const restrictDefaultExports =
110
- context.options[0] && context.options[0].restrictDefaultExports;
105
+ const {
106
+ restrictedNamedExports,
107
+ restrictedNamedExportsPattern: restrictedNamePattern,
108
+ restrictDefaultExports,
109
+ } = context.options[0];
110
+ const restrictedNames = new Set(restrictedNamedExports);
111
111
  const sourceCode = context.sourceCode;
112
112
 
113
113
  /**
@@ -53,12 +53,11 @@ const arrayOfGlobals = {
53
53
  /** @type {import('../types').Rule.RuleModule} */
54
54
  module.exports = {
55
55
  meta: {
56
- dialects: ["javascript", "typescript"],
57
- language: "javascript",
58
56
  type: "suggestion",
59
57
 
60
58
  docs: {
61
59
  description: "Disallow specified global variables",
60
+ dialects: ["JavaScript", "TypeScript"],
62
61
  recommended: false,
63
62
  url: "https://eslint.org/docs/latest/rules/no-restricted-globals",
64
63
  },
@@ -171,11 +171,10 @@ const arrayOfStringsOrObjectPatterns = {
171
171
  module.exports = {
172
172
  meta: {
173
173
  type: "suggestion",
174
- dialects: ["typescript", "javascript"],
175
- language: "javascript",
176
174
 
177
175
  docs: {
178
176
  description: "Disallow specified modules when loaded by `import`",
177
+ dialects: ["JavaScript", "TypeScript"],
179
178
  recommended: false,
180
179
  url: "https://eslint.org/docs/latest/rules/no-restricted-imports",
181
180
  },
@@ -70,6 +70,8 @@ module.exports = {
70
70
  uniqueItems: true,
71
71
  },
72
72
 
73
+ defaultOptions: [],
74
+
73
75
  messages: {
74
76
  restrictedObjectProperty:
75
77
  // eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
@@ -41,6 +41,8 @@ module.exports = {
41
41
  minItems: 0,
42
42
  },
43
43
 
44
+ defaultOptions: [],
45
+
44
46
  messages: {
45
47
  // eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
46
48
  restrictedSyntax: "{{message}}",
@@ -55,8 +55,6 @@ const ALLOWED_FUNCTION_VARIABLE_DEF_TYPES = new Set([
55
55
  module.exports = {
56
56
  meta: {
57
57
  type: "suggestion",
58
- dialects: ["typescript", "javascript"],
59
- language: "javascript",
60
58
 
61
59
  defaultOptions: [
62
60
  {
@@ -72,6 +70,7 @@ module.exports = {
72
70
  docs: {
73
71
  description:
74
72
  "Disallow variable declarations from shadowing variables declared in the outer scope",
73
+ dialects: ["JavaScript", "TypeScript"],
75
74
  recommended: false,
76
75
  url: "https://eslint.org/docs/latest/rules/no-shadow",
77
76
  },
@@ -12,12 +12,11 @@
12
12
  module.exports = {
13
13
  meta: {
14
14
  type: "problem",
15
- dialects: ["typescript", "javascript"],
16
- language: "javascript",
17
15
 
18
16
  docs: {
19
17
  description:
20
18
  "Disallow `let` or `var` variables that are read but never assigned",
19
+ dialects: ["JavaScript", "TypeScript"],
21
20
  recommended: true,
22
21
  url: "https://eslint.org/docs/latest/rules/no-unassigned-vars",
23
22
  },
@@ -29,12 +29,11 @@ function alwaysFalse() {
29
29
  /** @type {import('../types').Rule.RuleModule} */
30
30
  module.exports = {
31
31
  meta: {
32
- dialects: ["javascript", "typescript"],
33
- language: "javascript",
34
32
  type: "suggestion",
35
33
 
36
34
  docs: {
37
35
  description: "Disallow unused expressions",
36
+ dialects: ["JavaScript", "TypeScript"],
38
37
  recommended: false,
39
38
  url: "https://eslint.org/docs/latest/rules/no-unused-expressions",
40
39
  },
@@ -5,6 +5,12 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ //------------------------------------------------------------------------------
9
+ // Requirements
10
+ //------------------------------------------------------------------------------
11
+
12
+ const astUtils = require("./utils/ast-utils");
13
+
8
14
  //------------------------------------------------------------------------------
9
15
  // Rule Definition
10
16
  //------------------------------------------------------------------------------
@@ -13,6 +19,7 @@
13
19
  module.exports = {
14
20
  meta: {
15
21
  type: "problem",
22
+ hasSuggestions: true,
16
23
 
17
24
  docs: {
18
25
  description: "Disallow unused private class members",
@@ -25,12 +32,168 @@ module.exports = {
25
32
  messages: {
26
33
  unusedPrivateClassMember:
27
34
  "'{{classMemberName}}' is defined but never used.",
35
+ removeUnusedPrivateClassMember:
36
+ "Remove unused private class member '{{classMemberName}}'.",
28
37
  },
29
38
  },
30
39
 
31
40
  create(context) {
41
+ const sourceCode = context.sourceCode;
32
42
  const trackedClasses = [];
33
43
 
44
+ /**
45
+ * Gets the start index of the line that contains a given token or node.
46
+ * @param {ASTNode|Token|Comment} nodeOrToken The token or node to check
47
+ * @returns {number} The line start index
48
+ */
49
+ function getLineStartIndex(nodeOrToken) {
50
+ return nodeOrToken.range[0] - nodeOrToken.loc.start.column;
51
+ }
52
+
53
+ /**
54
+ * Checks whether a token or node starts on its own line, preceded only by whitespace.
55
+ * @param {ASTNode|Token|Comment} nodeOrToken The token or node to check
56
+ * @returns {boolean} Whether the token or node starts on its own line
57
+ */
58
+ function startsOnOwnLine(nodeOrToken) {
59
+ return (
60
+ sourceCode.getTokenBefore(nodeOrToken, {
61
+ includeComments: true,
62
+ }).loc.end.line !== nodeOrToken.loc.start.line
63
+ );
64
+ }
65
+
66
+ /**
67
+ * Gets leading comments that are directly attached to a class member.
68
+ * @param {ASTNode} classMemberNode The class member node
69
+ * @returns {Comment[]} Leading comments to remove with the member
70
+ */
71
+ function getLeadingComments(classMemberNode) {
72
+ const commentsBefore =
73
+ sourceCode.getCommentsBefore(classMemberNode);
74
+ const lastNonLeadingCommentIndex = commentsBefore.findLastIndex(
75
+ (comment, index, self) => {
76
+ const next =
77
+ index < self.length - 1
78
+ ? self[index + 1]
79
+ : classMemberNode;
80
+
81
+ return (
82
+ !startsOnOwnLine(comment) ||
83
+ next.loc.start.line - comment.loc.end.line > 1
84
+ );
85
+ },
86
+ );
87
+
88
+ return commentsBefore.slice(lastNonLeadingCommentIndex + 1);
89
+ }
90
+
91
+ /**
92
+ * Checks whether a class member shares its line with another token.
93
+ * @param {ASTNode} classMemberNode The class member node
94
+ * @returns {boolean} Whether the member shares its line with another token
95
+ */
96
+ function sharesLineWithAnotherToken(classMemberNode) {
97
+ const previousToken = sourceCode.getTokenBefore(classMemberNode);
98
+ const nextToken = sourceCode.getTokenAfter(classMemberNode);
99
+
100
+ return (
101
+ previousToken.loc.end.line === classMemberNode.loc.start.line ||
102
+ nextToken.loc.start.line === classMemberNode.loc.end.line
103
+ );
104
+ }
105
+
106
+ /**
107
+ * Gets trailing comments that are directly attached to a class member.
108
+ * Same-line trailing comments are preserved when another token shares
109
+ * the line, because the comment might describe the remaining code rather
110
+ * than the unused member alone.
111
+ * @param {ASTNode} classMemberNode The class member node
112
+ * @returns {Comment[]} Trailing comments to remove with the member
113
+ */
114
+ function getTrailingComments(classMemberNode) {
115
+ if (sharesLineWithAnotherToken(classMemberNode)) {
116
+ return [];
117
+ }
118
+
119
+ return sourceCode
120
+ .getCommentsAfter(classMemberNode)
121
+ .filter(
122
+ comment =>
123
+ comment.loc.start.line === classMemberNode.loc.end.line,
124
+ );
125
+ }
126
+
127
+ /**
128
+ * Gets the token after which a semicolon should be inserted when removing a class member.
129
+ * @param {ASTNode} classMemberNode The member that would be removed
130
+ * @returns {Token|null} The token after which a semicolon should be inserted, or null if no semicolon is needed
131
+ */
132
+ function getSemicolonInsertionToken(classMemberNode) {
133
+ const nextToken = sourceCode.getTokenAfter(classMemberNode);
134
+
135
+ if (
136
+ astUtils.canContinueExpressionInClassBody(nextToken) &&
137
+ astUtils.needsPrecedingSemicolon(sourceCode, classMemberNode)
138
+ ) {
139
+ return sourceCode.getTokenBefore(classMemberNode);
140
+ }
141
+
142
+ return null;
143
+ }
144
+
145
+ /**
146
+ * Gets the replacement range for removing an unused class member.
147
+ * @param {ASTNode} classMemberNode The member that would be removed
148
+ * @returns {number[]} The text range to remove
149
+ */
150
+ function getMemberRemovalRange(classMemberNode) {
151
+ const leadingComments = getLeadingComments(classMemberNode);
152
+ const trailingComments = getTrailingComments(classMemberNode);
153
+ const shouldRemoveLeadingComments =
154
+ leadingComments.length > 0 &&
155
+ !sharesLineWithAnotherToken(classMemberNode);
156
+ const lastItemToRemove =
157
+ trailingComments.length > 0
158
+ ? trailingComments.at(-1)
159
+ : classMemberNode;
160
+
161
+ const previousToken = sourceCode.getTokenBefore(classMemberNode);
162
+ const nextToken = sourceCode.getTokenAfter(lastItemToRemove, {
163
+ includeComments: true,
164
+ });
165
+ const nextTokenStartsOnNewLine =
166
+ nextToken.loc.start.line > lastItemToRemove.loc.end.line;
167
+ const shouldRemoveOwnLine =
168
+ !shouldRemoveLeadingComments &&
169
+ startsOnOwnLine(classMemberNode) &&
170
+ nextTokenStartsOnNewLine;
171
+ let start = classMemberNode.range[0];
172
+ let end = lastItemToRemove.range[1];
173
+
174
+ if (shouldRemoveLeadingComments) {
175
+ start = nextTokenStartsOnNewLine
176
+ ? getLineStartIndex(leadingComments[0])
177
+ : leadingComments[0].range[0];
178
+ end = nextTokenStartsOnNewLine
179
+ ? getLineStartIndex(nextToken)
180
+ : nextToken.range[0];
181
+ } else if (shouldRemoveOwnLine) {
182
+ start = getLineStartIndex(classMemberNode);
183
+ end = getLineStartIndex(nextToken);
184
+ } else if (
185
+ previousToken.loc.end.line === classMemberNode.loc.start.line
186
+ ) {
187
+ start = previousToken.range[1];
188
+ } else if (
189
+ nextToken.loc.start.line === lastItemToRemove.loc.end.line
190
+ ) {
191
+ end = nextToken.range[0];
192
+ }
193
+
194
+ return [start, end];
195
+ }
196
+
34
197
  /**
35
198
  * Check whether the current node is in a write only assignment.
36
199
  * @param {ASTNode} privateIdentifierNode Node referring to a private identifier
@@ -86,6 +249,7 @@ module.exports = {
86
249
  if (bodyMember.key.type === "PrivateIdentifier") {
87
250
  privateMembers.set(bodyMember.key.name, {
88
251
  declaredNode: bodyMember,
252
+ hasReference: false,
89
253
  isAccessor:
90
254
  bodyMember.type === "MethodDefinition" &&
91
255
  (bodyMember.kind === "set" ||
@@ -128,6 +292,8 @@ module.exports = {
128
292
  return;
129
293
  }
130
294
 
295
+ memberDefinition.hasReference = true;
296
+
131
297
  /*
132
298
  * Any usage of an accessor is considered a read, as the getter/setter can have
133
299
  * side-effects in its definition.
@@ -199,11 +365,12 @@ module.exports = {
199
365
 
200
366
  for (const [
201
367
  classMemberName,
202
- { declaredNode, isUsed },
368
+ { declaredNode, hasReference, isUsed },
203
369
  ] of unusedPrivateMembers.entries()) {
204
370
  if (isUsed) {
205
371
  continue;
206
372
  }
373
+
207
374
  context.report({
208
375
  node: declaredNode,
209
376
  loc: declaredNode.key.loc,
@@ -211,6 +378,39 @@ module.exports = {
211
378
  data: {
212
379
  classMemberName: `#${classMemberName}`,
213
380
  },
381
+ suggest: [
382
+ {
383
+ messageId: "removeUnusedPrivateClassMember",
384
+ data: {
385
+ classMemberName: `#${classMemberName}`,
386
+ },
387
+ *fix(fixer) {
388
+ if (hasReference) {
389
+ return;
390
+ }
391
+
392
+ const removalRange =
393
+ getMemberRemovalRange(declaredNode);
394
+ const semicolonInsertionToken =
395
+ getSemicolonInsertionToken(
396
+ declaredNode,
397
+ );
398
+ const removalFix = fixer.replaceTextRange(
399
+ removalRange,
400
+ "",
401
+ );
402
+
403
+ yield removalFix;
404
+
405
+ if (semicolonInsertionToken) {
406
+ yield fixer.insertTextAfter(
407
+ semicolonInsertionToken,
408
+ ";",
409
+ );
410
+ }
411
+ },
412
+ },
413
+ ],
214
414
  });
215
415
  }
216
416
  },
@@ -42,6 +42,20 @@ const astUtils = require("./utils/ast-utils");
42
42
  * @property {string} additional Any additional info to be appended at the end.
43
43
  */
44
44
 
45
+ //------------------------------------------------------------------------------
46
+ // Helpers
47
+ //------------------------------------------------------------------------------
48
+
49
+ const DEFAULT_OPTIONS = {
50
+ vars: "all",
51
+ args: "after-used",
52
+ ignoreRestSiblings: false,
53
+ caughtErrors: "all",
54
+ ignoreClassWithStaticInitBlock: false,
55
+ ignoreUsingDeclarations: false,
56
+ reportUsedIgnorePattern: false,
57
+ };
58
+
45
59
  //------------------------------------------------------------------------------
46
60
  // Rule Definition
47
61
  //------------------------------------------------------------------------------
@@ -108,6 +122,8 @@ module.exports = {
108
122
  },
109
123
  ],
110
124
 
125
+ defaultOptions: [DEFAULT_OPTIONS],
126
+
111
127
  messages: {
112
128
  unusedVar:
113
129
  "'{{varName}}' is {{action}} but never used{{additional}}.",
@@ -123,65 +139,46 @@ module.exports = {
123
139
  const REST_PROPERTY_TYPE =
124
140
  /^(?:RestElement|(?:Experimental)?RestProperty)$/u;
125
141
 
126
- const config = {
127
- vars: "all",
128
- args: "after-used",
129
- ignoreRestSiblings: false,
130
- caughtErrors: "all",
131
- ignoreClassWithStaticInitBlock: false,
132
- ignoreUsingDeclarations: false,
133
- reportUsedIgnorePattern: false,
134
- };
142
+ let config;
135
143
 
136
144
  const firstOption = context.options[0];
137
145
 
138
- if (firstOption) {
139
- if (typeof firstOption === "string") {
140
- config.vars = firstOption;
141
- } else {
142
- config.vars = firstOption.vars || config.vars;
143
- config.args = firstOption.args || config.args;
144
- config.ignoreRestSiblings =
145
- firstOption.ignoreRestSiblings || config.ignoreRestSiblings;
146
- config.caughtErrors =
147
- firstOption.caughtErrors || config.caughtErrors;
148
- config.ignoreClassWithStaticInitBlock =
149
- firstOption.ignoreClassWithStaticInitBlock ||
150
- config.ignoreClassWithStaticInitBlock;
151
- config.ignoreUsingDeclarations =
152
- firstOption.ignoreUsingDeclarations ||
153
- config.ignoreUsingDeclarations;
154
- config.reportUsedIgnorePattern =
155
- firstOption.reportUsedIgnorePattern ||
156
- config.reportUsedIgnorePattern;
157
-
158
- if (firstOption.varsIgnorePattern) {
159
- config.varsIgnorePattern = new RegExp(
160
- firstOption.varsIgnorePattern,
161
- "u",
162
- );
163
- }
146
+ if (typeof firstOption === "string") {
147
+ config = {
148
+ ...DEFAULT_OPTIONS,
149
+ vars: firstOption,
150
+ };
151
+ } else {
152
+ config = {
153
+ ...firstOption,
154
+ };
164
155
 
165
- if (firstOption.argsIgnorePattern) {
166
- config.argsIgnorePattern = new RegExp(
167
- firstOption.argsIgnorePattern,
168
- "u",
169
- );
170
- }
156
+ if (firstOption.varsIgnorePattern) {
157
+ config.varsIgnorePattern = new RegExp(
158
+ firstOption.varsIgnorePattern,
159
+ "u",
160
+ );
161
+ }
171
162
 
172
- if (firstOption.caughtErrorsIgnorePattern) {
173
- config.caughtErrorsIgnorePattern = new RegExp(
174
- firstOption.caughtErrorsIgnorePattern,
175
- "u",
176
- );
177
- }
163
+ if (firstOption.argsIgnorePattern) {
164
+ config.argsIgnorePattern = new RegExp(
165
+ firstOption.argsIgnorePattern,
166
+ "u",
167
+ );
168
+ }
178
169
 
179
- if (firstOption.destructuredArrayIgnorePattern) {
180
- config.destructuredArrayIgnorePattern = new RegExp(
181
- firstOption.destructuredArrayIgnorePattern,
182
- "u",
183
- );
184
- }
170
+ if (firstOption.caughtErrorsIgnorePattern) {
171
+ config.caughtErrorsIgnorePattern = new RegExp(
172
+ firstOption.caughtErrorsIgnorePattern,
173
+ "u",
174
+ );
175
+ }
176
+
177
+ if (firstOption.destructuredArrayIgnorePattern) {
178
+ config.destructuredArrayIgnorePattern = new RegExp(
179
+ firstOption.destructuredArrayIgnorePattern,
180
+ "u",
181
+ );
185
182
  }
186
183
  }
187
184
 
@@ -276,13 +276,12 @@ function isClassRefInClassDecorator(variable, reference) {
276
276
  /** @type {import('../types').Rule.RuleModule} */
277
277
  module.exports = {
278
278
  meta: {
279
- dialects: ["javascript", "typescript"],
280
- language: "javascript",
281
279
  type: "problem",
282
280
 
283
281
  docs: {
284
282
  description:
285
283
  "Disallow the use of variables before they are defined",
284
+ dialects: ["JavaScript", "TypeScript"],
286
285
  recommended: false,
287
286
  url: "https://eslint.org/docs/latest/rules/no-use-before-define",
288
287
  },
@@ -33,7 +33,7 @@ function isConcatOperatorToken(token) {
33
33
  }
34
34
 
35
35
  /**
36
- * Get's the right most node on the left side of a BinaryExpression with + operator.
36
+ * Gets the right most node on the left side of a BinaryExpression with + operator.
37
37
  * @param {ASTNode} node A BinaryExpression node to check.
38
38
  * @returns {ASTNode} node
39
39
  */
@@ -47,7 +47,7 @@ function getLeft(node) {
47
47
  }
48
48
 
49
49
  /**
50
- * Get's the left most node on the right side of a BinaryExpression with + operator.
50
+ * Gets the left most node on the right side of a BinaryExpression with + operator.
51
51
  * @param {ASTNode} node A BinaryExpression node to check.
52
52
  * @returns {ASTNode} node
53
53
  */
@@ -164,12 +164,11 @@ function isRedundantSuperCall(body, ctorParams) {
164
164
  /** @type {import('../types').Rule.RuleModule} */
165
165
  module.exports = {
166
166
  meta: {
167
- dialects: ["javascript", "typescript"],
168
- language: "javascript",
169
167
  type: "suggestion",
170
168
 
171
169
  docs: {
172
170
  description: "Disallow unnecessary constructors",
171
+ dialects: ["JavaScript", "TypeScript"],
173
172
  recommended: false,
174
173
  url: "https://eslint.org/docs/latest/rules/no-useless-constructor",
175
174
  },
@@ -237,8 +236,9 @@ module.exports = {
237
236
  const nextToken =
238
237
  sourceCode.getTokenAfter(node);
239
238
  const addSemiColon =
240
- nextToken.type === "Punctuator" &&
241
- nextToken.value === "[" &&
239
+ astUtils.canContinueExpressionInClassBody(
240
+ nextToken,
241
+ ) &&
242
242
  astUtils.needsPrecedingSemicolon(
243
243
  sourceCode,
244
244
  node,