eslint 9.27.0 → 9.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.
Files changed (37) hide show
  1. package/README.md +1 -1
  2. package/conf/ecma-version.js +1 -1
  3. package/conf/globals.js +10 -0
  4. package/lib/cli.js +20 -23
  5. package/lib/config/config-loader.js +32 -21
  6. package/lib/config/config.js +34 -11
  7. package/lib/eslint/eslint.js +18 -21
  8. package/lib/languages/js/source-code/source-code.js +104 -27
  9. package/lib/linter/apply-disable-directives.js +2 -4
  10. package/lib/linter/code-path-analysis/code-path-analyzer.js +8 -9
  11. package/lib/linter/linter.js +30 -61
  12. package/lib/linter/source-code-traverser.js +327 -0
  13. package/lib/linter/source-code-visitor.js +81 -0
  14. package/lib/options.js +7 -0
  15. package/lib/rules/class-methods-use-this.js +7 -0
  16. package/lib/rules/func-style.js +57 -7
  17. package/lib/rules/no-implicit-globals.js +31 -15
  18. package/lib/rules/no-magic-numbers.js +98 -5
  19. package/lib/rules/no-promise-executor-return.js +4 -35
  20. package/lib/rules/no-restricted-globals.js +35 -2
  21. package/lib/rules/no-restricted-properties.js +24 -10
  22. package/lib/rules/no-setter-return.js +13 -48
  23. package/lib/rules/no-shadow.js +262 -6
  24. package/lib/rules/no-unassigned-vars.js +14 -6
  25. package/lib/rules/no-use-before-define.js +99 -1
  26. package/lib/rules/no-var.js +14 -2
  27. package/lib/rules/prefer-arrow-callback.js +9 -0
  28. package/lib/rules/prefer-regex-literals.js +1 -18
  29. package/lib/services/suppressions-service.js +8 -0
  30. package/lib/services/warning-service.js +85 -0
  31. package/lib/shared/naming.js +109 -0
  32. package/lib/shared/relative-module-resolver.js +28 -0
  33. package/lib/types/index.d.ts +18 -7
  34. package/lib/types/rules.d.ts +52 -2
  35. package/package.json +12 -10
  36. package/lib/linter/node-event-generator.js +0 -256
  37. package/lib/linter/safe-emitter.js +0 -52
@@ -10,33 +10,16 @@
10
10
  //------------------------------------------------------------------------------
11
11
 
12
12
  const astUtils = require("./utils/ast-utils");
13
- const { findVariable } = require("@eslint-community/eslint-utils");
14
13
 
15
14
  //------------------------------------------------------------------------------
16
15
  // Helpers
17
16
  //------------------------------------------------------------------------------
18
17
 
19
- /**
20
- * Determines whether the given identifier node is a reference to a global variable.
21
- * @param {ASTNode} node `Identifier` node to check.
22
- * @param {Scope} scope Scope to which the node belongs.
23
- * @returns {boolean} True if the identifier is a reference to a global variable.
24
- */
25
- function isGlobalReference(node, scope) {
26
- const variable = findVariable(scope, node);
27
-
28
- return (
29
- variable !== null &&
30
- variable.scope.type === "global" &&
31
- variable.defs.length === 0
32
- );
33
- }
34
-
35
18
  /**
36
19
  * Determines whether the given node is an argument of the specified global method call, at the given `index` position.
37
20
  * E.g., for given `index === 1`, this function checks for `objectName.methodName(foo, node)`, where objectName is a global variable.
38
21
  * @param {ASTNode} node The node to check.
39
- * @param {Scope} scope Scope to which the node belongs.
22
+ * @param {SourceCode} sourceCode Source code to which the node belongs.
40
23
  * @param {string} objectName Name of the global object.
41
24
  * @param {string} methodName Name of the method.
42
25
  * @param {number} index The given position.
@@ -44,7 +27,7 @@ function isGlobalReference(node, scope) {
44
27
  */
45
28
  function isArgumentOfGlobalMethodCall(
46
29
  node,
47
- scope,
30
+ sourceCode,
48
31
  objectName,
49
32
  methodName,
50
33
  index,
@@ -59,9 +42,8 @@ function isArgumentOfGlobalMethodCall(
59
42
  objectName,
60
43
  methodName,
61
44
  ) &&
62
- isGlobalReference(
45
+ sourceCode.isGlobalReference(
63
46
  astUtils.skipChainExpression(callNode.callee).object,
64
- scope,
65
47
  )
66
48
  );
67
49
  }
@@ -69,21 +51,21 @@ function isArgumentOfGlobalMethodCall(
69
51
  /**
70
52
  * Determines whether the given node is used as a property descriptor.
71
53
  * @param {ASTNode} node The node to check.
72
- * @param {Scope} scope Scope to which the node belongs.
54
+ * @param {SourceCode} sourceCode Source code to which the node belongs.
73
55
  * @returns {boolean} `true` if the node is a property descriptor.
74
56
  */
75
- function isPropertyDescriptor(node, scope) {
57
+ function isPropertyDescriptor(node, sourceCode) {
76
58
  if (
77
59
  isArgumentOfGlobalMethodCall(
78
60
  node,
79
- scope,
61
+ sourceCode,
80
62
  "Object",
81
63
  "defineProperty",
82
64
  2,
83
65
  ) ||
84
66
  isArgumentOfGlobalMethodCall(
85
67
  node,
86
- scope,
68
+ sourceCode,
87
69
  "Reflect",
88
70
  "defineProperty",
89
71
  2,
@@ -101,14 +83,14 @@ function isPropertyDescriptor(node, scope) {
101
83
  grandparent.type === "ObjectExpression" &&
102
84
  (isArgumentOfGlobalMethodCall(
103
85
  grandparent,
104
- scope,
86
+ sourceCode,
105
87
  "Object",
106
88
  "create",
107
89
  1,
108
90
  ) ||
109
91
  isArgumentOfGlobalMethodCall(
110
92
  grandparent,
111
- scope,
93
+ sourceCode,
112
94
  "Object",
113
95
  "defineProperties",
114
96
  1,
@@ -124,10 +106,10 @@ function isPropertyDescriptor(node, scope) {
124
106
  /**
125
107
  * Determines whether the given function node is used as a setter function.
126
108
  * @param {ASTNode} node The node to check.
127
- * @param {Scope} scope Scope to which the node belongs.
109
+ * @param {SourceCode} sourceCode Source code to which the node belongs.
128
110
  * @returns {boolean} `true` if the node is a setter.
129
111
  */
130
- function isSetter(node, scope) {
112
+ function isSetter(node, sourceCode) {
131
113
  const parent = node.parent;
132
114
 
133
115
  if (
@@ -144,7 +126,7 @@ function isSetter(node, scope) {
144
126
  parent.value === node &&
145
127
  astUtils.getStaticPropertyName(parent) === "set" &&
146
128
  parent.parent.type === "ObjectExpression" &&
147
- isPropertyDescriptor(parent.parent, scope)
129
+ isPropertyDescriptor(parent.parent, sourceCode)
148
130
  ) {
149
131
  // Setter in a property descriptor
150
132
  return true;
@@ -153,21 +135,6 @@ function isSetter(node, scope) {
153
135
  return false;
154
136
  }
155
137
 
156
- /**
157
- * Finds function's outer scope.
158
- * @param {Scope} scope Function's own scope.
159
- * @returns {Scope} Function's outer scope.
160
- */
161
- function getOuterScope(scope) {
162
- const upper = scope.upper;
163
-
164
- if (upper.type === "function-expression-name") {
165
- return upper.upper;
166
- }
167
-
168
- return upper;
169
- }
170
-
171
138
  //------------------------------------------------------------------------------
172
139
  // Rule Definition
173
140
  //------------------------------------------------------------------------------
@@ -200,11 +167,9 @@ module.exports = {
200
167
  * @returns {void}
201
168
  */
202
169
  function enterFunction(node) {
203
- const outerScope = getOuterScope(sourceCode.getScope(node));
204
-
205
170
  funcInfo = {
206
171
  upper: funcInfo,
207
- isSetter: isSetter(node, outerScope),
172
+ isSetter: isSetter(node, sourceCode),
208
173
  };
209
174
  }
210
175
 
@@ -24,6 +24,23 @@ const FOR_IN_OF_TYPE = /^For(?:In|Of)Statement$/u;
24
24
  const SENTINEL_TYPE =
25
25
  /^(?:(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|CatchClause|ImportDeclaration|ExportNamedDeclaration)$/u;
26
26
 
27
+ // TS-specific node types
28
+ const TYPES_HOISTED_NODES = new Set([
29
+ "TSInterfaceDeclaration",
30
+ "TSTypeAliasDeclaration",
31
+ ]);
32
+
33
+ // TS-specific function variable def types
34
+ const ALLOWED_FUNCTION_VARIABLE_DEF_TYPES = new Set([
35
+ "TSCallSignatureDeclaration",
36
+ "TSFunctionType",
37
+ "TSMethodSignature",
38
+ "TSEmptyBodyFunctionExpression",
39
+ "TSDeclareFunction",
40
+ "TSConstructSignatureDeclaration",
41
+ "TSConstructorType",
42
+ ]);
43
+
27
44
  //------------------------------------------------------------------------------
28
45
  // Rule Definition
29
46
  //------------------------------------------------------------------------------
@@ -32,6 +49,8 @@ const SENTINEL_TYPE =
32
49
  module.exports = {
33
50
  meta: {
34
51
  type: "suggestion",
52
+ dialects: ["typescript", "javascript"],
53
+ language: "javascript",
35
54
 
36
55
  defaultOptions: [
37
56
  {
@@ -39,6 +58,8 @@ module.exports = {
39
58
  builtinGlobals: false,
40
59
  hoist: "functions",
41
60
  ignoreOnInitialization: false,
61
+ ignoreTypeValueShadow: true,
62
+ ignoreFunctionTypeParameterNameValueShadow: true,
42
63
  },
43
64
  ],
44
65
 
@@ -54,7 +75,15 @@ module.exports = {
54
75
  type: "object",
55
76
  properties: {
56
77
  builtinGlobals: { type: "boolean" },
57
- hoist: { enum: ["all", "functions", "never"] },
78
+ hoist: {
79
+ enum: [
80
+ "all",
81
+ "functions",
82
+ "never",
83
+ "types",
84
+ "functions-and-types",
85
+ ],
86
+ },
58
87
  allow: {
59
88
  type: "array",
60
89
  items: {
@@ -62,6 +91,10 @@ module.exports = {
62
91
  },
63
92
  },
64
93
  ignoreOnInitialization: { type: "boolean" },
94
+ ignoreTypeValueShadow: { type: "boolean" },
95
+ ignoreFunctionTypeParameterNameValueShadow: {
96
+ type: "boolean",
97
+ },
65
98
  },
66
99
  additionalProperties: false,
67
100
  },
@@ -75,10 +108,112 @@ module.exports = {
75
108
  },
76
109
 
77
110
  create(context) {
78
- const [{ builtinGlobals, hoist, allow, ignoreOnInitialization }] =
79
- context.options;
111
+ const [
112
+ {
113
+ builtinGlobals,
114
+ hoist,
115
+ allow,
116
+ ignoreOnInitialization,
117
+ ignoreTypeValueShadow,
118
+ ignoreFunctionTypeParameterNameValueShadow,
119
+ },
120
+ ] = context.options;
80
121
  const sourceCode = context.sourceCode;
81
122
 
123
+ /**
124
+ * Check if a scope is a TypeScript module augmenting the global namespace.
125
+ * @param {Scope} scope The scope to check
126
+ * @returns {boolean} Whether the scope is a global augmentation
127
+ */
128
+ function isGlobalAugmentation(scope) {
129
+ return (
130
+ scope.block.kind === "global" ||
131
+ (!!scope.upper && isGlobalAugmentation(scope.upper))
132
+ );
133
+ }
134
+
135
+ /**
136
+ * Check if variable is a `this` parameter.
137
+ * @param {Object} variable The variable to check
138
+ * @returns {boolean} Whether the variable is a this parameter
139
+ */
140
+ function isThisParam(variable) {
141
+ return variable.name === "this";
142
+ }
143
+
144
+ /**
145
+ * Checks if type and value shadows each other
146
+ * @param {Object} variable The variable to check
147
+ * @param {Object} shadowedVariable The shadowed variable
148
+ * @returns {boolean} Whether it's a type/value shadow case to ignore
149
+ */
150
+ function isTypeValueShadow(variable, shadowedVariable) {
151
+ if (ignoreTypeValueShadow !== true) {
152
+ return false;
153
+ }
154
+
155
+ if (!("isValueVariable" in variable)) {
156
+ return false;
157
+ }
158
+
159
+ const firstDefinition = shadowedVariable.defs[0];
160
+
161
+ // Check if shadowedVariable is a type import
162
+ const isTypeImport =
163
+ firstDefinition &&
164
+ firstDefinition.parent?.type === "ImportDeclaration" &&
165
+ (firstDefinition.parent.importKind === "type" ||
166
+ firstDefinition.parent.specifiers.some(
167
+ s => s.importKind === "type",
168
+ ));
169
+
170
+ const isShadowedValue =
171
+ !firstDefinition ||
172
+ (isTypeImport ? false : shadowedVariable.isValueVariable);
173
+
174
+ return variable.isValueVariable !== isShadowedValue;
175
+ }
176
+
177
+ /**
178
+ * Checks if it's a function type parameter shadow
179
+ * @param {Object} variable The variable to check
180
+ * @returns {boolean} Whether it's a function type parameter shadow case to ignore
181
+ */
182
+ function isFunctionTypeParameterNameValueShadow(variable) {
183
+ if (ignoreFunctionTypeParameterNameValueShadow !== true) {
184
+ return false;
185
+ }
186
+
187
+ return variable.defs.some(def =>
188
+ ALLOWED_FUNCTION_VARIABLE_DEF_TYPES.has(def.node.type),
189
+ );
190
+ }
191
+
192
+ /**
193
+ * Checks if the variable is a generic of a static method
194
+ * @param {Object} variable The variable to check
195
+ * @returns {boolean} Whether the variable is a generic of a static method
196
+ */
197
+ function isTypeParameterOfStaticMethod(variable) {
198
+ const typeParameter = variable.identifiers[0].parent;
199
+ const typeParameterDecl = typeParameter.parent;
200
+ if (typeParameterDecl.type !== "TSTypeParameterDeclaration") {
201
+ return false;
202
+ }
203
+ const functionExpr = typeParameterDecl.parent;
204
+ const methodDefinition = functionExpr.parent;
205
+ return methodDefinition.static;
206
+ }
207
+
208
+ /**
209
+ * Checks for static method generic shadowing class generic
210
+ * @param {Object} variable The variable to check
211
+ * @returns {boolean} Whether it's a static method generic shadowing class generic
212
+ */
213
+ function isGenericOfAStaticMethodShadow(variable) {
214
+ return isTypeParameterOfStaticMethod(variable);
215
+ }
216
+
82
217
  /**
83
218
  * Checks whether or not a given location is inside of the range of a given node.
84
219
  * @param {ASTNode} node An node to check.
@@ -114,7 +249,7 @@ module.exports = {
114
249
  function getOuterScope(scope) {
115
250
  const upper = scope.upper;
116
251
 
117
- if (upper.type === "function-expression-name") {
252
+ if (upper && upper.type === "function-expression-name") {
118
253
  return upper.upper;
119
254
  }
120
255
  return upper;
@@ -284,6 +419,21 @@ module.exports = {
284
419
  const inner = getNameRange(variable);
285
420
  const outer = getNameRange(scopeVar);
286
421
 
422
+ if (!outer || inner[1] >= outer[0]) {
423
+ return false;
424
+ }
425
+
426
+ if (hoist === "types") {
427
+ return !TYPES_HOISTED_NODES.has(outerDef.node.type);
428
+ }
429
+
430
+ if (hoist === "functions-and-types") {
431
+ return (
432
+ outerDef.node.type !== "FunctionDeclaration" &&
433
+ !TYPES_HOISTED_NODES.has(outerDef.node.type)
434
+ );
435
+ }
436
+
287
437
  return (
288
438
  inner &&
289
439
  outer &&
@@ -295,12 +445,111 @@ module.exports = {
295
445
  );
296
446
  }
297
447
 
448
+ /**
449
+ * Checks if the initialization of a variable has the declare modifier in a
450
+ * definition file.
451
+ * @param {Object} variable The variable to check
452
+ * @returns {boolean} Whether the variable is declared in a definition file
453
+ */
454
+ function isDeclareInDTSFile(variable) {
455
+ const fileName = context.filename;
456
+ if (
457
+ !fileName.endsWith(".d.ts") &&
458
+ !fileName.endsWith(".d.cts") &&
459
+ !fileName.endsWith(".d.mts")
460
+ ) {
461
+ return false;
462
+ }
463
+ return variable.defs.some(
464
+ def =>
465
+ (def.type === "Variable" && def.parent.declare) ||
466
+ (def.type === "ClassName" && def.node.declare) ||
467
+ (def.type === "TSEnumName" && def.node.declare) ||
468
+ (def.type === "TSModuleName" && def.node.declare),
469
+ );
470
+ }
471
+
472
+ /**
473
+ * Checks if a variable is a duplicate of an enum name in the enum scope
474
+ * @param {Object} variable The variable to check
475
+ * @returns {boolean} Whether it's a duplicate enum name variable
476
+ */
477
+ function isDuplicatedEnumNameVariable(variable) {
478
+ const block = variable.scope.block;
479
+
480
+ return (
481
+ block.type === "TSEnumDeclaration" &&
482
+ block.id === variable.identifiers[0]
483
+ );
484
+ }
485
+
486
+ /**
487
+ * Check if this is an external module declaration merging with a type import
488
+ * @param {Scope} scope Current scope
489
+ * @param {Object} variable Current variable
490
+ * @param {Object} shadowedVariable Shadowed variable
491
+ * @returns {boolean} Whether it's an external declaration merging
492
+ */
493
+ function isExternalDeclarationMerging(
494
+ scope,
495
+ variable,
496
+ shadowedVariable,
497
+ ) {
498
+ const firstDefinition = shadowedVariable.defs[0];
499
+
500
+ if (!firstDefinition || !firstDefinition.parent) {
501
+ return false;
502
+ }
503
+
504
+ // Check if the shadowed variable is a type import
505
+ const isTypeImport =
506
+ firstDefinition.parent.type === "ImportDeclaration" &&
507
+ (firstDefinition.parent.importKind === "type" ||
508
+ firstDefinition.parent.specifiers?.some(
509
+ s =>
510
+ s.type === "ImportSpecifier" &&
511
+ s.importKind === "type" &&
512
+ s.local.name === shadowedVariable.name,
513
+ ));
514
+
515
+ if (!isTypeImport) {
516
+ return false;
517
+ }
518
+
519
+ // Check if the current variable is within a module declaration
520
+ const moduleDecl = findSelfOrAncestor(
521
+ variable.identifiers[0]?.parent,
522
+ node => node.type === "TSModuleDeclaration",
523
+ );
524
+
525
+ if (!moduleDecl) {
526
+ return false;
527
+ }
528
+
529
+ /*
530
+ * Module declaration merging should only happen within the same module
531
+ * Check if the module name matches the import source
532
+ */
533
+ const importSource = firstDefinition.parent.source.value;
534
+ const moduleName =
535
+ moduleDecl.id.type === "Literal"
536
+ ? moduleDecl.id.value
537
+ : moduleDecl.id.name;
538
+
539
+ return importSource === moduleName;
540
+ }
541
+
298
542
  /**
299
543
  * Checks the current context for shadowed variables.
300
544
  * @param {Scope} scope Fixme
301
545
  * @returns {void}
302
546
  */
303
547
  function checkForShadows(scope) {
548
+ // ignore global augmentation
549
+ if (isGlobalAugmentation(scope)) {
550
+ return;
551
+ }
552
+
304
553
  const variables = scope.variables;
305
554
 
306
555
  for (let i = 0; i < variables.length; ++i) {
@@ -310,7 +559,10 @@ module.exports = {
310
559
  if (
311
560
  variable.identifiers.length === 0 ||
312
561
  isDuplicatedClassNameVariable(variable) ||
313
- isAllowed(variable)
562
+ isDuplicatedEnumNameVariable(variable) ||
563
+ isAllowed(variable) ||
564
+ isDeclareInDTSFile(variable) ||
565
+ isThisParam(variable)
314
566
  ) {
315
567
  continue;
316
568
  }
@@ -330,7 +582,11 @@ module.exports = {
330
582
  ignoreOnInitialization &&
331
583
  isInitPatternNode(variable, shadowed)
332
584
  ) &&
333
- !(hoist !== "all" && isInTdz(variable, shadowed))
585
+ !(hoist !== "all" && isInTdz(variable, shadowed)) &&
586
+ !isTypeValueShadow(variable, shadowed) &&
587
+ !isFunctionTypeParameterNameValueShadow(variable) &&
588
+ !isGenericOfAStaticMethodShadow(variable, shadowed) &&
589
+ !isExternalDeclarationMerging(scope, variable, shadowed)
334
590
  ) {
335
591
  const location = getDeclaredLocation(shadowed);
336
592
  const messageId = location.global
@@ -31,17 +31,25 @@ module.exports = {
31
31
 
32
32
  create(context) {
33
33
  const sourceCode = context.sourceCode;
34
+ let insideDeclareModule = false;
34
35
 
35
36
  return {
37
+ "TSModuleDeclaration[declare=true]"() {
38
+ insideDeclareModule = true;
39
+ },
40
+ "TSModuleDeclaration[declare=true]:exit"() {
41
+ insideDeclareModule = false;
42
+ },
36
43
  VariableDeclarator(node) {
37
44
  /** @type {import('estree').VariableDeclaration} */
38
45
  const declaration = node.parent;
39
- const shouldCheck =
40
- !node.init &&
41
- node.id.type === "Identifier" &&
42
- declaration.kind !== "const" &&
43
- !declaration.declare;
44
- if (!shouldCheck) {
46
+ const shouldSkip =
47
+ node.init ||
48
+ node.id.type !== "Identifier" ||
49
+ declaration.kind === "const" ||
50
+ declaration.declare ||
51
+ insideDeclareModule;
52
+ if (shouldSkip) {
45
53
  return;
46
54
  }
47
55
  const [variable] = sourceCode.getDeclaredVariables(node);
@@ -30,6 +30,9 @@ function parseOptions(options) {
30
30
  classes: true,
31
31
  variables: true,
32
32
  allowNamedExports: false,
33
+ enums: true,
34
+ typedefs: true,
35
+ ignoreTypeReferences: true,
33
36
  };
34
37
  }
35
38
 
@@ -208,6 +211,57 @@ function isEvaluatedDuringInitialization(reference) {
208
211
  return false;
209
212
  }
210
213
 
214
+ /**
215
+ * check whether the reference contains a type query.
216
+ * @param {ASTNode} node Identifier node to check.
217
+ * @returns {boolean} true if reference contains type query.
218
+ */
219
+ function referenceContainsTypeQuery(node) {
220
+ switch (node.type) {
221
+ case "TSTypeQuery":
222
+ return true;
223
+
224
+ case "TSQualifiedName":
225
+ case "Identifier":
226
+ return referenceContainsTypeQuery(node.parent);
227
+
228
+ default:
229
+ // if we find a different node, there's no chance that we're in a TSTypeQuery
230
+ return false;
231
+ }
232
+ }
233
+
234
+ /**
235
+ * Decorators are transpiled such that the decorator is placed after the class declaration
236
+ * So it is considered safe
237
+ * @param {Variable} variable The variable to check.
238
+ * @param {Reference} reference The reference to check.
239
+ * @returns {boolean} `true` if the reference is in a class decorator.
240
+ */
241
+ function isClassRefInClassDecorator(variable, reference) {
242
+ if (variable.defs[0].type !== "ClassName") {
243
+ return false;
244
+ }
245
+
246
+ if (
247
+ !variable.defs[0].node.decorators ||
248
+ variable.defs[0].node.decorators.length === 0
249
+ ) {
250
+ return false;
251
+ }
252
+
253
+ for (const deco of variable.defs[0].node.decorators) {
254
+ if (
255
+ reference.identifier.range[0] >= deco.range[0] &&
256
+ reference.identifier.range[1] <= deco.range[1]
257
+ ) {
258
+ return true;
259
+ }
260
+ }
261
+
262
+ return false;
263
+ }
264
+
211
265
  //------------------------------------------------------------------------------
212
266
  // Rule Definition
213
267
  //------------------------------------------------------------------------------
@@ -215,6 +269,8 @@ function isEvaluatedDuringInitialization(reference) {
215
269
  /** @type {import('../types').Rule.RuleModule} */
216
270
  module.exports = {
217
271
  meta: {
272
+ dialects: ["javascript", "typescript"],
273
+ language: "javascript",
218
274
  type: "problem",
219
275
 
220
276
  docs: {
@@ -237,6 +293,9 @@ module.exports = {
237
293
  classes: { type: "boolean" },
238
294
  variables: { type: "boolean" },
239
295
  allowNamedExports: { type: "boolean" },
296
+ enums: { type: "boolean" },
297
+ typedefs: { type: "boolean" },
298
+ ignoreTypeReferences: { type: "boolean" },
240
299
  },
241
300
  additionalProperties: false,
242
301
  },
@@ -250,6 +309,9 @@ module.exports = {
250
309
  functions: true,
251
310
  variables: true,
252
311
  allowNamedExports: false,
312
+ enums: true,
313
+ typedefs: true,
314
+ ignoreTypeReferences: true,
253
315
  },
254
316
  ],
255
317
 
@@ -310,6 +372,41 @@ module.exports = {
310
372
  return false;
311
373
  }
312
374
 
375
+ if (!options.enums && definitionType === "TSEnumName") {
376
+ return false;
377
+ }
378
+
379
+ if (!options.typedefs && definitionType === "Type") {
380
+ return false;
381
+ }
382
+
383
+ if (
384
+ options.ignoreTypeReferences &&
385
+ (referenceContainsTypeQuery(identifier) ||
386
+ identifier.parent.type === "TSTypeReference")
387
+ ) {
388
+ return false;
389
+ }
390
+
391
+ // skip nested namespace aliases as variable references
392
+ if (identifier.parent.type === "TSQualifiedName") {
393
+ let currentNode = identifier.parent;
394
+
395
+ while (currentNode.type === "TSQualifiedName") {
396
+ currentNode = currentNode.left;
397
+ }
398
+
399
+ if (currentNode === identifier) {
400
+ return true;
401
+ }
402
+
403
+ return false;
404
+ }
405
+
406
+ if (isClassRefInClassDecorator(variable, reference)) {
407
+ return false;
408
+ }
409
+
313
410
  return true;
314
411
  }
315
412
 
@@ -326,7 +423,8 @@ module.exports = {
326
423
  if (
327
424
  reference.identifier.range[1] <
328
425
  definitionIdentifier.range[1] ||
329
- isEvaluatedDuringInitialization(reference)
426
+ (isEvaluatedDuringInitialization(reference) &&
427
+ reference.identifier.parent.type !== "TSTypeReference")
330
428
  ) {
331
429
  context.report({
332
430
  node: reference.identifier,
@@ -199,6 +199,8 @@ function hasNameDisallowedForLetDeclarations(variable) {
199
199
  module.exports = {
200
200
  meta: {
201
201
  type: "suggestion",
202
+ dialects: ["typescript", "javascript"],
203
+ language: "javascript",
202
204
 
203
205
  docs: {
204
206
  description: "Require `let` or `const` instead of `var`",
@@ -346,9 +348,19 @@ module.exports = {
346
348
 
347
349
  return {
348
350
  "VariableDeclaration:exit"(node) {
349
- if (node.kind === "var") {
350
- report(node);
351
+ if (node.kind !== "var") {
352
+ return;
351
353
  }
354
+
355
+ if (
356
+ node.parent.type === "TSModuleBlock" &&
357
+ node.parent.parent.type === "TSModuleDeclaration" &&
358
+ node.parent.parent.global
359
+ ) {
360
+ return;
361
+ }
362
+
363
+ report(node);
352
364
  },
353
365
  };
354
366
  },