@saasmakers/eslint 0.2.6 → 0.2.7

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 (65) hide show
  1. package/dist/chunks/formatters.cjs +248 -0
  2. package/dist/chunks/formatters.mjs +246 -0
  3. package/dist/chunks/import.cjs +53 -0
  4. package/dist/chunks/import.mjs +51 -0
  5. package/dist/chunks/index.cjs +120 -0
  6. package/dist/chunks/index.mjs +101 -0
  7. package/dist/chunks/index2.cjs +880 -0
  8. package/dist/chunks/index2.mjs +868 -0
  9. package/dist/chunks/index3.cjs +982 -0
  10. package/dist/chunks/index3.mjs +979 -0
  11. package/dist/chunks/index4.cjs +12099 -0
  12. package/dist/chunks/index4.mjs +12077 -0
  13. package/dist/chunks/jsdoc.cjs +38398 -0
  14. package/dist/chunks/jsdoc.mjs +38391 -0
  15. package/dist/chunks/regexp.cjs +18518 -0
  16. package/dist/chunks/regexp.mjs +18511 -0
  17. package/dist/chunks/stylistic.cjs +23935 -0
  18. package/dist/chunks/stylistic.mjs +23932 -0
  19. package/dist/chunks/typescript.cjs +56168 -0
  20. package/dist/chunks/typescript.mjs +56154 -0
  21. package/dist/chunks/unicorn.cjs +82775 -0
  22. package/dist/chunks/unicorn.mjs +82764 -0
  23. package/dist/chunks/vue.cjs +96233 -0
  24. package/dist/chunks/vue.mjs +96220 -0
  25. package/dist/eslint.config.cjs +19 -10875
  26. package/dist/eslint.config.d.cts +3897 -16
  27. package/dist/eslint.config.d.mts +3897 -16
  28. package/dist/eslint.config.d.ts +3897 -16
  29. package/dist/eslint.config.mjs +18 -10853
  30. package/dist/index.cjs +1 -1
  31. package/dist/index.d.cts +6 -2
  32. package/dist/index.d.mts +6 -2
  33. package/dist/index.d.ts +6 -2
  34. package/dist/index.mjs +1 -1
  35. package/dist/shared/eslint.05nu4VbT.mjs +9 -0
  36. package/dist/shared/eslint.07qTxm9w.mjs +3352 -0
  37. package/dist/shared/eslint.6MAvpL4q.cjs +2141 -0
  38. package/dist/shared/{eslint.CohBuu1-.mjs → eslint.B3ywQ3NK.mjs} +157 -331
  39. package/dist/shared/eslint.BGpVg2tt.cjs +13 -0
  40. package/dist/shared/eslint.BL4sYiVQ.cjs +820 -0
  41. package/dist/shared/eslint.BOOP2x9L.cjs +67 -0
  42. package/dist/shared/eslint.Bf7aat-e.mjs +10 -0
  43. package/dist/shared/eslint.Bh1W2iVQ.cjs +37181 -0
  44. package/dist/shared/eslint.Bl69eiyD.cjs +7073 -0
  45. package/dist/shared/eslint.BtkqW7nC.mjs +818 -0
  46. package/dist/shared/eslint.C12_M0Cw.cjs +9 -0
  47. package/dist/shared/eslint.CMfxPSSy.cjs +14 -0
  48. package/dist/shared/eslint.COweQ1RR.mjs +5 -0
  49. package/dist/shared/eslint.CUi9znUC.mjs +13 -0
  50. package/dist/shared/eslint.Cg6Ty7p7.mjs +2699 -0
  51. package/dist/shared/eslint.CxAZpd0w.cjs +3365 -0
  52. package/dist/shared/eslint.CyJA7jO6.cjs +3813 -0
  53. package/dist/shared/eslint.DDD2xc4l.cjs +25 -0
  54. package/dist/shared/eslint.DI7QBrVD.mjs +6 -0
  55. package/dist/shared/eslint.DUamuDzp.cjs +7 -0
  56. package/dist/shared/eslint.DV_fpPxQ.mjs +3805 -0
  57. package/dist/shared/{eslint.DhFjwkxh.cjs → eslint.Dhg0jKDi.cjs} +167 -330
  58. package/dist/shared/eslint.Difk5awg.mjs +2139 -0
  59. package/dist/shared/eslint.Dlgr3LGM.mjs +7070 -0
  60. package/dist/shared/eslint.DoYGbUIG.cjs +2724 -0
  61. package/dist/shared/eslint.Dprsk9zl.mjs +65 -0
  62. package/dist/shared/eslint.DuJbNenz.mjs +37140 -0
  63. package/dist/shared/eslint.MfgVmFE7.cjs +3054 -0
  64. package/dist/shared/eslint.W7RM7aEw.mjs +3052 -0
  65. package/package.json +2 -1
@@ -0,0 +1,2724 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * @typedef {{ readonly [type: string]: ReadonlyArray<string> }} VisitorKeys
5
+ */
6
+
7
+ /**
8
+ * @type {VisitorKeys}
9
+ */
10
+ const KEYS = {
11
+ ArrayExpression: [
12
+ "elements"
13
+ ],
14
+ ArrayPattern: [
15
+ "elements"
16
+ ],
17
+ ArrowFunctionExpression: [
18
+ "params",
19
+ "body"
20
+ ],
21
+ AssignmentExpression: [
22
+ "left",
23
+ "right"
24
+ ],
25
+ AssignmentPattern: [
26
+ "left",
27
+ "right"
28
+ ],
29
+ AwaitExpression: [
30
+ "argument"
31
+ ],
32
+ BinaryExpression: [
33
+ "left",
34
+ "right"
35
+ ],
36
+ BlockStatement: [
37
+ "body"
38
+ ],
39
+ BreakStatement: [
40
+ "label"
41
+ ],
42
+ CallExpression: [
43
+ "callee",
44
+ "arguments"
45
+ ],
46
+ CatchClause: [
47
+ "param",
48
+ "body"
49
+ ],
50
+ ChainExpression: [
51
+ "expression"
52
+ ],
53
+ ClassBody: [
54
+ "body"
55
+ ],
56
+ ClassDeclaration: [
57
+ "id",
58
+ "superClass",
59
+ "body"
60
+ ],
61
+ ClassExpression: [
62
+ "id",
63
+ "superClass",
64
+ "body"
65
+ ],
66
+ ConditionalExpression: [
67
+ "test",
68
+ "consequent",
69
+ "alternate"
70
+ ],
71
+ ContinueStatement: [
72
+ "label"
73
+ ],
74
+ DebuggerStatement: [],
75
+ DoWhileStatement: [
76
+ "body",
77
+ "test"
78
+ ],
79
+ EmptyStatement: [],
80
+ ExperimentalRestProperty: [
81
+ "argument"
82
+ ],
83
+ ExperimentalSpreadProperty: [
84
+ "argument"
85
+ ],
86
+ ExportAllDeclaration: [
87
+ "exported",
88
+ "source"
89
+ ],
90
+ ExportDefaultDeclaration: [
91
+ "declaration"
92
+ ],
93
+ ExportNamedDeclaration: [
94
+ "declaration",
95
+ "specifiers",
96
+ "source"
97
+ ],
98
+ ExportSpecifier: [
99
+ "exported",
100
+ "local"
101
+ ],
102
+ ExpressionStatement: [
103
+ "expression"
104
+ ],
105
+ ForInStatement: [
106
+ "left",
107
+ "right",
108
+ "body"
109
+ ],
110
+ ForOfStatement: [
111
+ "left",
112
+ "right",
113
+ "body"
114
+ ],
115
+ ForStatement: [
116
+ "init",
117
+ "test",
118
+ "update",
119
+ "body"
120
+ ],
121
+ FunctionDeclaration: [
122
+ "id",
123
+ "params",
124
+ "body"
125
+ ],
126
+ FunctionExpression: [
127
+ "id",
128
+ "params",
129
+ "body"
130
+ ],
131
+ Identifier: [],
132
+ IfStatement: [
133
+ "test",
134
+ "consequent",
135
+ "alternate"
136
+ ],
137
+ ImportDeclaration: [
138
+ "specifiers",
139
+ "source"
140
+ ],
141
+ ImportDefaultSpecifier: [
142
+ "local"
143
+ ],
144
+ ImportExpression: [
145
+ "source"
146
+ ],
147
+ ImportNamespaceSpecifier: [
148
+ "local"
149
+ ],
150
+ ImportSpecifier: [
151
+ "imported",
152
+ "local"
153
+ ],
154
+ JSXAttribute: [
155
+ "name",
156
+ "value"
157
+ ],
158
+ JSXClosingElement: [
159
+ "name"
160
+ ],
161
+ JSXClosingFragment: [],
162
+ JSXElement: [
163
+ "openingElement",
164
+ "children",
165
+ "closingElement"
166
+ ],
167
+ JSXEmptyExpression: [],
168
+ JSXExpressionContainer: [
169
+ "expression"
170
+ ],
171
+ JSXFragment: [
172
+ "openingFragment",
173
+ "children",
174
+ "closingFragment"
175
+ ],
176
+ JSXIdentifier: [],
177
+ JSXMemberExpression: [
178
+ "object",
179
+ "property"
180
+ ],
181
+ JSXNamespacedName: [
182
+ "namespace",
183
+ "name"
184
+ ],
185
+ JSXOpeningElement: [
186
+ "name",
187
+ "attributes"
188
+ ],
189
+ JSXOpeningFragment: [],
190
+ JSXSpreadAttribute: [
191
+ "argument"
192
+ ],
193
+ JSXSpreadChild: [
194
+ "expression"
195
+ ],
196
+ JSXText: [],
197
+ LabeledStatement: [
198
+ "label",
199
+ "body"
200
+ ],
201
+ Literal: [],
202
+ LogicalExpression: [
203
+ "left",
204
+ "right"
205
+ ],
206
+ MemberExpression: [
207
+ "object",
208
+ "property"
209
+ ],
210
+ MetaProperty: [
211
+ "meta",
212
+ "property"
213
+ ],
214
+ MethodDefinition: [
215
+ "key",
216
+ "value"
217
+ ],
218
+ NewExpression: [
219
+ "callee",
220
+ "arguments"
221
+ ],
222
+ ObjectExpression: [
223
+ "properties"
224
+ ],
225
+ ObjectPattern: [
226
+ "properties"
227
+ ],
228
+ PrivateIdentifier: [],
229
+ Program: [
230
+ "body"
231
+ ],
232
+ Property: [
233
+ "key",
234
+ "value"
235
+ ],
236
+ PropertyDefinition: [
237
+ "key",
238
+ "value"
239
+ ],
240
+ RestElement: [
241
+ "argument"
242
+ ],
243
+ ReturnStatement: [
244
+ "argument"
245
+ ],
246
+ SequenceExpression: [
247
+ "expressions"
248
+ ],
249
+ SpreadElement: [
250
+ "argument"
251
+ ],
252
+ StaticBlock: [
253
+ "body"
254
+ ],
255
+ Super: [],
256
+ SwitchCase: [
257
+ "test",
258
+ "consequent"
259
+ ],
260
+ SwitchStatement: [
261
+ "discriminant",
262
+ "cases"
263
+ ],
264
+ TaggedTemplateExpression: [
265
+ "tag",
266
+ "quasi"
267
+ ],
268
+ TemplateElement: [],
269
+ TemplateLiteral: [
270
+ "quasis",
271
+ "expressions"
272
+ ],
273
+ ThisExpression: [],
274
+ ThrowStatement: [
275
+ "argument"
276
+ ],
277
+ TryStatement: [
278
+ "block",
279
+ "handler",
280
+ "finalizer"
281
+ ],
282
+ UnaryExpression: [
283
+ "argument"
284
+ ],
285
+ UpdateExpression: [
286
+ "argument"
287
+ ],
288
+ VariableDeclaration: [
289
+ "declarations"
290
+ ],
291
+ VariableDeclarator: [
292
+ "id",
293
+ "init"
294
+ ],
295
+ WhileStatement: [
296
+ "test",
297
+ "body"
298
+ ],
299
+ WithStatement: [
300
+ "object",
301
+ "body"
302
+ ],
303
+ YieldExpression: [
304
+ "argument"
305
+ ]
306
+ };
307
+
308
+ // Types.
309
+ const NODE_TYPES = Object.keys(KEYS);
310
+
311
+ // Freeze the keys.
312
+ for (const type of NODE_TYPES) {
313
+ Object.freeze(KEYS[type]);
314
+ }
315
+ Object.freeze(KEYS);
316
+
317
+ /**
318
+ * @author Toru Nagashima <https://github.com/mysticatea>
319
+ * See LICENSE file in root directory for full license.
320
+ */
321
+
322
+ /**
323
+ * @typedef {import('./visitor-keys.js').VisitorKeys} VisitorKeys
324
+ */
325
+
326
+ // List to ignore keys.
327
+ const KEY_BLACKLIST = new Set([
328
+ "parent",
329
+ "leadingComments",
330
+ "trailingComments"
331
+ ]);
332
+
333
+ /**
334
+ * Check whether a given key should be used or not.
335
+ * @param {string} key The key to check.
336
+ * @returns {boolean} `true` if the key should be used.
337
+ */
338
+ function filterKey(key) {
339
+ return !KEY_BLACKLIST.has(key) && key[0] !== "_";
340
+ }
341
+
342
+ /**
343
+ * Get visitor keys of a given node.
344
+ * @param {object} node The AST node to get keys.
345
+ * @returns {readonly string[]} Visitor keys of the node.
346
+ */
347
+ function getKeys(node) {
348
+ return Object.keys(node).filter(filterKey);
349
+ }
350
+
351
+ /** @typedef {import("eslint").Scope.Scope} Scope */
352
+ /** @typedef {import("estree").Node} Node */
353
+
354
+ /**
355
+ * Get the innermost scope which contains a given location.
356
+ * @param {Scope} initialScope The initial scope to search.
357
+ * @param {Node} node The location to search.
358
+ * @returns {Scope} The innermost scope.
359
+ */
360
+ function getInnermostScope(initialScope, node) {
361
+ const location = /** @type {[number, number]} */ (node.range)[0];
362
+
363
+ let scope = initialScope;
364
+ let found = false;
365
+ do {
366
+ found = false;
367
+ for (const childScope of scope.childScopes) {
368
+ const range = /** @type {[number, number]} */ (
369
+ childScope.block.range
370
+ );
371
+
372
+ if (range[0] <= location && location < range[1]) {
373
+ scope = childScope;
374
+ found = true;
375
+ break
376
+ }
377
+ }
378
+ } while (found)
379
+
380
+ return scope
381
+ }
382
+
383
+ /** @typedef {import("eslint").Scope.Scope} Scope */
384
+ /** @typedef {import("eslint").Scope.Variable} Variable */
385
+ /** @typedef {import("estree").Identifier} Identifier */
386
+
387
+ /**
388
+ * Find the variable of a given name.
389
+ * @param {Scope} initialScope The scope to start finding.
390
+ * @param {string|Identifier} nameOrNode The variable name to find. If this is a Node object then it should be an Identifier node.
391
+ * @returns {Variable|null} The found variable or null.
392
+ */
393
+ function findVariable(initialScope, nameOrNode) {
394
+ let name = "";
395
+ /** @type {Scope|null} */
396
+ let scope = initialScope;
397
+
398
+ if (typeof nameOrNode === "string") {
399
+ name = nameOrNode;
400
+ } else {
401
+ name = nameOrNode.name;
402
+ scope = getInnermostScope(scope, nameOrNode);
403
+ }
404
+
405
+ while (scope != null) {
406
+ const variable = scope.set.get(name);
407
+ if (variable != null) {
408
+ return variable
409
+ }
410
+ scope = scope.upper;
411
+ }
412
+
413
+ return null
414
+ }
415
+
416
+ /** @typedef {import("eslint").AST.Token} Token */
417
+ /** @typedef {import("estree").Comment} Comment */
418
+ /** @typedef {import("./types.mjs").ArrowToken} ArrowToken */
419
+ /** @typedef {import("./types.mjs").CommaToken} CommaToken */
420
+ /** @typedef {import("./types.mjs").SemicolonToken} SemicolonToken */
421
+ /** @typedef {import("./types.mjs").ColonToken} ColonToken */
422
+ /** @typedef {import("./types.mjs").OpeningParenToken} OpeningParenToken */
423
+ /** @typedef {import("./types.mjs").ClosingParenToken} ClosingParenToken */
424
+ /** @typedef {import("./types.mjs").OpeningBracketToken} OpeningBracketToken */
425
+ /** @typedef {import("./types.mjs").ClosingBracketToken} ClosingBracketToken */
426
+ /** @typedef {import("./types.mjs").OpeningBraceToken} OpeningBraceToken */
427
+ /** @typedef {import("./types.mjs").ClosingBraceToken} ClosingBraceToken */
428
+ /**
429
+ * @template {string} Value
430
+ * @typedef {import("./types.mjs").PunctuatorToken<Value>} PunctuatorToken
431
+ */
432
+
433
+ /** @typedef {Comment | Token} CommentOrToken */
434
+
435
+ /**
436
+ * Creates the negate function of the given function.
437
+ * @param {function(CommentOrToken):boolean} f - The function to negate.
438
+ * @returns {function(CommentOrToken):boolean} Negated function.
439
+ */
440
+ function negate(f) {
441
+ return (token) => !f(token)
442
+ }
443
+
444
+ /**
445
+ * Checks if the given token is a PunctuatorToken with the given value
446
+ * @template {string} Value
447
+ * @param {CommentOrToken} token - The token to check.
448
+ * @param {Value} value - The value to check.
449
+ * @returns {token is PunctuatorToken<Value>} `true` if the token is a PunctuatorToken with the given value.
450
+ */
451
+ function isPunctuatorTokenWithValue(token, value) {
452
+ return token.type === "Punctuator" && token.value === value
453
+ }
454
+
455
+ /**
456
+ * Checks if the given token is an arrow token or not.
457
+ * @param {CommentOrToken} token - The token to check.
458
+ * @returns {token is ArrowToken} `true` if the token is an arrow token.
459
+ */
460
+ function isArrowToken(token) {
461
+ return isPunctuatorTokenWithValue(token, "=>")
462
+ }
463
+
464
+ /**
465
+ * Checks if the given token is a comma token or not.
466
+ * @param {CommentOrToken} token - The token to check.
467
+ * @returns {token is CommaToken} `true` if the token is a comma token.
468
+ */
469
+ function isCommaToken(token) {
470
+ return isPunctuatorTokenWithValue(token, ",")
471
+ }
472
+
473
+ /**
474
+ * Checks if the given token is a semicolon token or not.
475
+ * @param {CommentOrToken} token - The token to check.
476
+ * @returns {token is SemicolonToken} `true` if the token is a semicolon token.
477
+ */
478
+ function isSemicolonToken(token) {
479
+ return isPunctuatorTokenWithValue(token, ";")
480
+ }
481
+
482
+ /**
483
+ * Checks if the given token is a colon token or not.
484
+ * @param {CommentOrToken} token - The token to check.
485
+ * @returns {token is ColonToken} `true` if the token is a colon token.
486
+ */
487
+ function isColonToken(token) {
488
+ return isPunctuatorTokenWithValue(token, ":")
489
+ }
490
+
491
+ /**
492
+ * Checks if the given token is an opening parenthesis token or not.
493
+ * @param {CommentOrToken} token - The token to check.
494
+ * @returns {token is OpeningParenToken} `true` if the token is an opening parenthesis token.
495
+ */
496
+ function isOpeningParenToken(token) {
497
+ return isPunctuatorTokenWithValue(token, "(")
498
+ }
499
+
500
+ /**
501
+ * Checks if the given token is a closing parenthesis token or not.
502
+ * @param {CommentOrToken} token - The token to check.
503
+ * @returns {token is ClosingParenToken} `true` if the token is a closing parenthesis token.
504
+ */
505
+ function isClosingParenToken(token) {
506
+ return isPunctuatorTokenWithValue(token, ")")
507
+ }
508
+
509
+ /**
510
+ * Checks if the given token is an opening square bracket token or not.
511
+ * @param {CommentOrToken} token - The token to check.
512
+ * @returns {token is OpeningBracketToken} `true` if the token is an opening square bracket token.
513
+ */
514
+ function isOpeningBracketToken(token) {
515
+ return isPunctuatorTokenWithValue(token, "[")
516
+ }
517
+
518
+ /**
519
+ * Checks if the given token is a closing square bracket token or not.
520
+ * @param {CommentOrToken} token - The token to check.
521
+ * @returns {token is ClosingBracketToken} `true` if the token is a closing square bracket token.
522
+ */
523
+ function isClosingBracketToken(token) {
524
+ return isPunctuatorTokenWithValue(token, "]")
525
+ }
526
+
527
+ /**
528
+ * Checks if the given token is an opening brace token or not.
529
+ * @param {CommentOrToken} token - The token to check.
530
+ * @returns {token is OpeningBraceToken} `true` if the token is an opening brace token.
531
+ */
532
+ function isOpeningBraceToken(token) {
533
+ return isPunctuatorTokenWithValue(token, "{")
534
+ }
535
+
536
+ /**
537
+ * Checks if the given token is a closing brace token or not.
538
+ * @param {CommentOrToken} token - The token to check.
539
+ * @returns {token is ClosingBraceToken} `true` if the token is a closing brace token.
540
+ */
541
+ function isClosingBraceToken(token) {
542
+ return isPunctuatorTokenWithValue(token, "}")
543
+ }
544
+
545
+ /**
546
+ * Checks if the given token is a comment token or not.
547
+ * @param {CommentOrToken} token - The token to check.
548
+ * @returns {token is Comment} `true` if the token is a comment token.
549
+ */
550
+ function isCommentToken(token) {
551
+ return ["Block", "Line", "Shebang"].includes(token.type)
552
+ }
553
+ const isNotSemicolonToken = negate(isSemicolonToken);
554
+
555
+ /** @typedef {import("eslint").Rule.Node} RuleNode */
556
+ /** @typedef {import("eslint").SourceCode} SourceCode */
557
+ /** @typedef {import("eslint").AST.Token} Token */
558
+ /** @typedef {import("estree").Function} FunctionNode */
559
+ /** @typedef {import("estree").FunctionDeclaration} FunctionDeclaration */
560
+ /** @typedef {import("estree").FunctionExpression} FunctionExpression */
561
+ /** @typedef {import("estree").SourceLocation} SourceLocation */
562
+ /** @typedef {import("estree").Position} Position */
563
+
564
+ /**
565
+ * Get the `(` token of the given function node.
566
+ * @param {FunctionExpression | FunctionDeclaration} node - The function node to get.
567
+ * @param {SourceCode} sourceCode - The source code object to get tokens.
568
+ * @returns {Token} `(` token.
569
+ */
570
+ function getOpeningParenOfParams(node, sourceCode) {
571
+ return node.id
572
+ ? /** @type {Token} */ (
573
+ sourceCode.getTokenAfter(node.id, isOpeningParenToken)
574
+ )
575
+ : /** @type {Token} */ (
576
+ sourceCode.getFirstToken(node, isOpeningParenToken)
577
+ )
578
+ }
579
+
580
+ /**
581
+ * Get the location of the given function node for reporting.
582
+ * @param {FunctionNode} node - The function node to get.
583
+ * @param {SourceCode} sourceCode - The source code object to get tokens.
584
+ * @returns {SourceLocation|null} The location of the function node for reporting.
585
+ */
586
+ function getFunctionHeadLocation(node, sourceCode) {
587
+ const parent = /** @type {RuleNode} */ (node).parent;
588
+
589
+ /** @type {Position|null} */
590
+ let start = null;
591
+ /** @type {Position|null} */
592
+ let end = null;
593
+
594
+ if (node.type === "ArrowFunctionExpression") {
595
+ const arrowToken = /** @type {Token} */ (
596
+ sourceCode.getTokenBefore(node.body, isArrowToken)
597
+ );
598
+
599
+ start = arrowToken.loc.start;
600
+ end = arrowToken.loc.end;
601
+ } else if (
602
+ parent &&
603
+ (parent.type === "Property" ||
604
+ parent.type === "MethodDefinition" ||
605
+ parent.type === "PropertyDefinition")
606
+ ) {
607
+ start = /** @type {SourceLocation} */ (parent.loc).start;
608
+ end = getOpeningParenOfParams(node, sourceCode).loc.start;
609
+ } else {
610
+ start = /** @type {SourceLocation} */ (node.loc).start;
611
+ end = getOpeningParenOfParams(node, sourceCode).loc.start;
612
+ }
613
+
614
+ return {
615
+ start: { ...start },
616
+ end: { ...end },
617
+ }
618
+ }
619
+
620
+ /* globals globalThis, global, self, window */
621
+ /** @typedef {import("./types.mjs").StaticValue} StaticValue */
622
+ /** @typedef {import("eslint").Scope.Scope} Scope */
623
+ /** @typedef {import("eslint").Scope.Variable} Variable */
624
+ /** @typedef {import("estree").Node} Node */
625
+ /** @typedef {import("@typescript-eslint/types").TSESTree.Node} TSESTreeNode */
626
+ /** @typedef {import("@typescript-eslint/types").TSESTree.AST_NODE_TYPES} TSESTreeNodeTypes */
627
+ /** @typedef {import("@typescript-eslint/types").TSESTree.MemberExpression} MemberExpression */
628
+ /** @typedef {import("@typescript-eslint/types").TSESTree.Property} Property */
629
+ /** @typedef {import("@typescript-eslint/types").TSESTree.RegExpLiteral} RegExpLiteral */
630
+ /** @typedef {import("@typescript-eslint/types").TSESTree.BigIntLiteral} BigIntLiteral */
631
+ /** @typedef {import("@typescript-eslint/types").TSESTree.Literal} Literal */
632
+
633
+ const globalObject =
634
+ typeof globalThis !== "undefined"
635
+ ? globalThis
636
+ : // @ts-ignore
637
+ typeof self !== "undefined"
638
+ ? // @ts-ignore
639
+ self
640
+ : // @ts-ignore
641
+ typeof window !== "undefined"
642
+ ? // @ts-ignore
643
+ window
644
+ : typeof global !== "undefined"
645
+ ? global
646
+ : {};
647
+
648
+ const builtinNames = Object.freeze(
649
+ new Set([
650
+ "Array",
651
+ "ArrayBuffer",
652
+ "BigInt",
653
+ "BigInt64Array",
654
+ "BigUint64Array",
655
+ "Boolean",
656
+ "DataView",
657
+ "Date",
658
+ "decodeURI",
659
+ "decodeURIComponent",
660
+ "encodeURI",
661
+ "encodeURIComponent",
662
+ "escape",
663
+ "Float32Array",
664
+ "Float64Array",
665
+ "Function",
666
+ "Infinity",
667
+ "Int16Array",
668
+ "Int32Array",
669
+ "Int8Array",
670
+ "isFinite",
671
+ "isNaN",
672
+ "isPrototypeOf",
673
+ "JSON",
674
+ "Map",
675
+ "Math",
676
+ "NaN",
677
+ "Number",
678
+ "Object",
679
+ "parseFloat",
680
+ "parseInt",
681
+ "Promise",
682
+ "Proxy",
683
+ "Reflect",
684
+ "RegExp",
685
+ "Set",
686
+ "String",
687
+ "Symbol",
688
+ "Uint16Array",
689
+ "Uint32Array",
690
+ "Uint8Array",
691
+ "Uint8ClampedArray",
692
+ "undefined",
693
+ "unescape",
694
+ "WeakMap",
695
+ "WeakSet",
696
+ ]),
697
+ );
698
+ const callAllowed = new Set(
699
+ [
700
+ Array.isArray,
701
+ Array.of,
702
+ Array.prototype.at,
703
+ Array.prototype.concat,
704
+ Array.prototype.entries,
705
+ Array.prototype.every,
706
+ Array.prototype.filter,
707
+ Array.prototype.find,
708
+ Array.prototype.findIndex,
709
+ Array.prototype.flat,
710
+ Array.prototype.includes,
711
+ Array.prototype.indexOf,
712
+ Array.prototype.join,
713
+ Array.prototype.keys,
714
+ Array.prototype.lastIndexOf,
715
+ Array.prototype.slice,
716
+ Array.prototype.some,
717
+ Array.prototype.toString,
718
+ Array.prototype.values,
719
+ typeof BigInt === "function" ? BigInt : undefined,
720
+ Boolean,
721
+ Date,
722
+ Date.parse,
723
+ decodeURI,
724
+ decodeURIComponent,
725
+ encodeURI,
726
+ encodeURIComponent,
727
+ escape,
728
+ isFinite,
729
+ isNaN,
730
+ // @ts-ignore
731
+ isPrototypeOf,
732
+ Map,
733
+ Map.prototype.entries,
734
+ Map.prototype.get,
735
+ Map.prototype.has,
736
+ Map.prototype.keys,
737
+ Map.prototype.values,
738
+ .../** @type {(keyof typeof Math)[]} */ (
739
+ Object.getOwnPropertyNames(Math)
740
+ )
741
+ .filter((k) => k !== "random")
742
+ .map((k) => Math[k])
743
+ .filter((f) => typeof f === "function"),
744
+ Number,
745
+ Number.isFinite,
746
+ Number.isNaN,
747
+ Number.parseFloat,
748
+ Number.parseInt,
749
+ Number.prototype.toExponential,
750
+ Number.prototype.toFixed,
751
+ Number.prototype.toPrecision,
752
+ Number.prototype.toString,
753
+ Object,
754
+ Object.entries,
755
+ Object.is,
756
+ Object.isExtensible,
757
+ Object.isFrozen,
758
+ Object.isSealed,
759
+ Object.keys,
760
+ Object.values,
761
+ parseFloat,
762
+ parseInt,
763
+ RegExp,
764
+ Set,
765
+ Set.prototype.entries,
766
+ Set.prototype.has,
767
+ Set.prototype.keys,
768
+ Set.prototype.values,
769
+ String,
770
+ String.fromCharCode,
771
+ String.fromCodePoint,
772
+ String.raw,
773
+ String.prototype.at,
774
+ String.prototype.charAt,
775
+ String.prototype.charCodeAt,
776
+ String.prototype.codePointAt,
777
+ String.prototype.concat,
778
+ String.prototype.endsWith,
779
+ String.prototype.includes,
780
+ String.prototype.indexOf,
781
+ String.prototype.lastIndexOf,
782
+ String.prototype.normalize,
783
+ String.prototype.padEnd,
784
+ String.prototype.padStart,
785
+ String.prototype.slice,
786
+ String.prototype.startsWith,
787
+ String.prototype.substr,
788
+ String.prototype.substring,
789
+ String.prototype.toLowerCase,
790
+ String.prototype.toString,
791
+ String.prototype.toUpperCase,
792
+ String.prototype.trim,
793
+ String.prototype.trimEnd,
794
+ String.prototype.trimLeft,
795
+ String.prototype.trimRight,
796
+ String.prototype.trimStart,
797
+ Symbol.for,
798
+ Symbol.keyFor,
799
+ unescape,
800
+ ].filter((f) => typeof f === "function"),
801
+ );
802
+ const callPassThrough = new Set([
803
+ Object.freeze,
804
+ Object.preventExtensions,
805
+ Object.seal,
806
+ ]);
807
+
808
+ /** @type {ReadonlyArray<readonly [Function, ReadonlySet<string>]>} */
809
+ const getterAllowed = [
810
+ [Map, new Set(["size"])],
811
+ [
812
+ RegExp,
813
+ new Set([
814
+ "dotAll",
815
+ "flags",
816
+ "global",
817
+ "hasIndices",
818
+ "ignoreCase",
819
+ "multiline",
820
+ "source",
821
+ "sticky",
822
+ "unicode",
823
+ ]),
824
+ ],
825
+ [Set, new Set(["size"])],
826
+ ];
827
+
828
+ /**
829
+ * Get the property descriptor.
830
+ * @param {object} object The object to get.
831
+ * @param {string|number|symbol} name The property name to get.
832
+ */
833
+ function getPropertyDescriptor(object, name) {
834
+ let x = object;
835
+ while ((typeof x === "object" || typeof x === "function") && x !== null) {
836
+ const d = Object.getOwnPropertyDescriptor(x, name);
837
+ if (d) {
838
+ return d
839
+ }
840
+ x = Object.getPrototypeOf(x);
841
+ }
842
+ return null
843
+ }
844
+
845
+ /**
846
+ * Check if a property is getter or not.
847
+ * @param {object} object The object to check.
848
+ * @param {string|number|symbol} name The property name to check.
849
+ */
850
+ function isGetter(object, name) {
851
+ const d = getPropertyDescriptor(object, name);
852
+ return d != null && d.get != null
853
+ }
854
+
855
+ /**
856
+ * Get the element values of a given node list.
857
+ * @param {(Node|TSESTreeNode|null)[]} nodeList The node list to get values.
858
+ * @param {Scope|undefined|null} initialScope The initial scope to find variables.
859
+ * @returns {any[]|null} The value list if all nodes are constant. Otherwise, null.
860
+ */
861
+ function getElementValues(nodeList, initialScope) {
862
+ const valueList = [];
863
+
864
+ for (let i = 0; i < nodeList.length; ++i) {
865
+ const elementNode = nodeList[i];
866
+
867
+ if (elementNode == null) {
868
+ valueList.length = i + 1;
869
+ } else if (elementNode.type === "SpreadElement") {
870
+ const argument = getStaticValueR(elementNode.argument, initialScope);
871
+ if (argument == null) {
872
+ return null
873
+ }
874
+ valueList.push(.../** @type {Iterable<any>} */ (argument.value));
875
+ } else {
876
+ const element = getStaticValueR(elementNode, initialScope);
877
+ if (element == null) {
878
+ return null
879
+ }
880
+ valueList.push(element.value);
881
+ }
882
+ }
883
+
884
+ return valueList
885
+ }
886
+
887
+ /**
888
+ * Checks if a variable is a built-in global.
889
+ * @param {Variable|null} variable The variable to check.
890
+ * @returns {variable is Variable & {defs:[]}}
891
+ */
892
+ function isBuiltinGlobal(variable) {
893
+ return (
894
+ variable != null &&
895
+ variable.defs.length === 0 &&
896
+ builtinNames.has(variable.name) &&
897
+ variable.name in globalObject
898
+ )
899
+ }
900
+
901
+ /**
902
+ * Checks if a variable can be considered as a constant.
903
+ * @param {Variable} variable
904
+ * @returns {variable is Variable & {defs: [import("eslint").Scope.Definition & { type: "Variable" }]}} True if the variable can be considered as a constant.
905
+ */
906
+ function canBeConsideredConst(variable) {
907
+ if (variable.defs.length !== 1) {
908
+ return false
909
+ }
910
+ const def = variable.defs[0];
911
+ return Boolean(
912
+ def.parent &&
913
+ def.type === "Variable" &&
914
+ (def.parent.kind === "const" || isEffectivelyConst(variable)),
915
+ )
916
+ }
917
+
918
+ /**
919
+ * Returns whether the given variable is never written to after initialization.
920
+ * @param {Variable} variable
921
+ * @returns {boolean}
922
+ */
923
+ function isEffectivelyConst(variable) {
924
+ const refs = variable.references;
925
+
926
+ const inits = refs.filter((r) => r.init).length;
927
+ const reads = refs.filter((r) => r.isReadOnly()).length;
928
+ if (inits === 1 && reads + inits === refs.length) {
929
+ // there is only one init and all other references only read
930
+ return true
931
+ }
932
+ return false
933
+ }
934
+
935
+ /**
936
+ * Checks if a variable has mutation in its property.
937
+ * @param {Variable} variable The variable to check.
938
+ * @param {Scope|null} initialScope The scope to start finding variable. Optional. If the node is a computed property node and this scope was given, this checks the computed property name by the `getStringIfConstant` function with the scope, and returns the value of it.
939
+ * @returns {boolean} True if the variable has mutation in its property.
940
+ */
941
+ function hasMutationInProperty(variable, initialScope) {
942
+ for (const ref of variable.references) {
943
+ let node = /** @type {TSESTreeNode} */ (ref.identifier);
944
+ while (node && node.parent && node.parent.type === "MemberExpression") {
945
+ node = node.parent;
946
+ }
947
+ if (!node || !node.parent) {
948
+ continue
949
+ }
950
+ if (
951
+ (node.parent.type === "AssignmentExpression" &&
952
+ node.parent.left === node) ||
953
+ (node.parent.type === "UpdateExpression" &&
954
+ node.parent.argument === node)
955
+ ) {
956
+ // This is a mutation.
957
+ return true
958
+ }
959
+ if (
960
+ node.parent.type === "CallExpression" &&
961
+ node.parent.callee === node &&
962
+ node.type === "MemberExpression"
963
+ ) {
964
+ const methodName = getStaticPropertyNameValue(node, initialScope);
965
+ if (isNameOfMutationArrayMethod(methodName)) {
966
+ // This is a mutation.
967
+ return true
968
+ }
969
+ }
970
+ }
971
+ return false
972
+
973
+ /**
974
+ * Checks if a method name is one of the mutation array methods.
975
+ * @param {StaticValue|null} methodName The method name to check.
976
+ * @returns {boolean} True if the method name is a mutation array method.
977
+ */
978
+ function isNameOfMutationArrayMethod(methodName) {
979
+ if (methodName == null || methodName.value == null) {
980
+ return false
981
+ }
982
+ const name = methodName.value;
983
+ return (
984
+ name === "copyWithin" ||
985
+ name === "fill" ||
986
+ name === "pop" ||
987
+ name === "push" ||
988
+ name === "reverse" ||
989
+ name === "shift" ||
990
+ name === "sort" ||
991
+ name === "splice" ||
992
+ name === "unshift"
993
+ )
994
+ }
995
+ }
996
+
997
+ /**
998
+ * @template {TSESTreeNodeTypes} T
999
+ * @callback VisitorCallback
1000
+ * @param {TSESTreeNode & { type: T }} node
1001
+ * @param {Scope|undefined|null} initialScope
1002
+ * @returns {StaticValue | null}
1003
+ */
1004
+ /**
1005
+ * @typedef { { [K in TSESTreeNodeTypes]?: VisitorCallback<K> } } Operations
1006
+ */
1007
+ /**
1008
+ * @type {Operations}
1009
+ */
1010
+ const operations = Object.freeze({
1011
+ ArrayExpression(node, initialScope) {
1012
+ const elements = getElementValues(node.elements, initialScope);
1013
+ return elements != null ? { value: elements } : null
1014
+ },
1015
+
1016
+ AssignmentExpression(node, initialScope) {
1017
+ if (node.operator === "=") {
1018
+ return getStaticValueR(node.right, initialScope)
1019
+ }
1020
+ return null
1021
+ },
1022
+
1023
+ //eslint-disable-next-line complexity
1024
+ BinaryExpression(node, initialScope) {
1025
+ if (node.operator === "in" || node.operator === "instanceof") {
1026
+ // Not supported.
1027
+ return null
1028
+ }
1029
+
1030
+ const left = getStaticValueR(node.left, initialScope);
1031
+ const right = getStaticValueR(node.right, initialScope);
1032
+ if (left != null && right != null) {
1033
+ switch (node.operator) {
1034
+ case "==":
1035
+ return { value: left.value == right.value } //eslint-disable-line eqeqeq
1036
+ case "!=":
1037
+ return { value: left.value != right.value } //eslint-disable-line eqeqeq
1038
+ case "===":
1039
+ return { value: left.value === right.value }
1040
+ case "!==":
1041
+ return { value: left.value !== right.value }
1042
+ case "<":
1043
+ return {
1044
+ value:
1045
+ /** @type {any} */ (left.value) <
1046
+ /** @type {any} */ (right.value),
1047
+ }
1048
+ case "<=":
1049
+ return {
1050
+ value:
1051
+ /** @type {any} */ (left.value) <=
1052
+ /** @type {any} */ (right.value),
1053
+ }
1054
+ case ">":
1055
+ return {
1056
+ value:
1057
+ /** @type {any} */ (left.value) >
1058
+ /** @type {any} */ (right.value),
1059
+ }
1060
+ case ">=":
1061
+ return {
1062
+ value:
1063
+ /** @type {any} */ (left.value) >=
1064
+ /** @type {any} */ (right.value),
1065
+ }
1066
+ case "<<":
1067
+ return {
1068
+ value:
1069
+ /** @type {any} */ (left.value) <<
1070
+ /** @type {any} */ (right.value),
1071
+ }
1072
+ case ">>":
1073
+ return {
1074
+ value:
1075
+ /** @type {any} */ (left.value) >>
1076
+ /** @type {any} */ (right.value),
1077
+ }
1078
+ case ">>>":
1079
+ return {
1080
+ value:
1081
+ /** @type {any} */ (left.value) >>>
1082
+ /** @type {any} */ (right.value),
1083
+ }
1084
+ case "+":
1085
+ return {
1086
+ value:
1087
+ /** @type {any} */ (left.value) +
1088
+ /** @type {any} */ (right.value),
1089
+ }
1090
+ case "-":
1091
+ return {
1092
+ value:
1093
+ /** @type {any} */ (left.value) -
1094
+ /** @type {any} */ (right.value),
1095
+ }
1096
+ case "*":
1097
+ return {
1098
+ value:
1099
+ /** @type {any} */ (left.value) *
1100
+ /** @type {any} */ (right.value),
1101
+ }
1102
+ case "/":
1103
+ return {
1104
+ value:
1105
+ /** @type {any} */ (left.value) /
1106
+ /** @type {any} */ (right.value),
1107
+ }
1108
+ case "%":
1109
+ return {
1110
+ value:
1111
+ /** @type {any} */ (left.value) %
1112
+ /** @type {any} */ (right.value),
1113
+ }
1114
+ case "**":
1115
+ return {
1116
+ value:
1117
+ /** @type {any} */ (left.value) **
1118
+ /** @type {any} */ (right.value),
1119
+ }
1120
+ case "|":
1121
+ return {
1122
+ value:
1123
+ /** @type {any} */ (left.value) |
1124
+ /** @type {any} */ (right.value),
1125
+ }
1126
+ case "^":
1127
+ return {
1128
+ value:
1129
+ /** @type {any} */ (left.value) ^
1130
+ /** @type {any} */ (right.value),
1131
+ }
1132
+ case "&":
1133
+ return {
1134
+ value:
1135
+ /** @type {any} */ (left.value) &
1136
+ /** @type {any} */ (right.value),
1137
+ }
1138
+
1139
+ // no default
1140
+ }
1141
+ }
1142
+
1143
+ return null
1144
+ },
1145
+
1146
+ CallExpression(node, initialScope) {
1147
+ const calleeNode = node.callee;
1148
+ const args = getElementValues(node.arguments, initialScope);
1149
+
1150
+ if (args != null) {
1151
+ if (calleeNode.type === "MemberExpression") {
1152
+ if (calleeNode.property.type === "PrivateIdentifier") {
1153
+ return null
1154
+ }
1155
+ const object = getStaticValueR(calleeNode.object, initialScope);
1156
+ if (object != null) {
1157
+ if (
1158
+ object.value == null &&
1159
+ (object.optional || node.optional)
1160
+ ) {
1161
+ return { value: undefined, optional: true }
1162
+ }
1163
+ const property = getStaticPropertyNameValue(
1164
+ calleeNode,
1165
+ initialScope,
1166
+ );
1167
+
1168
+ if (property != null) {
1169
+ const receiver =
1170
+ /** @type {Record<PropertyKey, (...args: any[]) => any>} */ (
1171
+ object.value
1172
+ );
1173
+ const methodName = /** @type {PropertyKey} */ (
1174
+ property.value
1175
+ );
1176
+ if (callAllowed.has(receiver[methodName])) {
1177
+ return {
1178
+ value: receiver[methodName](...args),
1179
+ }
1180
+ }
1181
+ if (callPassThrough.has(receiver[methodName])) {
1182
+ return { value: args[0] }
1183
+ }
1184
+ }
1185
+ }
1186
+ } else {
1187
+ const callee = getStaticValueR(calleeNode, initialScope);
1188
+ if (callee != null) {
1189
+ if (callee.value == null && node.optional) {
1190
+ return { value: undefined, optional: true }
1191
+ }
1192
+ const func = /** @type {(...args: any[]) => any} */ (
1193
+ callee.value
1194
+ );
1195
+ if (callAllowed.has(func)) {
1196
+ return { value: func(...args) }
1197
+ }
1198
+ if (callPassThrough.has(func)) {
1199
+ return { value: args[0] }
1200
+ }
1201
+ }
1202
+ }
1203
+ }
1204
+
1205
+ return null
1206
+ },
1207
+
1208
+ ConditionalExpression(node, initialScope) {
1209
+ const test = getStaticValueR(node.test, initialScope);
1210
+ if (test != null) {
1211
+ return test.value
1212
+ ? getStaticValueR(node.consequent, initialScope)
1213
+ : getStaticValueR(node.alternate, initialScope)
1214
+ }
1215
+ return null
1216
+ },
1217
+
1218
+ ExpressionStatement(node, initialScope) {
1219
+ return getStaticValueR(node.expression, initialScope)
1220
+ },
1221
+
1222
+ Identifier(node, initialScope) {
1223
+ if (initialScope != null) {
1224
+ const variable = findVariable(initialScope, node);
1225
+
1226
+ if (variable != null) {
1227
+ // Built-in globals.
1228
+ if (isBuiltinGlobal(variable)) {
1229
+ return { value: globalObject[variable.name] }
1230
+ }
1231
+
1232
+ // Constants.
1233
+ if (canBeConsideredConst(variable)) {
1234
+ const def = variable.defs[0];
1235
+ if (
1236
+ // TODO(mysticatea): don't support destructuring here.
1237
+ def.node.id.type === "Identifier"
1238
+ ) {
1239
+ const init = getStaticValueR(
1240
+ def.node.init,
1241
+ initialScope,
1242
+ );
1243
+ if (
1244
+ init &&
1245
+ typeof init.value === "object" &&
1246
+ init.value !== null
1247
+ ) {
1248
+ if (hasMutationInProperty(variable, initialScope)) {
1249
+ // This variable has mutation in its property.
1250
+ return null
1251
+ }
1252
+ }
1253
+ return init
1254
+ }
1255
+ }
1256
+ }
1257
+ }
1258
+ return null
1259
+ },
1260
+
1261
+ Literal(node) {
1262
+ const literal =
1263
+ /** @type {Partial<Literal> & Partial<RegExpLiteral> & Partial<BigIntLiteral>} */ (
1264
+ node
1265
+ );
1266
+ //istanbul ignore if : this is implementation-specific behavior.
1267
+ if (
1268
+ (literal.regex != null || literal.bigint != null) &&
1269
+ literal.value == null
1270
+ ) {
1271
+ // It was a RegExp/BigInt literal, but Node.js didn't support it.
1272
+ return null
1273
+ }
1274
+ return { value: literal.value }
1275
+ },
1276
+
1277
+ LogicalExpression(node, initialScope) {
1278
+ const left = getStaticValueR(node.left, initialScope);
1279
+ if (left != null) {
1280
+ if (
1281
+ (node.operator === "||" && Boolean(left.value) === true) ||
1282
+ (node.operator === "&&" && Boolean(left.value) === false) ||
1283
+ (node.operator === "??" && left.value != null)
1284
+ ) {
1285
+ return left
1286
+ }
1287
+
1288
+ const right = getStaticValueR(node.right, initialScope);
1289
+ if (right != null) {
1290
+ return right
1291
+ }
1292
+ }
1293
+
1294
+ return null
1295
+ },
1296
+
1297
+ MemberExpression(node, initialScope) {
1298
+ if (node.property.type === "PrivateIdentifier") {
1299
+ return null
1300
+ }
1301
+ const object = getStaticValueR(node.object, initialScope);
1302
+ if (object != null) {
1303
+ if (object.value == null && (object.optional || node.optional)) {
1304
+ return { value: undefined, optional: true }
1305
+ }
1306
+ const property = getStaticPropertyNameValue(node, initialScope);
1307
+
1308
+ if (property != null) {
1309
+ if (
1310
+ !isGetter(
1311
+ /** @type {object} */ (object.value),
1312
+ /** @type {PropertyKey} */ (property.value),
1313
+ )
1314
+ ) {
1315
+ return {
1316
+ value: /** @type {Record<PropertyKey, unknown>} */ (
1317
+ object.value
1318
+ )[/** @type {PropertyKey} */ (property.value)],
1319
+ }
1320
+ }
1321
+
1322
+ for (const [classFn, allowed] of getterAllowed) {
1323
+ if (
1324
+ object.value instanceof classFn &&
1325
+ allowed.has(/** @type {string} */ (property.value))
1326
+ ) {
1327
+ return {
1328
+ value: /** @type {Record<PropertyKey, unknown>} */ (
1329
+ object.value
1330
+ )[/** @type {PropertyKey} */ (property.value)],
1331
+ }
1332
+ }
1333
+ }
1334
+ }
1335
+ }
1336
+ return null
1337
+ },
1338
+
1339
+ ChainExpression(node, initialScope) {
1340
+ const expression = getStaticValueR(node.expression, initialScope);
1341
+ if (expression != null) {
1342
+ return { value: expression.value }
1343
+ }
1344
+ return null
1345
+ },
1346
+
1347
+ NewExpression(node, initialScope) {
1348
+ const callee = getStaticValueR(node.callee, initialScope);
1349
+ const args = getElementValues(node.arguments, initialScope);
1350
+
1351
+ if (callee != null && args != null) {
1352
+ const Func = /** @type {new (...args: any[]) => any} */ (
1353
+ callee.value
1354
+ );
1355
+ if (callAllowed.has(Func)) {
1356
+ return { value: new Func(...args) }
1357
+ }
1358
+ }
1359
+
1360
+ return null
1361
+ },
1362
+
1363
+ ObjectExpression(node, initialScope) {
1364
+ /** @type {Record<PropertyKey, unknown>} */
1365
+ const object = {};
1366
+
1367
+ for (const propertyNode of node.properties) {
1368
+ if (propertyNode.type === "Property") {
1369
+ if (propertyNode.kind !== "init") {
1370
+ return null
1371
+ }
1372
+ const key = getStaticPropertyNameValue(
1373
+ propertyNode,
1374
+ initialScope,
1375
+ );
1376
+ const value = getStaticValueR(propertyNode.value, initialScope);
1377
+ if (key == null || value == null) {
1378
+ return null
1379
+ }
1380
+ object[/** @type {PropertyKey} */ (key.value)] = value.value;
1381
+ } else if (
1382
+ propertyNode.type === "SpreadElement" ||
1383
+ // @ts-expect-error -- Backward compatibility
1384
+ propertyNode.type === "ExperimentalSpreadProperty"
1385
+ ) {
1386
+ const argument = getStaticValueR(
1387
+ propertyNode.argument,
1388
+ initialScope,
1389
+ );
1390
+ if (argument == null) {
1391
+ return null
1392
+ }
1393
+ Object.assign(object, argument.value);
1394
+ } else {
1395
+ return null
1396
+ }
1397
+ }
1398
+
1399
+ return { value: object }
1400
+ },
1401
+
1402
+ SequenceExpression(node, initialScope) {
1403
+ const last = node.expressions[node.expressions.length - 1];
1404
+ return getStaticValueR(last, initialScope)
1405
+ },
1406
+
1407
+ TaggedTemplateExpression(node, initialScope) {
1408
+ const tag = getStaticValueR(node.tag, initialScope);
1409
+ const expressions = getElementValues(
1410
+ node.quasi.expressions,
1411
+ initialScope,
1412
+ );
1413
+
1414
+ if (tag != null && expressions != null) {
1415
+ const func = /** @type {(...args: any[]) => any} */ (tag.value);
1416
+ /** @type {any[] & { raw?: string[] }} */
1417
+ const strings = node.quasi.quasis.map((q) => q.value.cooked);
1418
+ strings.raw = node.quasi.quasis.map((q) => q.value.raw);
1419
+
1420
+ if (func === String.raw) {
1421
+ return { value: func(strings, ...expressions) }
1422
+ }
1423
+ }
1424
+
1425
+ return null
1426
+ },
1427
+
1428
+ TemplateLiteral(node, initialScope) {
1429
+ const expressions = getElementValues(node.expressions, initialScope);
1430
+ if (expressions != null) {
1431
+ let value = node.quasis[0].value.cooked;
1432
+ for (let i = 0; i < expressions.length; ++i) {
1433
+ value += expressions[i];
1434
+ value += /** @type {string} */ (node.quasis[i + 1].value.cooked);
1435
+ }
1436
+ return { value }
1437
+ }
1438
+ return null
1439
+ },
1440
+
1441
+ UnaryExpression(node, initialScope) {
1442
+ if (node.operator === "delete") {
1443
+ // Not supported.
1444
+ return null
1445
+ }
1446
+ if (node.operator === "void") {
1447
+ return { value: undefined }
1448
+ }
1449
+
1450
+ const arg = getStaticValueR(node.argument, initialScope);
1451
+ if (arg != null) {
1452
+ switch (node.operator) {
1453
+ case "-":
1454
+ return { value: -(/** @type {any} */ (arg.value)) }
1455
+ case "+":
1456
+ return { value: +(/** @type {any} */ (arg.value)) } //eslint-disable-line no-implicit-coercion
1457
+ case "!":
1458
+ return { value: !arg.value }
1459
+ case "~":
1460
+ return { value: ~(/** @type {any} */ (arg.value)) }
1461
+ case "typeof":
1462
+ return { value: typeof arg.value }
1463
+
1464
+ // no default
1465
+ }
1466
+ }
1467
+
1468
+ return null
1469
+ },
1470
+ TSAsExpression(node, initialScope) {
1471
+ return getStaticValueR(node.expression, initialScope)
1472
+ },
1473
+ TSSatisfiesExpression(node, initialScope) {
1474
+ return getStaticValueR(node.expression, initialScope)
1475
+ },
1476
+ TSTypeAssertion(node, initialScope) {
1477
+ return getStaticValueR(node.expression, initialScope)
1478
+ },
1479
+ TSNonNullExpression(node, initialScope) {
1480
+ return getStaticValueR(node.expression, initialScope)
1481
+ },
1482
+ TSInstantiationExpression(node, initialScope) {
1483
+ return getStaticValueR(node.expression, initialScope)
1484
+ },
1485
+ });
1486
+
1487
+ /**
1488
+ * Get the value of a given node if it's a static value.
1489
+ * @param {Node|TSESTreeNode|null|undefined} node The node to get.
1490
+ * @param {Scope|undefined|null} initialScope The scope to start finding variable.
1491
+ * @returns {StaticValue|null} The static value of the node, or `null`.
1492
+ */
1493
+ function getStaticValueR(node, initialScope) {
1494
+ if (node != null && Object.hasOwnProperty.call(operations, node.type)) {
1495
+ return /** @type {VisitorCallback<any>} */ (operations[node.type])(
1496
+ /** @type {TSESTreeNode} */ (node),
1497
+ initialScope,
1498
+ )
1499
+ }
1500
+ return null
1501
+ }
1502
+
1503
+ /**
1504
+ * Get the static value of property name from a MemberExpression node or a Property node.
1505
+ * @param {MemberExpression|Property} node The node to get.
1506
+ * @param {Scope|null} [initialScope] The scope to start finding variable. Optional. If the node is a computed property node and this scope was given, this checks the computed property name by the `getStringIfConstant` function with the scope, and returns the value of it.
1507
+ * @returns {StaticValue|null} The static value of the property name of the node, or `null`.
1508
+ */
1509
+ function getStaticPropertyNameValue(node, initialScope) {
1510
+ const nameNode = node.type === "Property" ? node.key : node.property;
1511
+
1512
+ if (node.computed) {
1513
+ return getStaticValueR(nameNode, initialScope)
1514
+ }
1515
+
1516
+ if (nameNode.type === "Identifier") {
1517
+ return { value: nameNode.name }
1518
+ }
1519
+
1520
+ if (nameNode.type === "Literal") {
1521
+ if (/** @type {Partial<BigIntLiteral>} */ (nameNode).bigint) {
1522
+ return { value: /** @type {BigIntLiteral} */ (nameNode).bigint }
1523
+ }
1524
+ return { value: String(nameNode.value) }
1525
+ }
1526
+
1527
+ return null
1528
+ }
1529
+
1530
+ /**
1531
+ * Get the value of a given node if it's a static value.
1532
+ * @param {Node} node The node to get.
1533
+ * @param {Scope|null} [initialScope] The scope to start finding variable. Optional. If this scope was given, this tries to resolve identifier references which are in the given node as much as possible.
1534
+ * @returns {StaticValue | null} The static value of the node, or `null`.
1535
+ */
1536
+ function getStaticValue(node, initialScope = null) {
1537
+ try {
1538
+ return getStaticValueR(node, initialScope)
1539
+ } catch (_error) {
1540
+ return null
1541
+ }
1542
+ }
1543
+
1544
+ /** @typedef {import("eslint").Scope.Scope} Scope */
1545
+ /** @typedef {import("estree").Node} Node */
1546
+ /** @typedef {import("estree").RegExpLiteral} RegExpLiteral */
1547
+ /** @typedef {import("estree").BigIntLiteral} BigIntLiteral */
1548
+ /** @typedef {import("estree").SimpleLiteral} SimpleLiteral */
1549
+
1550
+ /**
1551
+ * Get the value of a given node if it's a literal or a template literal.
1552
+ * @param {Node} node The node to get.
1553
+ * @param {Scope|null} [initialScope] The scope to start finding variable. Optional. If the node is an Identifier node and this scope was given, this checks the variable of the identifier, and returns the value of it if the variable is a constant.
1554
+ * @returns {string|null} The value of the node, or `null`.
1555
+ */
1556
+ function getStringIfConstant(node, initialScope = null) {
1557
+ // Handle the literals that the platform doesn't support natively.
1558
+ if (node && node.type === "Literal" && node.value === null) {
1559
+ const literal =
1560
+ /** @type {Partial<SimpleLiteral> & Partial<RegExpLiteral> & Partial<BigIntLiteral>} */ (
1561
+ node
1562
+ );
1563
+ if (literal.regex) {
1564
+ return `/${literal.regex.pattern}/${literal.regex.flags}`
1565
+ }
1566
+ if (literal.bigint) {
1567
+ return literal.bigint
1568
+ }
1569
+ }
1570
+
1571
+ const evaluated = getStaticValue(node, initialScope);
1572
+
1573
+ if (evaluated) {
1574
+ // `String(Symbol.prototype)` throws error
1575
+ try {
1576
+ return String(evaluated.value)
1577
+ } catch {
1578
+ // No op
1579
+ }
1580
+ }
1581
+
1582
+ return null
1583
+ }
1584
+
1585
+ /** @typedef {import("eslint").Scope.Scope} Scope */
1586
+ /** @typedef {import("estree").MemberExpression} MemberExpression */
1587
+ /** @typedef {import("estree").MethodDefinition} MethodDefinition */
1588
+ /** @typedef {import("estree").Property} Property */
1589
+ /** @typedef {import("estree").PropertyDefinition} PropertyDefinition */
1590
+ /** @typedef {import("estree").Identifier} Identifier */
1591
+
1592
+ /**
1593
+ * Get the property name from a MemberExpression node or a Property node.
1594
+ * @param {MemberExpression | MethodDefinition | Property | PropertyDefinition} node The node to get.
1595
+ * @param {Scope} [initialScope] The scope to start finding variable. Optional. If the node is a computed property node and this scope was given, this checks the computed property name by the `getStringIfConstant` function with the scope, and returns the value of it.
1596
+ * @returns {string|null|undefined} The property name of the node.
1597
+ */
1598
+ function getPropertyName(node, initialScope) {
1599
+ switch (node.type) {
1600
+ case "MemberExpression":
1601
+ if (node.computed) {
1602
+ return getStringIfConstant(node.property, initialScope)
1603
+ }
1604
+ if (node.property.type === "PrivateIdentifier") {
1605
+ return null
1606
+ }
1607
+ return /** @type {Partial<Identifier>} */ (node.property).name
1608
+
1609
+ case "Property":
1610
+ case "MethodDefinition":
1611
+ case "PropertyDefinition":
1612
+ if (node.computed) {
1613
+ return getStringIfConstant(node.key, initialScope)
1614
+ }
1615
+ if (node.key.type === "Literal") {
1616
+ return String(node.key.value)
1617
+ }
1618
+ if (node.key.type === "PrivateIdentifier") {
1619
+ return null
1620
+ }
1621
+ return /** @type {Partial<Identifier>} */ (node.key).name
1622
+ }
1623
+
1624
+ return null
1625
+ }
1626
+
1627
+ /** @typedef {import("eslint").Rule.Node} RuleNode */
1628
+ /** @typedef {import("eslint").SourceCode} SourceCode */
1629
+ /** @typedef {import("estree").Function} FunctionNode */
1630
+ /** @typedef {import("estree").FunctionDeclaration} FunctionDeclaration */
1631
+ /** @typedef {import("estree").FunctionExpression} FunctionExpression */
1632
+ /** @typedef {import("estree").Identifier} Identifier */
1633
+
1634
+ /**
1635
+ * Get the name and kind of the given function node.
1636
+ * @param {FunctionNode} node - The function node to get.
1637
+ * @param {SourceCode} [sourceCode] The source code object to get the code of computed property keys.
1638
+ * @returns {string} The name and kind of the function node.
1639
+ */
1640
+ // eslint-disable-next-line complexity
1641
+ function getFunctionNameWithKind(node, sourceCode) {
1642
+ const parent = /** @type {RuleNode} */ (node).parent;
1643
+
1644
+ if (!parent) {
1645
+ return ""
1646
+ }
1647
+
1648
+ const tokens = [];
1649
+ const isObjectMethod = parent.type === "Property" && parent.value === node;
1650
+ const isClassMethod =
1651
+ parent.type === "MethodDefinition" && parent.value === node;
1652
+ const isClassFieldMethod =
1653
+ parent.type === "PropertyDefinition" && parent.value === node;
1654
+
1655
+ // Modifiers.
1656
+ if (isClassMethod || isClassFieldMethod) {
1657
+ if (parent.static) {
1658
+ tokens.push("static");
1659
+ }
1660
+ if (parent.key.type === "PrivateIdentifier") {
1661
+ tokens.push("private");
1662
+ }
1663
+ }
1664
+ if (node.async) {
1665
+ tokens.push("async");
1666
+ }
1667
+ if (node.generator) {
1668
+ tokens.push("generator");
1669
+ }
1670
+
1671
+ // Kinds.
1672
+ if (isObjectMethod || isClassMethod) {
1673
+ if (parent.kind === "constructor") {
1674
+ return "constructor"
1675
+ }
1676
+ if (parent.kind === "get") {
1677
+ tokens.push("getter");
1678
+ } else if (parent.kind === "set") {
1679
+ tokens.push("setter");
1680
+ } else {
1681
+ tokens.push("method");
1682
+ }
1683
+ } else if (isClassFieldMethod) {
1684
+ tokens.push("method");
1685
+ } else {
1686
+ if (node.type === "ArrowFunctionExpression") {
1687
+ tokens.push("arrow");
1688
+ }
1689
+ tokens.push("function");
1690
+ }
1691
+
1692
+ // Names.
1693
+ if (isObjectMethod || isClassMethod || isClassFieldMethod) {
1694
+ if (parent.key.type === "PrivateIdentifier") {
1695
+ tokens.push(`#${parent.key.name}`);
1696
+ } else {
1697
+ const name = getPropertyName(parent);
1698
+ if (name) {
1699
+ tokens.push(`'${name}'`);
1700
+ } else if (sourceCode) {
1701
+ const keyText = sourceCode.getText(parent.key);
1702
+ if (!keyText.includes("\n")) {
1703
+ tokens.push(`[${keyText}]`);
1704
+ }
1705
+ }
1706
+ }
1707
+ } else if (hasId(node)) {
1708
+ tokens.push(`'${node.id.name}'`);
1709
+ } else if (
1710
+ parent.type === "VariableDeclarator" &&
1711
+ parent.id &&
1712
+ parent.id.type === "Identifier"
1713
+ ) {
1714
+ tokens.push(`'${parent.id.name}'`);
1715
+ } else if (
1716
+ (parent.type === "AssignmentExpression" ||
1717
+ parent.type === "AssignmentPattern") &&
1718
+ parent.left &&
1719
+ parent.left.type === "Identifier"
1720
+ ) {
1721
+ tokens.push(`'${parent.left.name}'`);
1722
+ } else if (
1723
+ parent.type === "ExportDefaultDeclaration" &&
1724
+ parent.declaration === node
1725
+ ) {
1726
+ tokens.push("'default'");
1727
+ }
1728
+
1729
+ return tokens.join(" ")
1730
+ }
1731
+
1732
+ /**
1733
+ * @param {FunctionNode} node
1734
+ * @returns {node is FunctionDeclaration | FunctionExpression & { id: Identifier }}
1735
+ */
1736
+ function hasId(node) {
1737
+ return Boolean(
1738
+ /** @type {Partial<FunctionDeclaration | FunctionExpression>} */ (node)
1739
+ .id,
1740
+ )
1741
+ }
1742
+
1743
+ /** @typedef {import("estree").Node} Node */
1744
+ /** @typedef {import("eslint").SourceCode} SourceCode */
1745
+ /** @typedef {import("./types.mjs").HasSideEffectOptions} HasSideEffectOptions */
1746
+ /** @typedef {import("estree").BinaryExpression} BinaryExpression */
1747
+ /** @typedef {import("estree").MemberExpression} MemberExpression */
1748
+ /** @typedef {import("estree").MethodDefinition} MethodDefinition */
1749
+ /** @typedef {import("estree").Property} Property */
1750
+ /** @typedef {import("estree").PropertyDefinition} PropertyDefinition */
1751
+ /** @typedef {import("estree").UnaryExpression} UnaryExpression */
1752
+
1753
+ const typeConversionBinaryOps = Object.freeze(
1754
+ new Set([
1755
+ "==",
1756
+ "!=",
1757
+ "<",
1758
+ "<=",
1759
+ ">",
1760
+ ">=",
1761
+ "<<",
1762
+ ">>",
1763
+ ">>>",
1764
+ "+",
1765
+ "-",
1766
+ "*",
1767
+ "/",
1768
+ "%",
1769
+ "|",
1770
+ "^",
1771
+ "&",
1772
+ "in",
1773
+ ]),
1774
+ );
1775
+ const typeConversionUnaryOps = Object.freeze(new Set(["-", "+", "!", "~"]));
1776
+
1777
+ /**
1778
+ * Check whether the given value is an ASTNode or not.
1779
+ * @param {any} x The value to check.
1780
+ * @returns {x is Node} `true` if the value is an ASTNode.
1781
+ */
1782
+ function isNode(x) {
1783
+ return x !== null && typeof x === "object" && typeof x.type === "string"
1784
+ }
1785
+
1786
+ const visitor = Object.freeze(
1787
+ Object.assign(Object.create(null), {
1788
+ /**
1789
+ * @param {Node} node
1790
+ * @param {HasSideEffectOptions} options
1791
+ * @param {Record<string, string[]>} visitorKeys
1792
+ */
1793
+ $visit(node, options, visitorKeys) {
1794
+ const { type } = node;
1795
+
1796
+ if (typeof (/** @type {any} */ (this)[type]) === "function") {
1797
+ return /** @type {any} */ (this)[type](
1798
+ node,
1799
+ options,
1800
+ visitorKeys,
1801
+ )
1802
+ }
1803
+
1804
+ return this.$visitChildren(node, options, visitorKeys)
1805
+ },
1806
+
1807
+ /**
1808
+ * @param {Node} node
1809
+ * @param {HasSideEffectOptions} options
1810
+ * @param {Record<string, string[]>} visitorKeys
1811
+ */
1812
+ $visitChildren(node, options, visitorKeys) {
1813
+ const { type } = node;
1814
+
1815
+ for (const key of /** @type {(keyof Node)[]} */ (
1816
+ visitorKeys[type] || getKeys(node)
1817
+ )) {
1818
+ const value = node[key];
1819
+
1820
+ if (Array.isArray(value)) {
1821
+ for (const element of value) {
1822
+ if (
1823
+ isNode(element) &&
1824
+ this.$visit(element, options, visitorKeys)
1825
+ ) {
1826
+ return true
1827
+ }
1828
+ }
1829
+ } else if (
1830
+ isNode(value) &&
1831
+ this.$visit(value, options, visitorKeys)
1832
+ ) {
1833
+ return true
1834
+ }
1835
+ }
1836
+
1837
+ return false
1838
+ },
1839
+
1840
+ ArrowFunctionExpression() {
1841
+ return false
1842
+ },
1843
+ AssignmentExpression() {
1844
+ return true
1845
+ },
1846
+ AwaitExpression() {
1847
+ return true
1848
+ },
1849
+ /**
1850
+ * @param {BinaryExpression} node
1851
+ * @param {HasSideEffectOptions} options
1852
+ * @param {Record<string, string[]>} visitorKeys
1853
+ */
1854
+ BinaryExpression(node, options, visitorKeys) {
1855
+ if (
1856
+ options.considerImplicitTypeConversion &&
1857
+ typeConversionBinaryOps.has(node.operator) &&
1858
+ (node.left.type !== "Literal" || node.right.type !== "Literal")
1859
+ ) {
1860
+ return true
1861
+ }
1862
+ return this.$visitChildren(node, options, visitorKeys)
1863
+ },
1864
+ CallExpression() {
1865
+ return true
1866
+ },
1867
+ FunctionExpression() {
1868
+ return false
1869
+ },
1870
+ ImportExpression() {
1871
+ return true
1872
+ },
1873
+ /**
1874
+ * @param {MemberExpression} node
1875
+ * @param {HasSideEffectOptions} options
1876
+ * @param {Record<string, string[]>} visitorKeys
1877
+ */
1878
+ MemberExpression(node, options, visitorKeys) {
1879
+ if (options.considerGetters) {
1880
+ return true
1881
+ }
1882
+ if (
1883
+ options.considerImplicitTypeConversion &&
1884
+ node.computed &&
1885
+ node.property.type !== "Literal"
1886
+ ) {
1887
+ return true
1888
+ }
1889
+ return this.$visitChildren(node, options, visitorKeys)
1890
+ },
1891
+ /**
1892
+ * @param {MethodDefinition} node
1893
+ * @param {HasSideEffectOptions} options
1894
+ * @param {Record<string, string[]>} visitorKeys
1895
+ */
1896
+ MethodDefinition(node, options, visitorKeys) {
1897
+ if (
1898
+ options.considerImplicitTypeConversion &&
1899
+ node.computed &&
1900
+ node.key.type !== "Literal"
1901
+ ) {
1902
+ return true
1903
+ }
1904
+ return this.$visitChildren(node, options, visitorKeys)
1905
+ },
1906
+ NewExpression() {
1907
+ return true
1908
+ },
1909
+ /**
1910
+ * @param {Property} node
1911
+ * @param {HasSideEffectOptions} options
1912
+ * @param {Record<string, string[]>} visitorKeys
1913
+ */
1914
+ Property(node, options, visitorKeys) {
1915
+ if (
1916
+ options.considerImplicitTypeConversion &&
1917
+ node.computed &&
1918
+ node.key.type !== "Literal"
1919
+ ) {
1920
+ return true
1921
+ }
1922
+ return this.$visitChildren(node, options, visitorKeys)
1923
+ },
1924
+ /**
1925
+ * @param {PropertyDefinition} node
1926
+ * @param {HasSideEffectOptions} options
1927
+ * @param {Record<string, string[]>} visitorKeys
1928
+ */
1929
+ PropertyDefinition(node, options, visitorKeys) {
1930
+ if (
1931
+ options.considerImplicitTypeConversion &&
1932
+ node.computed &&
1933
+ node.key.type !== "Literal"
1934
+ ) {
1935
+ return true
1936
+ }
1937
+ return this.$visitChildren(node, options, visitorKeys)
1938
+ },
1939
+ /**
1940
+ * @param {UnaryExpression} node
1941
+ * @param {HasSideEffectOptions} options
1942
+ * @param {Record<string, string[]>} visitorKeys
1943
+ */
1944
+ UnaryExpression(node, options, visitorKeys) {
1945
+ if (node.operator === "delete") {
1946
+ return true
1947
+ }
1948
+ if (
1949
+ options.considerImplicitTypeConversion &&
1950
+ typeConversionUnaryOps.has(node.operator) &&
1951
+ node.argument.type !== "Literal"
1952
+ ) {
1953
+ return true
1954
+ }
1955
+ return this.$visitChildren(node, options, visitorKeys)
1956
+ },
1957
+ UpdateExpression() {
1958
+ return true
1959
+ },
1960
+ YieldExpression() {
1961
+ return true
1962
+ },
1963
+ }),
1964
+ );
1965
+
1966
+ /**
1967
+ * Check whether a given node has any side effect or not.
1968
+ * @param {Node} node The node to get.
1969
+ * @param {SourceCode} sourceCode The source code object.
1970
+ * @param {HasSideEffectOptions} [options] The option object.
1971
+ * @returns {boolean} `true` if the node has a certain side effect.
1972
+ */
1973
+ function hasSideEffect(node, sourceCode, options = {}) {
1974
+ const { considerGetters = false, considerImplicitTypeConversion = false } =
1975
+ options;
1976
+ return visitor.$visit(
1977
+ node,
1978
+ { considerGetters, considerImplicitTypeConversion },
1979
+ sourceCode.visitorKeys || KEYS,
1980
+ )
1981
+ }
1982
+
1983
+ /** @typedef {import("estree").Node} Node */
1984
+ /** @typedef {import("@typescript-eslint/types").TSESTree.NewExpression} TSNewExpression */
1985
+ /** @typedef {import("@typescript-eslint/types").TSESTree.CallExpression} TSCallExpression */
1986
+ /** @typedef {import("eslint").SourceCode} SourceCode */
1987
+ /** @typedef {import("eslint").AST.Token} Token */
1988
+ /** @typedef {import("eslint").Rule.Node} RuleNode */
1989
+
1990
+ /**
1991
+ * Get the left parenthesis of the parent node syntax if it exists.
1992
+ * E.g., `if (a) {}` then the `(`.
1993
+ * @param {Node} node The AST node to check.
1994
+ * @param {SourceCode} sourceCode The source code object to get tokens.
1995
+ * @returns {Token|null} The left parenthesis of the parent node syntax
1996
+ */
1997
+ // eslint-disable-next-line complexity
1998
+ function getParentSyntaxParen(node, sourceCode) {
1999
+ const parent = /** @type {RuleNode} */ (node).parent;
2000
+
2001
+ if (!parent) {
2002
+ return null
2003
+ }
2004
+
2005
+ switch (parent.type) {
2006
+ case "CallExpression":
2007
+ case "NewExpression":
2008
+ if (parent.arguments.length === 1 && parent.arguments[0] === node) {
2009
+ return sourceCode.getTokenAfter(
2010
+ // @ts-expect-error https://github.com/typescript-eslint/typescript-eslint/pull/5384
2011
+ parent.typeArguments ||
2012
+ /** @type {RuleNode} */ (
2013
+ /** @type {unknown} */ (
2014
+ /** @type {TSNewExpression | TSCallExpression} */ (
2015
+ parent
2016
+ ).typeParameters
2017
+ )
2018
+ ) ||
2019
+ parent.callee,
2020
+ isOpeningParenToken,
2021
+ )
2022
+ }
2023
+ return null
2024
+
2025
+ case "DoWhileStatement":
2026
+ if (parent.test === node) {
2027
+ return sourceCode.getTokenAfter(
2028
+ parent.body,
2029
+ isOpeningParenToken,
2030
+ )
2031
+ }
2032
+ return null
2033
+
2034
+ case "IfStatement":
2035
+ case "WhileStatement":
2036
+ if (parent.test === node) {
2037
+ return sourceCode.getFirstToken(parent, 1)
2038
+ }
2039
+ return null
2040
+
2041
+ case "ImportExpression":
2042
+ if (parent.source === node) {
2043
+ return sourceCode.getFirstToken(parent, 1)
2044
+ }
2045
+ return null
2046
+
2047
+ case "SwitchStatement":
2048
+ if (parent.discriminant === node) {
2049
+ return sourceCode.getFirstToken(parent, 1)
2050
+ }
2051
+ return null
2052
+
2053
+ case "WithStatement":
2054
+ if (parent.object === node) {
2055
+ return sourceCode.getFirstToken(parent, 1)
2056
+ }
2057
+ return null
2058
+
2059
+ default:
2060
+ return null
2061
+ }
2062
+ }
2063
+
2064
+ /**
2065
+ * Check whether a given node is parenthesized or not.
2066
+ * @param {number} times The number of parantheses.
2067
+ * @param {Node} node The AST node to check.
2068
+ * @param {SourceCode} sourceCode The source code object to get tokens.
2069
+ * @returns {boolean} `true` if the node is parenthesized the given times.
2070
+ */
2071
+ /**
2072
+ * Check whether a given node is parenthesized or not.
2073
+ * @param {Node} node The AST node to check.
2074
+ * @param {SourceCode} sourceCode The source code object to get tokens.
2075
+ * @returns {boolean} `true` if the node is parenthesized.
2076
+ */
2077
+ /**
2078
+ * Check whether a given node is parenthesized or not.
2079
+ * @param {Node|number} timesOrNode The first parameter.
2080
+ * @param {Node|SourceCode} nodeOrSourceCode The second parameter.
2081
+ * @param {SourceCode} [optionalSourceCode] The third parameter.
2082
+ * @returns {boolean} `true` if the node is parenthesized.
2083
+ */
2084
+ function isParenthesized(
2085
+ timesOrNode,
2086
+ nodeOrSourceCode,
2087
+ optionalSourceCode,
2088
+ ) {
2089
+ /** @type {number} */
2090
+ let times,
2091
+ /** @type {RuleNode} */
2092
+ node,
2093
+ /** @type {SourceCode} */
2094
+ sourceCode,
2095
+ maybeLeftParen,
2096
+ maybeRightParen;
2097
+ if (typeof timesOrNode === "number") {
2098
+ times = timesOrNode | 0;
2099
+ node = /** @type {RuleNode} */ (nodeOrSourceCode);
2100
+ sourceCode = /** @type {SourceCode} */ (optionalSourceCode);
2101
+ if (!(times >= 1)) {
2102
+ throw new TypeError("'times' should be a positive integer.")
2103
+ }
2104
+ } else {
2105
+ times = 1;
2106
+ node = /** @type {RuleNode} */ (timesOrNode);
2107
+ sourceCode = /** @type {SourceCode} */ (nodeOrSourceCode);
2108
+ }
2109
+
2110
+ if (
2111
+ node == null ||
2112
+ // `Program` can't be parenthesized
2113
+ node.parent == null ||
2114
+ // `CatchClause.param` can't be parenthesized, example `try {} catch (error) {}`
2115
+ (node.parent.type === "CatchClause" && node.parent.param === node)
2116
+ ) {
2117
+ return false
2118
+ }
2119
+
2120
+ maybeLeftParen = maybeRightParen = node;
2121
+ do {
2122
+ maybeLeftParen = sourceCode.getTokenBefore(maybeLeftParen);
2123
+ maybeRightParen = sourceCode.getTokenAfter(maybeRightParen);
2124
+ } while (
2125
+ maybeLeftParen != null &&
2126
+ maybeRightParen != null &&
2127
+ isOpeningParenToken(maybeLeftParen) &&
2128
+ isClosingParenToken(maybeRightParen) &&
2129
+ // Avoid false positive such as `if (a) {}`
2130
+ maybeLeftParen !== getParentSyntaxParen(node, sourceCode) &&
2131
+ --times > 0
2132
+ )
2133
+
2134
+ return times === 0
2135
+ }
2136
+
2137
+ /** @typedef {import("eslint").Scope.Scope} Scope */
2138
+ /** @typedef {import("eslint").Scope.Variable} Variable */
2139
+ /** @typedef {import("eslint").Rule.Node} RuleNode */
2140
+ /** @typedef {import("estree").Node} Node */
2141
+ /** @typedef {import("estree").Expression} Expression */
2142
+ /** @typedef {import("estree").Pattern} Pattern */
2143
+ /** @typedef {import("estree").Identifier} Identifier */
2144
+ /** @typedef {import("estree").SimpleCallExpression} CallExpression */
2145
+ /** @typedef {import("estree").Program} Program */
2146
+ /** @typedef {import("estree").ImportDeclaration} ImportDeclaration */
2147
+ /** @typedef {import("estree").ExportAllDeclaration} ExportAllDeclaration */
2148
+ /** @typedef {import("estree").ExportDefaultDeclaration} ExportDefaultDeclaration */
2149
+ /** @typedef {import("estree").ExportNamedDeclaration} ExportNamedDeclaration */
2150
+ /** @typedef {import("estree").ImportSpecifier} ImportSpecifier */
2151
+ /** @typedef {import("estree").ImportDefaultSpecifier} ImportDefaultSpecifier */
2152
+ /** @typedef {import("estree").ImportNamespaceSpecifier} ImportNamespaceSpecifier */
2153
+ /** @typedef {import("estree").ExportSpecifier} ExportSpecifier */
2154
+ /** @typedef {import("estree").Property} Property */
2155
+ /** @typedef {import("estree").AssignmentProperty} AssignmentProperty */
2156
+ /** @typedef {import("estree").Literal} Literal */
2157
+ /** @typedef {import("@typescript-eslint/types").TSESTree.Node} TSESTreeNode */
2158
+ /** @typedef {import("./types.mjs").ReferenceTrackerOptions} ReferenceTrackerOptions */
2159
+ /**
2160
+ * @template T
2161
+ * @typedef {import("./types.mjs").TraceMap<T>} TraceMap
2162
+ */
2163
+ /**
2164
+ * @template T
2165
+ * @typedef {import("./types.mjs").TraceMapObject<T>} TraceMapObject
2166
+ */
2167
+ /**
2168
+ * @template T
2169
+ * @typedef {import("./types.mjs").TrackedReferences<T>} TrackedReferences
2170
+ */
2171
+
2172
+ const IMPORT_TYPE = /^(?:Import|Export(?:All|Default|Named))Declaration$/u;
2173
+
2174
+ /**
2175
+ * Check whether a given node is an import node or not.
2176
+ * @param {Node} node
2177
+ * @returns {node is ImportDeclaration|ExportAllDeclaration|ExportNamedDeclaration&{source: Literal}} `true` if the node is an import node.
2178
+ */
2179
+ function isHasSource(node) {
2180
+ return (
2181
+ IMPORT_TYPE.test(node.type) &&
2182
+ /** @type {ImportDeclaration|ExportAllDeclaration|ExportNamedDeclaration} */ (
2183
+ node
2184
+ ).source != null
2185
+ )
2186
+ }
2187
+ const has =
2188
+ /** @type {<T>(traceMap: TraceMap<unknown>, v: T) => v is (string extends T ? string : T)} */ (
2189
+ Function.call.bind(Object.hasOwnProperty)
2190
+ );
2191
+
2192
+ const READ = Symbol("read");
2193
+ const CALL = Symbol("call");
2194
+ const CONSTRUCT = Symbol("construct");
2195
+ const ESM = Symbol("esm");
2196
+
2197
+ const requireCall = { require: { [CALL]: true } };
2198
+
2199
+ /**
2200
+ * Check whether a given variable is modified or not.
2201
+ * @param {Variable|undefined} variable The variable to check.
2202
+ * @returns {boolean} `true` if the variable is modified.
2203
+ */
2204
+ function isModifiedGlobal(variable) {
2205
+ return (
2206
+ variable == null ||
2207
+ variable.defs.length !== 0 ||
2208
+ variable.references.some((r) => r.isWrite())
2209
+ )
2210
+ }
2211
+
2212
+ /**
2213
+ * Check if the value of a given node is passed through to the parent syntax as-is.
2214
+ * For example, `a` and `b` in (`a || b` and `c ? a : b`) are passed through.
2215
+ * @param {Node} node A node to check.
2216
+ * @returns {node is RuleNode & {parent: Expression}} `true` if the node is passed through.
2217
+ */
2218
+ function isPassThrough(node) {
2219
+ const parent = /** @type {TSESTreeNode} */ (node).parent;
2220
+
2221
+ if (parent) {
2222
+ switch (parent.type) {
2223
+ case "ConditionalExpression":
2224
+ return parent.consequent === node || parent.alternate === node
2225
+ case "LogicalExpression":
2226
+ return true
2227
+ case "SequenceExpression":
2228
+ return (
2229
+ parent.expressions[parent.expressions.length - 1] === node
2230
+ )
2231
+ case "ChainExpression":
2232
+ return true
2233
+ case "TSAsExpression":
2234
+ case "TSSatisfiesExpression":
2235
+ case "TSTypeAssertion":
2236
+ case "TSNonNullExpression":
2237
+ case "TSInstantiationExpression":
2238
+ return true
2239
+
2240
+ default:
2241
+ return false
2242
+ }
2243
+ }
2244
+ return false
2245
+ }
2246
+
2247
+ /**
2248
+ * The reference tracker.
2249
+ */
2250
+ class ReferenceTracker {
2251
+ /**
2252
+ * Initialize this tracker.
2253
+ * @param {Scope} globalScope The global scope.
2254
+ * @param {object} [options] The options.
2255
+ * @param {"legacy"|"strict"} [options.mode="strict"] The mode to determine the ImportDeclaration's behavior for CJS modules.
2256
+ * @param {string[]} [options.globalObjectNames=["global","globalThis","self","window"]] The variable names for Global Object.
2257
+ */
2258
+ constructor(globalScope, options = {}) {
2259
+ const {
2260
+ mode = "strict",
2261
+ globalObjectNames = ["global", "globalThis", "self", "window"],
2262
+ } = options;
2263
+ /** @private @type {Variable[]} */
2264
+ this.variableStack = [];
2265
+ /** @private */
2266
+ this.globalScope = globalScope;
2267
+ /** @private */
2268
+ this.mode = mode;
2269
+ /** @private */
2270
+ this.globalObjectNames = globalObjectNames.slice(0);
2271
+ }
2272
+
2273
+ /**
2274
+ * Iterate the references of global variables.
2275
+ * @template T
2276
+ * @param {TraceMap<T>} traceMap The trace map.
2277
+ * @returns {IterableIterator<TrackedReferences<T>>} The iterator to iterate references.
2278
+ */
2279
+ *iterateGlobalReferences(traceMap) {
2280
+ for (const key of Object.keys(traceMap)) {
2281
+ const nextTraceMap = traceMap[key];
2282
+ const path = [key];
2283
+ const variable = this.globalScope.set.get(key);
2284
+
2285
+ if (isModifiedGlobal(variable)) {
2286
+ continue
2287
+ }
2288
+
2289
+ yield* this._iterateVariableReferences(
2290
+ /** @type {Variable} */ (variable),
2291
+ path,
2292
+ nextTraceMap,
2293
+ true,
2294
+ );
2295
+ }
2296
+
2297
+ for (const key of this.globalObjectNames) {
2298
+ /** @type {string[]} */
2299
+ const path = [];
2300
+ const variable = this.globalScope.set.get(key);
2301
+
2302
+ if (isModifiedGlobal(variable)) {
2303
+ continue
2304
+ }
2305
+
2306
+ yield* this._iterateVariableReferences(
2307
+ /** @type {Variable} */ (variable),
2308
+ path,
2309
+ traceMap,
2310
+ false,
2311
+ );
2312
+ }
2313
+ }
2314
+
2315
+ /**
2316
+ * Iterate the references of CommonJS modules.
2317
+ * @template T
2318
+ * @param {TraceMap<T>} traceMap The trace map.
2319
+ * @returns {IterableIterator<TrackedReferences<T>>} The iterator to iterate references.
2320
+ */
2321
+ *iterateCjsReferences(traceMap) {
2322
+ for (const { node } of this.iterateGlobalReferences(requireCall)) {
2323
+ const key = getStringIfConstant(
2324
+ /** @type {CallExpression} */ (node).arguments[0],
2325
+ );
2326
+ if (key == null || !has(traceMap, key)) {
2327
+ continue
2328
+ }
2329
+
2330
+ const nextTraceMap = traceMap[key];
2331
+ const path = [key];
2332
+
2333
+ if (nextTraceMap[READ]) {
2334
+ yield {
2335
+ node,
2336
+ path,
2337
+ type: READ,
2338
+ info: nextTraceMap[READ],
2339
+ };
2340
+ }
2341
+ yield* this._iteratePropertyReferences(
2342
+ /** @type {CallExpression} */ (node),
2343
+ path,
2344
+ nextTraceMap,
2345
+ );
2346
+ }
2347
+ }
2348
+
2349
+ /**
2350
+ * Iterate the references of ES modules.
2351
+ * @template T
2352
+ * @param {TraceMap<T>} traceMap The trace map.
2353
+ * @returns {IterableIterator<TrackedReferences<T>>} The iterator to iterate references.
2354
+ */
2355
+ *iterateEsmReferences(traceMap) {
2356
+ const programNode = /** @type {Program} */ (this.globalScope.block);
2357
+
2358
+ for (const node of programNode.body) {
2359
+ if (!isHasSource(node)) {
2360
+ continue
2361
+ }
2362
+ const moduleId = /** @type {string} */ (node.source.value);
2363
+
2364
+ if (!has(traceMap, moduleId)) {
2365
+ continue
2366
+ }
2367
+ const nextTraceMap = traceMap[moduleId];
2368
+ const path = [moduleId];
2369
+
2370
+ if (nextTraceMap[READ]) {
2371
+ yield {
2372
+ // eslint-disable-next-line object-shorthand -- apply type
2373
+ node: /** @type {RuleNode} */ (node),
2374
+ path,
2375
+ type: READ,
2376
+ info: nextTraceMap[READ],
2377
+ };
2378
+ }
2379
+
2380
+ if (node.type === "ExportAllDeclaration") {
2381
+ for (const key of Object.keys(nextTraceMap)) {
2382
+ const exportTraceMap = nextTraceMap[key];
2383
+ if (exportTraceMap[READ]) {
2384
+ yield {
2385
+ // eslint-disable-next-line object-shorthand -- apply type
2386
+ node: /** @type {RuleNode} */ (node),
2387
+ path: path.concat(key),
2388
+ type: READ,
2389
+ info: exportTraceMap[READ],
2390
+ };
2391
+ }
2392
+ }
2393
+ } else {
2394
+ for (const specifier of node.specifiers) {
2395
+ const esm = has(nextTraceMap, ESM);
2396
+ const it = this._iterateImportReferences(
2397
+ specifier,
2398
+ path,
2399
+ esm
2400
+ ? nextTraceMap
2401
+ : this.mode === "legacy"
2402
+ ? { default: nextTraceMap, ...nextTraceMap }
2403
+ : { default: nextTraceMap },
2404
+ );
2405
+
2406
+ if (esm) {
2407
+ yield* it;
2408
+ } else {
2409
+ for (const report of it) {
2410
+ report.path = report.path.filter(exceptDefault);
2411
+ if (
2412
+ report.path.length >= 2 ||
2413
+ report.type !== READ
2414
+ ) {
2415
+ yield report;
2416
+ }
2417
+ }
2418
+ }
2419
+ }
2420
+ }
2421
+ }
2422
+ }
2423
+
2424
+ /**
2425
+ * Iterate the property references for a given expression AST node.
2426
+ * @template T
2427
+ * @param {Expression} node The expression AST node to iterate property references.
2428
+ * @param {TraceMap<T>} traceMap The trace map.
2429
+ * @returns {IterableIterator<TrackedReferences<T>>} The iterator to iterate property references.
2430
+ */
2431
+ *iteratePropertyReferences(node, traceMap) {
2432
+ yield* this._iteratePropertyReferences(node, [], traceMap);
2433
+ }
2434
+
2435
+ /**
2436
+ * Iterate the references for a given variable.
2437
+ * @private
2438
+ * @template T
2439
+ * @param {Variable} variable The variable to iterate that references.
2440
+ * @param {string[]} path The current path.
2441
+ * @param {TraceMapObject<T>} traceMap The trace map.
2442
+ * @param {boolean} shouldReport = The flag to report those references.
2443
+ * @returns {IterableIterator<TrackedReferences<T>>} The iterator to iterate references.
2444
+ */
2445
+ *_iterateVariableReferences(variable, path, traceMap, shouldReport) {
2446
+ if (this.variableStack.includes(variable)) {
2447
+ return
2448
+ }
2449
+ this.variableStack.push(variable);
2450
+ try {
2451
+ for (const reference of variable.references) {
2452
+ if (!reference.isRead()) {
2453
+ continue
2454
+ }
2455
+ const node = /** @type {RuleNode & Identifier} */ (
2456
+ reference.identifier
2457
+ );
2458
+
2459
+ if (shouldReport && traceMap[READ]) {
2460
+ yield { node, path, type: READ, info: traceMap[READ] };
2461
+ }
2462
+ yield* this._iteratePropertyReferences(node, path, traceMap);
2463
+ }
2464
+ } finally {
2465
+ this.variableStack.pop();
2466
+ }
2467
+ }
2468
+
2469
+ /**
2470
+ * Iterate the references for a given AST node.
2471
+ * @private
2472
+ * @template T
2473
+ * @param {Expression} rootNode The AST node to iterate references.
2474
+ * @param {string[]} path The current path.
2475
+ * @param {TraceMapObject<T>} traceMap The trace map.
2476
+ * @returns {IterableIterator<TrackedReferences<T>>} The iterator to iterate references.
2477
+ */
2478
+ //eslint-disable-next-line complexity
2479
+ *_iteratePropertyReferences(rootNode, path, traceMap) {
2480
+ let node = rootNode;
2481
+ while (isPassThrough(node)) {
2482
+ node = node.parent;
2483
+ }
2484
+
2485
+ const parent = /** @type {RuleNode} */ (node).parent;
2486
+ if (!parent) {
2487
+ return
2488
+ }
2489
+ if (parent.type === "MemberExpression") {
2490
+ if (parent.object === node) {
2491
+ const key = getPropertyName(parent);
2492
+ if (key == null || !has(traceMap, key)) {
2493
+ return
2494
+ }
2495
+
2496
+ path = path.concat(key); //eslint-disable-line no-param-reassign
2497
+ const nextTraceMap = traceMap[key];
2498
+ if (nextTraceMap[READ]) {
2499
+ yield {
2500
+ node: parent,
2501
+ path,
2502
+ type: READ,
2503
+ info: nextTraceMap[READ],
2504
+ };
2505
+ }
2506
+ yield* this._iteratePropertyReferences(
2507
+ parent,
2508
+ path,
2509
+ nextTraceMap,
2510
+ );
2511
+ }
2512
+ return
2513
+ }
2514
+ if (parent.type === "CallExpression") {
2515
+ if (parent.callee === node && traceMap[CALL]) {
2516
+ yield { node: parent, path, type: CALL, info: traceMap[CALL] };
2517
+ }
2518
+ return
2519
+ }
2520
+ if (parent.type === "NewExpression") {
2521
+ if (parent.callee === node && traceMap[CONSTRUCT]) {
2522
+ yield {
2523
+ node: parent,
2524
+ path,
2525
+ type: CONSTRUCT,
2526
+ info: traceMap[CONSTRUCT],
2527
+ };
2528
+ }
2529
+ return
2530
+ }
2531
+ if (parent.type === "AssignmentExpression") {
2532
+ if (parent.right === node) {
2533
+ yield* this._iterateLhsReferences(parent.left, path, traceMap);
2534
+ yield* this._iteratePropertyReferences(parent, path, traceMap);
2535
+ }
2536
+ return
2537
+ }
2538
+ if (parent.type === "AssignmentPattern") {
2539
+ if (parent.right === node) {
2540
+ yield* this._iterateLhsReferences(parent.left, path, traceMap);
2541
+ }
2542
+ return
2543
+ }
2544
+ if (parent.type === "VariableDeclarator") {
2545
+ if (parent.init === node) {
2546
+ yield* this._iterateLhsReferences(parent.id, path, traceMap);
2547
+ }
2548
+ }
2549
+ }
2550
+
2551
+ /**
2552
+ * Iterate the references for a given Pattern node.
2553
+ * @private
2554
+ * @template T
2555
+ * @param {Pattern} patternNode The Pattern node to iterate references.
2556
+ * @param {string[]} path The current path.
2557
+ * @param {TraceMapObject<T>} traceMap The trace map.
2558
+ * @returns {IterableIterator<TrackedReferences<T>>} The iterator to iterate references.
2559
+ */
2560
+ *_iterateLhsReferences(patternNode, path, traceMap) {
2561
+ if (patternNode.type === "Identifier") {
2562
+ const variable = findVariable(this.globalScope, patternNode);
2563
+ if (variable != null) {
2564
+ yield* this._iterateVariableReferences(
2565
+ variable,
2566
+ path,
2567
+ traceMap,
2568
+ false,
2569
+ );
2570
+ }
2571
+ return
2572
+ }
2573
+ if (patternNode.type === "ObjectPattern") {
2574
+ for (const property of patternNode.properties) {
2575
+ const key = getPropertyName(
2576
+ /** @type {AssignmentProperty} */ (property),
2577
+ );
2578
+
2579
+ if (key == null || !has(traceMap, key)) {
2580
+ continue
2581
+ }
2582
+
2583
+ const nextPath = path.concat(key);
2584
+ const nextTraceMap = traceMap[key];
2585
+ if (nextTraceMap[READ]) {
2586
+ yield {
2587
+ node: /** @type {RuleNode} */ (property),
2588
+ path: nextPath,
2589
+ type: READ,
2590
+ info: nextTraceMap[READ],
2591
+ };
2592
+ }
2593
+ yield* this._iterateLhsReferences(
2594
+ /** @type {AssignmentProperty} */ (property).value,
2595
+ nextPath,
2596
+ nextTraceMap,
2597
+ );
2598
+ }
2599
+ return
2600
+ }
2601
+ if (patternNode.type === "AssignmentPattern") {
2602
+ yield* this._iterateLhsReferences(patternNode.left, path, traceMap);
2603
+ }
2604
+ }
2605
+
2606
+ /**
2607
+ * Iterate the references for a given ModuleSpecifier node.
2608
+ * @private
2609
+ * @template T
2610
+ * @param {ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier | ExportSpecifier} specifierNode The ModuleSpecifier node to iterate references.
2611
+ * @param {string[]} path The current path.
2612
+ * @param {TraceMapObject<T>} traceMap The trace map.
2613
+ * @returns {IterableIterator<TrackedReferences<T>>} The iterator to iterate references.
2614
+ */
2615
+ *_iterateImportReferences(specifierNode, path, traceMap) {
2616
+ const type = specifierNode.type;
2617
+
2618
+ if (type === "ImportSpecifier" || type === "ImportDefaultSpecifier") {
2619
+ const key =
2620
+ type === "ImportDefaultSpecifier"
2621
+ ? "default"
2622
+ : specifierNode.imported.type === "Identifier"
2623
+ ? specifierNode.imported.name
2624
+ : specifierNode.imported.value;
2625
+ if (!has(traceMap, key)) {
2626
+ return
2627
+ }
2628
+
2629
+ path = path.concat(key); //eslint-disable-line no-param-reassign
2630
+ const nextTraceMap = traceMap[key];
2631
+ if (nextTraceMap[READ]) {
2632
+ yield {
2633
+ node: /** @type {RuleNode} */ (specifierNode),
2634
+ path,
2635
+ type: READ,
2636
+ info: nextTraceMap[READ],
2637
+ };
2638
+ }
2639
+ yield* this._iterateVariableReferences(
2640
+ /** @type {Variable} */ (
2641
+ findVariable(this.globalScope, specifierNode.local)
2642
+ ),
2643
+ path,
2644
+ nextTraceMap,
2645
+ false,
2646
+ );
2647
+
2648
+ return
2649
+ }
2650
+
2651
+ if (type === "ImportNamespaceSpecifier") {
2652
+ yield* this._iterateVariableReferences(
2653
+ /** @type {Variable} */ (
2654
+ findVariable(this.globalScope, specifierNode.local)
2655
+ ),
2656
+ path,
2657
+ traceMap,
2658
+ false,
2659
+ );
2660
+ return
2661
+ }
2662
+
2663
+ if (type === "ExportSpecifier") {
2664
+ const key =
2665
+ specifierNode.local.type === "Identifier"
2666
+ ? specifierNode.local.name
2667
+ : specifierNode.local.value;
2668
+ if (!has(traceMap, key)) {
2669
+ return
2670
+ }
2671
+
2672
+ path = path.concat(key); //eslint-disable-line no-param-reassign
2673
+ const nextTraceMap = traceMap[key];
2674
+ if (nextTraceMap[READ]) {
2675
+ yield {
2676
+ node: /** @type {RuleNode} */ (specifierNode),
2677
+ path,
2678
+ type: READ,
2679
+ info: nextTraceMap[READ],
2680
+ };
2681
+ }
2682
+ }
2683
+ }
2684
+ }
2685
+
2686
+ ReferenceTracker.READ = READ;
2687
+ ReferenceTracker.CALL = CALL;
2688
+ ReferenceTracker.CONSTRUCT = CONSTRUCT;
2689
+ ReferenceTracker.ESM = ESM;
2690
+
2691
+ /**
2692
+ * This is a predicate function for Array#filter.
2693
+ * @param {string} name A name part.
2694
+ * @param {number} index The index of the name.
2695
+ * @returns {boolean} `false` if it's default.
2696
+ */
2697
+ function exceptDefault(name, index) {
2698
+ return !(index === 1 && name === "default")
2699
+ }
2700
+
2701
+ exports.CALL = CALL;
2702
+ exports.CONSTRUCT = CONSTRUCT;
2703
+ exports.READ = READ;
2704
+ exports.ReferenceTracker = ReferenceTracker;
2705
+ exports.findVariable = findVariable;
2706
+ exports.getFunctionHeadLocation = getFunctionHeadLocation;
2707
+ exports.getFunctionNameWithKind = getFunctionNameWithKind;
2708
+ exports.getPropertyName = getPropertyName;
2709
+ exports.getStaticValue = getStaticValue;
2710
+ exports.getStringIfConstant = getStringIfConstant;
2711
+ exports.hasSideEffect = hasSideEffect;
2712
+ exports.isArrowToken = isArrowToken;
2713
+ exports.isClosingBraceToken = isClosingBraceToken;
2714
+ exports.isClosingBracketToken = isClosingBracketToken;
2715
+ exports.isClosingParenToken = isClosingParenToken;
2716
+ exports.isColonToken = isColonToken;
2717
+ exports.isCommaToken = isCommaToken;
2718
+ exports.isCommentToken = isCommentToken;
2719
+ exports.isNotSemicolonToken = isNotSemicolonToken;
2720
+ exports.isOpeningBraceToken = isOpeningBraceToken;
2721
+ exports.isOpeningBracketToken = isOpeningBracketToken;
2722
+ exports.isOpeningParenToken = isOpeningParenToken;
2723
+ exports.isParenthesized = isParenthesized;
2724
+ exports.isSemicolonToken = isSemicolonToken;