.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint-utils / index.js
1 /*! @author Toru Nagashima <https://github.com/mysticatea> */
2 'use strict';
3
4 Object.defineProperty(exports, '__esModule', { value: true });
5
6 function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
7
8 var evk = _interopDefault(require('eslint-visitor-keys'));
9
10 /**
11  * Get the innermost scope which contains a given location.
12  * @param {Scope} initialScope The initial scope to search.
13  * @param {Node} node The location to search.
14  * @returns {Scope} The innermost scope.
15  */
16 function getInnermostScope(initialScope, node) {
17     const location = node.range[0];
18
19     let scope = initialScope;
20     let found = false;
21     do {
22         found = false;
23         for (const childScope of scope.childScopes) {
24             const range = childScope.block.range;
25
26             if (range[0] <= location && location < range[1]) {
27                 scope = childScope;
28                 found = true;
29                 break
30             }
31         }
32     } while (found)
33
34     return scope
35 }
36
37 /**
38  * Find the variable of a given name.
39  * @param {Scope} initialScope The scope to start finding.
40  * @param {string|Node} nameOrNode The variable name to find. If this is a Node object then it should be an Identifier node.
41  * @returns {Variable|null} The found variable or null.
42  */
43 function findVariable(initialScope, nameOrNode) {
44     let name = "";
45     let scope = initialScope;
46
47     if (typeof nameOrNode === "string") {
48         name = nameOrNode;
49     } else {
50         name = nameOrNode.name;
51         scope = getInnermostScope(scope, nameOrNode);
52     }
53
54     while (scope != null) {
55         const variable = scope.set.get(name);
56         if (variable != null) {
57             return variable
58         }
59         scope = scope.upper;
60     }
61
62     return null
63 }
64
65 /**
66  * Negate the result of `this` calling.
67  * @param {Token} token The token to check.
68  * @returns {boolean} `true` if the result of `this(token)` is `false`.
69  */
70 function negate0(token) {
71     return !this(token) //eslint-disable-line no-invalid-this
72 }
73
74 /**
75  * Creates the negate function of the given function.
76  * @param {function(Token):boolean} f - The function to negate.
77  * @returns {function(Token):boolean} Negated function.
78  */
79 function negate(f) {
80     return negate0.bind(f)
81 }
82
83 /**
84  * Checks if the given token is an arrow token or not.
85  * @param {Token} token - The token to check.
86  * @returns {boolean} `true` if the token is an arrow token.
87  */
88 function isArrowToken(token) {
89     return token.value === "=>" && token.type === "Punctuator"
90 }
91
92 /**
93  * Checks if the given token is a comma token or not.
94  * @param {Token} token - The token to check.
95  * @returns {boolean} `true` if the token is a comma token.
96  */
97 function isCommaToken(token) {
98     return token.value === "," && token.type === "Punctuator"
99 }
100
101 /**
102  * Checks if the given token is a semicolon token or not.
103  * @param {Token} token - The token to check.
104  * @returns {boolean} `true` if the token is a semicolon token.
105  */
106 function isSemicolonToken(token) {
107     return token.value === ";" && token.type === "Punctuator"
108 }
109
110 /**
111  * Checks if the given token is a colon token or not.
112  * @param {Token} token - The token to check.
113  * @returns {boolean} `true` if the token is a colon token.
114  */
115 function isColonToken(token) {
116     return token.value === ":" && token.type === "Punctuator"
117 }
118
119 /**
120  * Checks if the given token is an opening parenthesis token or not.
121  * @param {Token} token - The token to check.
122  * @returns {boolean} `true` if the token is an opening parenthesis token.
123  */
124 function isOpeningParenToken(token) {
125     return token.value === "(" && token.type === "Punctuator"
126 }
127
128 /**
129  * Checks if the given token is a closing parenthesis token or not.
130  * @param {Token} token - The token to check.
131  * @returns {boolean} `true` if the token is a closing parenthesis token.
132  */
133 function isClosingParenToken(token) {
134     return token.value === ")" && token.type === "Punctuator"
135 }
136
137 /**
138  * Checks if the given token is an opening square bracket token or not.
139  * @param {Token} token - The token to check.
140  * @returns {boolean} `true` if the token is an opening square bracket token.
141  */
142 function isOpeningBracketToken(token) {
143     return token.value === "[" && token.type === "Punctuator"
144 }
145
146 /**
147  * Checks if the given token is a closing square bracket token or not.
148  * @param {Token} token - The token to check.
149  * @returns {boolean} `true` if the token is a closing square bracket token.
150  */
151 function isClosingBracketToken(token) {
152     return token.value === "]" && token.type === "Punctuator"
153 }
154
155 /**
156  * Checks if the given token is an opening brace token or not.
157  * @param {Token} token - The token to check.
158  * @returns {boolean} `true` if the token is an opening brace token.
159  */
160 function isOpeningBraceToken(token) {
161     return token.value === "{" && token.type === "Punctuator"
162 }
163
164 /**
165  * Checks if the given token is a closing brace token or not.
166  * @param {Token} token - The token to check.
167  * @returns {boolean} `true` if the token is a closing brace token.
168  */
169 function isClosingBraceToken(token) {
170     return token.value === "}" && token.type === "Punctuator"
171 }
172
173 /**
174  * Checks if the given token is a comment token or not.
175  * @param {Token} token - The token to check.
176  * @returns {boolean} `true` if the token is a comment token.
177  */
178 function isCommentToken(token) {
179     return (
180         token.type === "Line" ||
181         token.type === "Block" ||
182         token.type === "Shebang"
183     )
184 }
185
186 const isNotArrowToken = negate(isArrowToken);
187 const isNotCommaToken = negate(isCommaToken);
188 const isNotSemicolonToken = negate(isSemicolonToken);
189 const isNotColonToken = negate(isColonToken);
190 const isNotOpeningParenToken = negate(isOpeningParenToken);
191 const isNotClosingParenToken = negate(isClosingParenToken);
192 const isNotOpeningBracketToken = negate(isOpeningBracketToken);
193 const isNotClosingBracketToken = negate(isClosingBracketToken);
194 const isNotOpeningBraceToken = negate(isOpeningBraceToken);
195 const isNotClosingBraceToken = negate(isClosingBraceToken);
196 const isNotCommentToken = negate(isCommentToken);
197
198 /**
199  * Get the `(` token of the given function node.
200  * @param {Node} node - The function node to get.
201  * @param {SourceCode} sourceCode - The source code object to get tokens.
202  * @returns {Token} `(` token.
203  */
204 function getOpeningParenOfParams(node, sourceCode) {
205     return node.id
206         ? sourceCode.getTokenAfter(node.id, isOpeningParenToken)
207         : sourceCode.getFirstToken(node, isOpeningParenToken)
208 }
209
210 /**
211  * Get the location of the given function node for reporting.
212  * @param {Node} node - The function node to get.
213  * @param {SourceCode} sourceCode - The source code object to get tokens.
214  * @returns {string} The location of the function node for reporting.
215  */
216 function getFunctionHeadLocation(node, sourceCode) {
217     const parent = node.parent;
218     let start = null;
219     let end = null;
220
221     if (node.type === "ArrowFunctionExpression") {
222         const arrowToken = sourceCode.getTokenBefore(node.body, isArrowToken);
223
224         start = arrowToken.loc.start;
225         end = arrowToken.loc.end;
226     } else if (
227         parent.type === "Property" ||
228         parent.type === "MethodDefinition"
229     ) {
230         start = parent.loc.start;
231         end = getOpeningParenOfParams(node, sourceCode).loc.start;
232     } else {
233         start = node.loc.start;
234         end = getOpeningParenOfParams(node, sourceCode).loc.start;
235     }
236
237     return {
238         start: Object.assign({}, start),
239         end: Object.assign({}, end),
240     }
241 }
242
243 /* globals BigInt, globalThis, global, self, window */
244
245 const globalObject =
246     typeof globalThis !== "undefined"
247         ? globalThis
248         : typeof self !== "undefined"
249         ? self
250         : typeof window !== "undefined"
251         ? window
252         : typeof global !== "undefined"
253         ? global
254         : {};
255
256 const builtinNames = Object.freeze(
257     new Set([
258         "Array",
259         "ArrayBuffer",
260         "BigInt",
261         "BigInt64Array",
262         "BigUint64Array",
263         "Boolean",
264         "DataView",
265         "Date",
266         "decodeURI",
267         "decodeURIComponent",
268         "encodeURI",
269         "encodeURIComponent",
270         "escape",
271         "Float32Array",
272         "Float64Array",
273         "Function",
274         "Infinity",
275         "Int16Array",
276         "Int32Array",
277         "Int8Array",
278         "isFinite",
279         "isNaN",
280         "isPrototypeOf",
281         "JSON",
282         "Map",
283         "Math",
284         "NaN",
285         "Number",
286         "Object",
287         "parseFloat",
288         "parseInt",
289         "Promise",
290         "Proxy",
291         "Reflect",
292         "RegExp",
293         "Set",
294         "String",
295         "Symbol",
296         "Uint16Array",
297         "Uint32Array",
298         "Uint8Array",
299         "Uint8ClampedArray",
300         "undefined",
301         "unescape",
302         "WeakMap",
303         "WeakSet",
304     ])
305 );
306 const callAllowed = new Set(
307     [
308         Array.isArray,
309         typeof BigInt === "function" ? BigInt : undefined,
310         Boolean,
311         Date,
312         Date.parse,
313         decodeURI,
314         decodeURIComponent,
315         encodeURI,
316         encodeURIComponent,
317         escape,
318         isFinite,
319         isNaN,
320         isPrototypeOf,
321         ...Object.getOwnPropertyNames(Math)
322             .map(k => Math[k])
323             .filter(f => typeof f === "function"),
324         Number,
325         Number.isFinite,
326         Number.isNaN,
327         Number.parseFloat,
328         Number.parseInt,
329         Object,
330         Object.entries,
331         Object.is,
332         Object.isExtensible,
333         Object.isFrozen,
334         Object.isSealed,
335         Object.keys,
336         Object.values,
337         parseFloat,
338         parseInt,
339         RegExp,
340         String,
341         String.fromCharCode,
342         String.fromCodePoint,
343         String.raw,
344         Symbol,
345         Symbol.for,
346         Symbol.keyFor,
347         unescape,
348     ].filter(f => typeof f === "function")
349 );
350 const callPassThrough = new Set([
351     Object.freeze,
352     Object.preventExtensions,
353     Object.seal,
354 ]);
355
356 /**
357  * Get the property descriptor.
358  * @param {object} object The object to get.
359  * @param {string|number|symbol} name The property name to get.
360  */
361 function getPropertyDescriptor(object, name) {
362     let x = object;
363     while ((typeof x === "object" || typeof x === "function") && x !== null) {
364         const d = Object.getOwnPropertyDescriptor(x, name);
365         if (d) {
366             return d
367         }
368         x = Object.getPrototypeOf(x);
369     }
370     return null
371 }
372
373 /**
374  * Check if a property is getter or not.
375  * @param {object} object The object to check.
376  * @param {string|number|symbol} name The property name to check.
377  */
378 function isGetter(object, name) {
379     const d = getPropertyDescriptor(object, name);
380     return d != null && d.get != null
381 }
382
383 /**
384  * Get the element values of a given node list.
385  * @param {Node[]} nodeList The node list to get values.
386  * @param {Scope|undefined} initialScope The initial scope to find variables.
387  * @returns {any[]|null} The value list if all nodes are constant. Otherwise, null.
388  */
389 function getElementValues(nodeList, initialScope) {
390     const valueList = [];
391
392     for (let i = 0; i < nodeList.length; ++i) {
393         const elementNode = nodeList[i];
394
395         if (elementNode == null) {
396             valueList.length = i + 1;
397         } else if (elementNode.type === "SpreadElement") {
398             const argument = getStaticValueR(elementNode.argument, initialScope);
399             if (argument == null) {
400                 return null
401             }
402             valueList.push(...argument.value);
403         } else {
404             const element = getStaticValueR(elementNode, initialScope);
405             if (element == null) {
406                 return null
407             }
408             valueList.push(element.value);
409         }
410     }
411
412     return valueList
413 }
414
415 const operations = Object.freeze({
416     ArrayExpression(node, initialScope) {
417         const elements = getElementValues(node.elements, initialScope);
418         return elements != null ? { value: elements } : null
419     },
420
421     AssignmentExpression(node, initialScope) {
422         if (node.operator === "=") {
423             return getStaticValueR(node.right, initialScope)
424         }
425         return null
426     },
427
428     //eslint-disable-next-line complexity
429     BinaryExpression(node, initialScope) {
430         if (node.operator === "in" || node.operator === "instanceof") {
431             // Not supported.
432             return null
433         }
434
435         const left = getStaticValueR(node.left, initialScope);
436         const right = getStaticValueR(node.right, initialScope);
437         if (left != null && right != null) {
438             switch (node.operator) {
439                 case "==":
440                     return { value: left.value == right.value } //eslint-disable-line eqeqeq
441                 case "!=":
442                     return { value: left.value != right.value } //eslint-disable-line eqeqeq
443                 case "===":
444                     return { value: left.value === right.value }
445                 case "!==":
446                     return { value: left.value !== right.value }
447                 case "<":
448                     return { value: left.value < right.value }
449                 case "<=":
450                     return { value: left.value <= right.value }
451                 case ">":
452                     return { value: left.value > right.value }
453                 case ">=":
454                     return { value: left.value >= right.value }
455                 case "<<":
456                     return { value: left.value << right.value }
457                 case ">>":
458                     return { value: left.value >> right.value }
459                 case ">>>":
460                     return { value: left.value >>> right.value }
461                 case "+":
462                     return { value: left.value + right.value }
463                 case "-":
464                     return { value: left.value - right.value }
465                 case "*":
466                     return { value: left.value * right.value }
467                 case "/":
468                     return { value: left.value / right.value }
469                 case "%":
470                     return { value: left.value % right.value }
471                 case "**":
472                     return { value: Math.pow(left.value, right.value) }
473                 case "|":
474                     return { value: left.value | right.value }
475                 case "^":
476                     return { value: left.value ^ right.value }
477                 case "&":
478                     return { value: left.value & right.value }
479
480                 // no default
481             }
482         }
483
484         return null
485     },
486
487     CallExpression(node, initialScope) {
488         const calleeNode = node.callee;
489         const args = getElementValues(node.arguments, initialScope);
490
491         if (args != null) {
492             if (calleeNode.type === "MemberExpression") {
493                 const object = getStaticValueR(calleeNode.object, initialScope);
494                 if (object != null) {
495                     if (
496                         object.value == null &&
497                         (object.optional || node.optional)
498                     ) {
499                         return { value: undefined, optional: true }
500                     }
501                     const property = calleeNode.computed
502                         ? getStaticValueR(calleeNode.property, initialScope)
503                         : { value: calleeNode.property.name };
504
505                     if (property != null) {
506                         const receiver = object.value;
507                         const methodName = property.value;
508                         if (callAllowed.has(receiver[methodName])) {
509                             return { value: receiver[methodName](...args) }
510                         }
511                         if (callPassThrough.has(receiver[methodName])) {
512                             return { value: args[0] }
513                         }
514                     }
515                 }
516             } else {
517                 const callee = getStaticValueR(calleeNode, initialScope);
518                 if (callee != null) {
519                     if (callee.value == null && node.optional) {
520                         return { value: undefined, optional: true }
521                     }
522                     const func = callee.value;
523                     if (callAllowed.has(func)) {
524                         return { value: func(...args) }
525                     }
526                     if (callPassThrough.has(func)) {
527                         return { value: args[0] }
528                     }
529                 }
530             }
531         }
532
533         return null
534     },
535
536     ConditionalExpression(node, initialScope) {
537         const test = getStaticValueR(node.test, initialScope);
538         if (test != null) {
539             return test.value
540                 ? getStaticValueR(node.consequent, initialScope)
541                 : getStaticValueR(node.alternate, initialScope)
542         }
543         return null
544     },
545
546     ExpressionStatement(node, initialScope) {
547         return getStaticValueR(node.expression, initialScope)
548     },
549
550     Identifier(node, initialScope) {
551         if (initialScope != null) {
552             const variable = findVariable(initialScope, node);
553
554             // Built-in globals.
555             if (
556                 variable != null &&
557                 variable.defs.length === 0 &&
558                 builtinNames.has(variable.name) &&
559                 variable.name in globalObject
560             ) {
561                 return { value: globalObject[variable.name] }
562             }
563
564             // Constants.
565             if (variable != null && variable.defs.length === 1) {
566                 const def = variable.defs[0];
567                 if (
568                     def.parent &&
569                     def.parent.kind === "const" &&
570                     // TODO(mysticatea): don't support destructuring here.
571                     def.node.id.type === "Identifier"
572                 ) {
573                     return getStaticValueR(def.node.init, initialScope)
574                 }
575             }
576         }
577         return null
578     },
579
580     Literal(node) {
581         //istanbul ignore if : this is implementation-specific behavior.
582         if ((node.regex != null || node.bigint != null) && node.value == null) {
583             // It was a RegExp/BigInt literal, but Node.js didn't support it.
584             return null
585         }
586         return { value: node.value }
587     },
588
589     LogicalExpression(node, initialScope) {
590         const left = getStaticValueR(node.left, initialScope);
591         if (left != null) {
592             if (
593                 (node.operator === "||" && Boolean(left.value) === true) ||
594                 (node.operator === "&&" && Boolean(left.value) === false) ||
595                 (node.operator === "??" && left.value != null)
596             ) {
597                 return left
598             }
599
600             const right = getStaticValueR(node.right, initialScope);
601             if (right != null) {
602                 return right
603             }
604         }
605
606         return null
607     },
608
609     MemberExpression(node, initialScope) {
610         const object = getStaticValueR(node.object, initialScope);
611         if (object != null) {
612             if (object.value == null && (object.optional || node.optional)) {
613                 return { value: undefined, optional: true }
614             }
615             const property = node.computed
616                 ? getStaticValueR(node.property, initialScope)
617                 : { value: node.property.name };
618
619             if (property != null && !isGetter(object.value, property.value)) {
620                 return { value: object.value[property.value] }
621             }
622         }
623         return null
624     },
625
626     ChainExpression(node, initialScope) {
627         const expression = getStaticValueR(node.expression, initialScope);
628         if (expression != null) {
629             return { value: expression.value }
630         }
631         return null
632     },
633
634     NewExpression(node, initialScope) {
635         const callee = getStaticValueR(node.callee, initialScope);
636         const args = getElementValues(node.arguments, initialScope);
637
638         if (callee != null && args != null) {
639             const Func = callee.value;
640             if (callAllowed.has(Func)) {
641                 return { value: new Func(...args) }
642             }
643         }
644
645         return null
646     },
647
648     ObjectExpression(node, initialScope) {
649         const object = {};
650
651         for (const propertyNode of node.properties) {
652             if (propertyNode.type === "Property") {
653                 if (propertyNode.kind !== "init") {
654                     return null
655                 }
656                 const key = propertyNode.computed
657                     ? getStaticValueR(propertyNode.key, initialScope)
658                     : { value: propertyNode.key.name };
659                 const value = getStaticValueR(propertyNode.value, initialScope);
660                 if (key == null || value == null) {
661                     return null
662                 }
663                 object[key.value] = value.value;
664             } else if (
665                 propertyNode.type === "SpreadElement" ||
666                 propertyNode.type === "ExperimentalSpreadProperty"
667             ) {
668                 const argument = getStaticValueR(
669                     propertyNode.argument,
670                     initialScope
671                 );
672                 if (argument == null) {
673                     return null
674                 }
675                 Object.assign(object, argument.value);
676             } else {
677                 return null
678             }
679         }
680
681         return { value: object }
682     },
683
684     SequenceExpression(node, initialScope) {
685         const last = node.expressions[node.expressions.length - 1];
686         return getStaticValueR(last, initialScope)
687     },
688
689     TaggedTemplateExpression(node, initialScope) {
690         const tag = getStaticValueR(node.tag, initialScope);
691         const expressions = getElementValues(
692             node.quasi.expressions,
693             initialScope
694         );
695
696         if (tag != null && expressions != null) {
697             const func = tag.value;
698             const strings = node.quasi.quasis.map(q => q.value.cooked);
699             strings.raw = node.quasi.quasis.map(q => q.value.raw);
700
701             if (func === String.raw) {
702                 return { value: func(strings, ...expressions) }
703             }
704         }
705
706         return null
707     },
708
709     TemplateLiteral(node, initialScope) {
710         const expressions = getElementValues(node.expressions, initialScope);
711         if (expressions != null) {
712             let value = node.quasis[0].value.cooked;
713             for (let i = 0; i < expressions.length; ++i) {
714                 value += expressions[i];
715                 value += node.quasis[i + 1].value.cooked;
716             }
717             return { value }
718         }
719         return null
720     },
721
722     UnaryExpression(node, initialScope) {
723         if (node.operator === "delete") {
724             // Not supported.
725             return null
726         }
727         if (node.operator === "void") {
728             return { value: undefined }
729         }
730
731         const arg = getStaticValueR(node.argument, initialScope);
732         if (arg != null) {
733             switch (node.operator) {
734                 case "-":
735                     return { value: -arg.value }
736                 case "+":
737                     return { value: +arg.value } //eslint-disable-line no-implicit-coercion
738                 case "!":
739                     return { value: !arg.value }
740                 case "~":
741                     return { value: ~arg.value }
742                 case "typeof":
743                     return { value: typeof arg.value }
744
745                 // no default
746             }
747         }
748
749         return null
750     },
751 });
752
753 /**
754  * Get the value of a given node if it's a static value.
755  * @param {Node} node The node to get.
756  * @param {Scope|undefined} initialScope The scope to start finding variable.
757  * @returns {{value:any}|{value:undefined,optional?:true}|null} The static value of the node, or `null`.
758  */
759 function getStaticValueR(node, initialScope) {
760     if (node != null && Object.hasOwnProperty.call(operations, node.type)) {
761         return operations[node.type](node, initialScope)
762     }
763     return null
764 }
765
766 /**
767  * Get the value of a given node if it's a static value.
768  * @param {Node} node The node to get.
769  * @param {Scope} [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.
770  * @returns {{value:any}|{value:undefined,optional?:true}|null} The static value of the node, or `null`.
771  */
772 function getStaticValue(node, initialScope = null) {
773     try {
774         return getStaticValueR(node, initialScope)
775     } catch (_error) {
776         return null
777     }
778 }
779
780 /**
781  * Get the value of a given node if it's a literal or a template literal.
782  * @param {Node} node The node to get.
783  * @param {Scope} [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.
784  * @returns {string|null} The value of the node, or `null`.
785  */
786 function getStringIfConstant(node, initialScope = null) {
787     // Handle the literals that the platform doesn't support natively.
788     if (node && node.type === "Literal" && node.value === null) {
789         if (node.regex) {
790             return `/${node.regex.pattern}/${node.regex.flags}`
791         }
792         if (node.bigint) {
793             return node.bigint
794         }
795     }
796
797     const evaluated = getStaticValue(node, initialScope);
798     return evaluated && String(evaluated.value)
799 }
800
801 /**
802  * Get the property name from a MemberExpression node or a Property node.
803  * @param {Node} node The node to get.
804  * @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.
805  * @returns {string|null} The property name of the node.
806  */
807 function getPropertyName(node, initialScope) {
808     switch (node.type) {
809         case "MemberExpression":
810             if (node.computed) {
811                 return getStringIfConstant(node.property, initialScope)
812             }
813             return node.property.name
814
815         case "Property":
816         case "MethodDefinition":
817             if (node.computed) {
818                 return getStringIfConstant(node.key, initialScope)
819             }
820             if (node.key.type === "Literal") {
821                 return String(node.key.value)
822             }
823             return node.key.name
824
825         // no default
826     }
827
828     return null
829 }
830
831 /**
832  * Get the name and kind of the given function node.
833  * @param {ASTNode} node - The function node to get.
834  * @returns {string} The name and kind of the function node.
835  */
836 function getFunctionNameWithKind(node) {
837     const parent = node.parent;
838     const tokens = [];
839
840     if (parent.type === "MethodDefinition" && parent.static) {
841         tokens.push("static");
842     }
843     if (node.async) {
844         tokens.push("async");
845     }
846     if (node.generator) {
847         tokens.push("generator");
848     }
849
850     if (node.type === "ArrowFunctionExpression") {
851         tokens.push("arrow", "function");
852     } else if (
853         parent.type === "Property" ||
854         parent.type === "MethodDefinition"
855     ) {
856         if (parent.kind === "constructor") {
857             return "constructor"
858         }
859         if (parent.kind === "get") {
860             tokens.push("getter");
861         } else if (parent.kind === "set") {
862             tokens.push("setter");
863         } else {
864             tokens.push("method");
865         }
866     } else {
867         tokens.push("function");
868     }
869
870     if (node.id) {
871         tokens.push(`'${node.id.name}'`);
872     } else {
873         const name = getPropertyName(parent);
874
875         if (name) {
876             tokens.push(`'${name}'`);
877         }
878     }
879
880     if (node.type === "ArrowFunctionExpression") {
881         if (
882             parent.type === "VariableDeclarator" &&
883             parent.id &&
884             parent.id.type === "Identifier"
885         ) {
886             tokens.push(`'${parent.id.name}'`);
887         }
888         if (
889             parent.type === "AssignmentExpression" &&
890             parent.left &&
891             parent.left.type === "Identifier"
892         ) {
893             tokens.push(`'${parent.left.name}'`);
894         }
895     }
896
897     return tokens.join(" ")
898 }
899
900 const typeConversionBinaryOps = Object.freeze(
901     new Set([
902         "==",
903         "!=",
904         "<",
905         "<=",
906         ">",
907         ">=",
908         "<<",
909         ">>",
910         ">>>",
911         "+",
912         "-",
913         "*",
914         "/",
915         "%",
916         "|",
917         "^",
918         "&",
919         "in",
920     ])
921 );
922 const typeConversionUnaryOps = Object.freeze(new Set(["-", "+", "!", "~"]));
923
924 /**
925  * Check whether the given value is an ASTNode or not.
926  * @param {any} x The value to check.
927  * @returns {boolean} `true` if the value is an ASTNode.
928  */
929 function isNode(x) {
930     return x !== null && typeof x === "object" && typeof x.type === "string"
931 }
932
933 const visitor = Object.freeze(
934     Object.assign(Object.create(null), {
935         $visit(node, options, visitorKeys) {
936             const { type } = node;
937
938             if (typeof this[type] === "function") {
939                 return this[type](node, options, visitorKeys)
940             }
941
942             return this.$visitChildren(node, options, visitorKeys)
943         },
944
945         $visitChildren(node, options, visitorKeys) {
946             const { type } = node;
947
948             for (const key of visitorKeys[type] || evk.getKeys(node)) {
949                 const value = node[key];
950
951                 if (Array.isArray(value)) {
952                     for (const element of value) {
953                         if (
954                             isNode(element) &&
955                             this.$visit(element, options, visitorKeys)
956                         ) {
957                             return true
958                         }
959                     }
960                 } else if (
961                     isNode(value) &&
962                     this.$visit(value, options, visitorKeys)
963                 ) {
964                     return true
965                 }
966             }
967
968             return false
969         },
970
971         ArrowFunctionExpression() {
972             return false
973         },
974         AssignmentExpression() {
975             return true
976         },
977         AwaitExpression() {
978             return true
979         },
980         BinaryExpression(node, options, visitorKeys) {
981             if (
982                 options.considerImplicitTypeConversion &&
983                 typeConversionBinaryOps.has(node.operator) &&
984                 (node.left.type !== "Literal" || node.right.type !== "Literal")
985             ) {
986                 return true
987             }
988             return this.$visitChildren(node, options, visitorKeys)
989         },
990         CallExpression() {
991             return true
992         },
993         FunctionExpression() {
994             return false
995         },
996         ImportExpression() {
997             return true
998         },
999         MemberExpression(node, options, visitorKeys) {
1000             if (options.considerGetters) {
1001                 return true
1002             }
1003             if (
1004                 options.considerImplicitTypeConversion &&
1005                 node.computed &&
1006                 node.property.type !== "Literal"
1007             ) {
1008                 return true
1009             }
1010             return this.$visitChildren(node, options, visitorKeys)
1011         },
1012         MethodDefinition(node, options, visitorKeys) {
1013             if (
1014                 options.considerImplicitTypeConversion &&
1015                 node.computed &&
1016                 node.key.type !== "Literal"
1017             ) {
1018                 return true
1019             }
1020             return this.$visitChildren(node, options, visitorKeys)
1021         },
1022         NewExpression() {
1023             return true
1024         },
1025         Property(node, options, visitorKeys) {
1026             if (
1027                 options.considerImplicitTypeConversion &&
1028                 node.computed &&
1029                 node.key.type !== "Literal"
1030             ) {
1031                 return true
1032             }
1033             return this.$visitChildren(node, options, visitorKeys)
1034         },
1035         UnaryExpression(node, options, visitorKeys) {
1036             if (node.operator === "delete") {
1037                 return true
1038             }
1039             if (
1040                 options.considerImplicitTypeConversion &&
1041                 typeConversionUnaryOps.has(node.operator) &&
1042                 node.argument.type !== "Literal"
1043             ) {
1044                 return true
1045             }
1046             return this.$visitChildren(node, options, visitorKeys)
1047         },
1048         UpdateExpression() {
1049             return true
1050         },
1051         YieldExpression() {
1052             return true
1053         },
1054     })
1055 );
1056
1057 /**
1058  * Check whether a given node has any side effect or not.
1059  * @param {Node} node The node to get.
1060  * @param {SourceCode} sourceCode The source code object.
1061  * @param {object} [options] The option object.
1062  * @param {boolean} [options.considerGetters=false] If `true` then it considers member accesses as the node which has side effects.
1063  * @param {boolean} [options.considerImplicitTypeConversion=false] If `true` then it considers implicit type conversion as the node which has side effects.
1064  * @param {object} [options.visitorKeys=evk.KEYS] The keys to traverse nodes. Use `context.getSourceCode().visitorKeys`.
1065  * @returns {boolean} `true` if the node has a certain side effect.
1066  */
1067 function hasSideEffect(
1068     node,
1069     sourceCode,
1070     { considerGetters = false, considerImplicitTypeConversion = false } = {}
1071 ) {
1072     return visitor.$visit(
1073         node,
1074         { considerGetters, considerImplicitTypeConversion },
1075         sourceCode.visitorKeys || evk.KEYS
1076     )
1077 }
1078
1079 /**
1080  * Get the left parenthesis of the parent node syntax if it exists.
1081  * E.g., `if (a) {}` then the `(`.
1082  * @param {Node} node The AST node to check.
1083  * @param {SourceCode} sourceCode The source code object to get tokens.
1084  * @returns {Token|null} The left parenthesis of the parent node syntax
1085  */
1086 function getParentSyntaxParen(node, sourceCode) {
1087     const parent = node.parent;
1088
1089     switch (parent.type) {
1090         case "CallExpression":
1091         case "NewExpression":
1092             if (parent.arguments.length === 1 && parent.arguments[0] === node) {
1093                 return sourceCode.getTokenAfter(
1094                     parent.callee,
1095                     isOpeningParenToken
1096                 )
1097             }
1098             return null
1099
1100         case "DoWhileStatement":
1101             if (parent.test === node) {
1102                 return sourceCode.getTokenAfter(
1103                     parent.body,
1104                     isOpeningParenToken
1105                 )
1106             }
1107             return null
1108
1109         case "IfStatement":
1110         case "WhileStatement":
1111             if (parent.test === node) {
1112                 return sourceCode.getFirstToken(parent, 1)
1113             }
1114             return null
1115
1116         case "ImportExpression":
1117             if (parent.source === node) {
1118                 return sourceCode.getFirstToken(parent, 1)
1119             }
1120             return null
1121
1122         case "SwitchStatement":
1123             if (parent.discriminant === node) {
1124                 return sourceCode.getFirstToken(parent, 1)
1125             }
1126             return null
1127
1128         case "WithStatement":
1129             if (parent.object === node) {
1130                 return sourceCode.getFirstToken(parent, 1)
1131             }
1132             return null
1133
1134         default:
1135             return null
1136     }
1137 }
1138
1139 /**
1140  * Check whether a given node is parenthesized or not.
1141  * @param {number} times The number of parantheses.
1142  * @param {Node} node The AST node to check.
1143  * @param {SourceCode} sourceCode The source code object to get tokens.
1144  * @returns {boolean} `true` if the node is parenthesized the given times.
1145  */
1146 /**
1147  * Check whether a given node is parenthesized or not.
1148  * @param {Node} node The AST node to check.
1149  * @param {SourceCode} sourceCode The source code object to get tokens.
1150  * @returns {boolean} `true` if the node is parenthesized.
1151  */
1152 function isParenthesized(
1153     timesOrNode,
1154     nodeOrSourceCode,
1155     optionalSourceCode
1156 ) {
1157     let times, node, sourceCode, maybeLeftParen, maybeRightParen;
1158     if (typeof timesOrNode === "number") {
1159         times = timesOrNode | 0;
1160         node = nodeOrSourceCode;
1161         sourceCode = optionalSourceCode;
1162         if (!(times >= 1)) {
1163             throw new TypeError("'times' should be a positive integer.")
1164         }
1165     } else {
1166         times = 1;
1167         node = timesOrNode;
1168         sourceCode = nodeOrSourceCode;
1169     }
1170
1171     if (node == null) {
1172         return false
1173     }
1174
1175     maybeLeftParen = maybeRightParen = node;
1176     do {
1177         maybeLeftParen = sourceCode.getTokenBefore(maybeLeftParen);
1178         maybeRightParen = sourceCode.getTokenAfter(maybeRightParen);
1179     } while (
1180         maybeLeftParen != null &&
1181         maybeRightParen != null &&
1182         isOpeningParenToken(maybeLeftParen) &&
1183         isClosingParenToken(maybeRightParen) &&
1184         // Avoid false positive such as `if (a) {}`
1185         maybeLeftParen !== getParentSyntaxParen(node, sourceCode) &&
1186         --times > 0
1187     )
1188
1189     return times === 0
1190 }
1191
1192 /**
1193  * @author Toru Nagashima <https://github.com/mysticatea>
1194  * See LICENSE file in root directory for full license.
1195  */
1196
1197 const placeholder = /\$(?:[$&`']|[1-9][0-9]?)/gu;
1198
1199 /** @type {WeakMap<PatternMatcher, {pattern:RegExp,escaped:boolean}>} */
1200 const internal = new WeakMap();
1201
1202 /**
1203  * Check whether a given character is escaped or not.
1204  * @param {string} str The string to check.
1205  * @param {number} index The location of the character to check.
1206  * @returns {boolean} `true` if the character is escaped.
1207  */
1208 function isEscaped(str, index) {
1209     let escaped = false;
1210     for (let i = index - 1; i >= 0 && str.charCodeAt(i) === 0x5c; --i) {
1211         escaped = !escaped;
1212     }
1213     return escaped
1214 }
1215
1216 /**
1217  * Replace a given string by a given matcher.
1218  * @param {PatternMatcher} matcher The pattern matcher.
1219  * @param {string} str The string to be replaced.
1220  * @param {string} replacement The new substring to replace each matched part.
1221  * @returns {string} The replaced string.
1222  */
1223 function replaceS(matcher, str, replacement) {
1224     const chunks = [];
1225     let index = 0;
1226
1227     /** @type {RegExpExecArray} */
1228     let match = null;
1229
1230     /**
1231      * @param {string} key The placeholder.
1232      * @returns {string} The replaced string.
1233      */
1234     function replacer(key) {
1235         switch (key) {
1236             case "$$":
1237                 return "$"
1238             case "$&":
1239                 return match[0]
1240             case "$`":
1241                 return str.slice(0, match.index)
1242             case "$'":
1243                 return str.slice(match.index + match[0].length)
1244             default: {
1245                 const i = key.slice(1);
1246                 if (i in match) {
1247                     return match[i]
1248                 }
1249                 return key
1250             }
1251         }
1252     }
1253
1254     for (match of matcher.execAll(str)) {
1255         chunks.push(str.slice(index, match.index));
1256         chunks.push(replacement.replace(placeholder, replacer));
1257         index = match.index + match[0].length;
1258     }
1259     chunks.push(str.slice(index));
1260
1261     return chunks.join("")
1262 }
1263
1264 /**
1265  * Replace a given string by a given matcher.
1266  * @param {PatternMatcher} matcher The pattern matcher.
1267  * @param {string} str The string to be replaced.
1268  * @param {(...strs[])=>string} replace The function to replace each matched part.
1269  * @returns {string} The replaced string.
1270  */
1271 function replaceF(matcher, str, replace) {
1272     const chunks = [];
1273     let index = 0;
1274
1275     for (const match of matcher.execAll(str)) {
1276         chunks.push(str.slice(index, match.index));
1277         chunks.push(String(replace(...match, match.index, match.input)));
1278         index = match.index + match[0].length;
1279     }
1280     chunks.push(str.slice(index));
1281
1282     return chunks.join("")
1283 }
1284
1285 /**
1286  * The class to find patterns as considering escape sequences.
1287  */
1288 class PatternMatcher {
1289     /**
1290      * Initialize this matcher.
1291      * @param {RegExp} pattern The pattern to match.
1292      * @param {{escaped:boolean}} options The options.
1293      */
1294     constructor(pattern, { escaped = false } = {}) {
1295         if (!(pattern instanceof RegExp)) {
1296             throw new TypeError("'pattern' should be a RegExp instance.")
1297         }
1298         if (!pattern.flags.includes("g")) {
1299             throw new Error("'pattern' should contains 'g' flag.")
1300         }
1301
1302         internal.set(this, {
1303             pattern: new RegExp(pattern.source, pattern.flags),
1304             escaped: Boolean(escaped),
1305         });
1306     }
1307
1308     /**
1309      * Find the pattern in a given string.
1310      * @param {string} str The string to find.
1311      * @returns {IterableIterator<RegExpExecArray>} The iterator which iterate the matched information.
1312      */
1313     *execAll(str) {
1314         const { pattern, escaped } = internal.get(this);
1315         let match = null;
1316         let lastIndex = 0;
1317
1318         pattern.lastIndex = 0;
1319         while ((match = pattern.exec(str)) != null) {
1320             if (escaped || !isEscaped(str, match.index)) {
1321                 lastIndex = pattern.lastIndex;
1322                 yield match;
1323                 pattern.lastIndex = lastIndex;
1324             }
1325         }
1326     }
1327
1328     /**
1329      * Check whether the pattern is found in a given string.
1330      * @param {string} str The string to check.
1331      * @returns {boolean} `true` if the pattern was found in the string.
1332      */
1333     test(str) {
1334         const it = this.execAll(str);
1335         const ret = it.next();
1336         return !ret.done
1337     }
1338
1339     /**
1340      * Replace a given string.
1341      * @param {string} str The string to be replaced.
1342      * @param {(string|((...strs:string[])=>string))} replacer The string or function to replace. This is the same as the 2nd argument of `String.prototype.replace`.
1343      * @returns {string} The replaced string.
1344      */
1345     [Symbol.replace](str, replacer) {
1346         return typeof replacer === "function"
1347             ? replaceF(this, String(str), replacer)
1348             : replaceS(this, String(str), String(replacer))
1349     }
1350 }
1351
1352 const IMPORT_TYPE = /^(?:Import|Export(?:All|Default|Named))Declaration$/u;
1353 const has = Function.call.bind(Object.hasOwnProperty);
1354
1355 const READ = Symbol("read");
1356 const CALL = Symbol("call");
1357 const CONSTRUCT = Symbol("construct");
1358 const ESM = Symbol("esm");
1359
1360 const requireCall = { require: { [CALL]: true } };
1361
1362 /**
1363  * Check whether a given variable is modified or not.
1364  * @param {Variable} variable The variable to check.
1365  * @returns {boolean} `true` if the variable is modified.
1366  */
1367 function isModifiedGlobal(variable) {
1368     return (
1369         variable == null ||
1370         variable.defs.length !== 0 ||
1371         variable.references.some(r => r.isWrite())
1372     )
1373 }
1374
1375 /**
1376  * Check if the value of a given node is passed through to the parent syntax as-is.
1377  * For example, `a` and `b` in (`a || b` and `c ? a : b`) are passed through.
1378  * @param {Node} node A node to check.
1379  * @returns {boolean} `true` if the node is passed through.
1380  */
1381 function isPassThrough(node) {
1382     const parent = node.parent;
1383
1384     switch (parent && parent.type) {
1385         case "ConditionalExpression":
1386             return parent.consequent === node || parent.alternate === node
1387         case "LogicalExpression":
1388             return true
1389         case "SequenceExpression":
1390             return parent.expressions[parent.expressions.length - 1] === node
1391         case "ChainExpression":
1392             return true
1393
1394         default:
1395             return false
1396     }
1397 }
1398
1399 /**
1400  * The reference tracker.
1401  */
1402 class ReferenceTracker {
1403     /**
1404      * Initialize this tracker.
1405      * @param {Scope} globalScope The global scope.
1406      * @param {object} [options] The options.
1407      * @param {"legacy"|"strict"} [options.mode="strict"] The mode to determine the ImportDeclaration's behavior for CJS modules.
1408      * @param {string[]} [options.globalObjectNames=["global","globalThis","self","window"]] The variable names for Global Object.
1409      */
1410     constructor(
1411         globalScope,
1412         {
1413             mode = "strict",
1414             globalObjectNames = ["global", "globalThis", "self", "window"],
1415         } = {}
1416     ) {
1417         this.variableStack = [];
1418         this.globalScope = globalScope;
1419         this.mode = mode;
1420         this.globalObjectNames = globalObjectNames.slice(0);
1421     }
1422
1423     /**
1424      * Iterate the references of global variables.
1425      * @param {object} traceMap The trace map.
1426      * @returns {IterableIterator<{node:Node,path:string[],type:symbol,info:any}>} The iterator to iterate references.
1427      */
1428     *iterateGlobalReferences(traceMap) {
1429         for (const key of Object.keys(traceMap)) {
1430             const nextTraceMap = traceMap[key];
1431             const path = [key];
1432             const variable = this.globalScope.set.get(key);
1433
1434             if (isModifiedGlobal(variable)) {
1435                 continue
1436             }
1437
1438             yield* this._iterateVariableReferences(
1439                 variable,
1440                 path,
1441                 nextTraceMap,
1442                 true
1443             );
1444         }
1445
1446         for (const key of this.globalObjectNames) {
1447             const path = [];
1448             const variable = this.globalScope.set.get(key);
1449
1450             if (isModifiedGlobal(variable)) {
1451                 continue
1452             }
1453
1454             yield* this._iterateVariableReferences(
1455                 variable,
1456                 path,
1457                 traceMap,
1458                 false
1459             );
1460         }
1461     }
1462
1463     /**
1464      * Iterate the references of CommonJS modules.
1465      * @param {object} traceMap The trace map.
1466      * @returns {IterableIterator<{node:Node,path:string[],type:symbol,info:any}>} The iterator to iterate references.
1467      */
1468     *iterateCjsReferences(traceMap) {
1469         for (const { node } of this.iterateGlobalReferences(requireCall)) {
1470             const key = getStringIfConstant(node.arguments[0]);
1471             if (key == null || !has(traceMap, key)) {
1472                 continue
1473             }
1474
1475             const nextTraceMap = traceMap[key];
1476             const path = [key];
1477
1478             if (nextTraceMap[READ]) {
1479                 yield {
1480                     node,
1481                     path,
1482                     type: READ,
1483                     info: nextTraceMap[READ],
1484                 };
1485             }
1486             yield* this._iteratePropertyReferences(node, path, nextTraceMap);
1487         }
1488     }
1489
1490     /**
1491      * Iterate the references of ES modules.
1492      * @param {object} traceMap The trace map.
1493      * @returns {IterableIterator<{node:Node,path:string[],type:symbol,info:any}>} The iterator to iterate references.
1494      */
1495     *iterateEsmReferences(traceMap) {
1496         const programNode = this.globalScope.block;
1497
1498         for (const node of programNode.body) {
1499             if (!IMPORT_TYPE.test(node.type) || node.source == null) {
1500                 continue
1501             }
1502             const moduleId = node.source.value;
1503
1504             if (!has(traceMap, moduleId)) {
1505                 continue
1506             }
1507             const nextTraceMap = traceMap[moduleId];
1508             const path = [moduleId];
1509
1510             if (nextTraceMap[READ]) {
1511                 yield { node, path, type: READ, info: nextTraceMap[READ] };
1512             }
1513
1514             if (node.type === "ExportAllDeclaration") {
1515                 for (const key of Object.keys(nextTraceMap)) {
1516                     const exportTraceMap = nextTraceMap[key];
1517                     if (exportTraceMap[READ]) {
1518                         yield {
1519                             node,
1520                             path: path.concat(key),
1521                             type: READ,
1522                             info: exportTraceMap[READ],
1523                         };
1524                     }
1525                 }
1526             } else {
1527                 for (const specifier of node.specifiers) {
1528                     const esm = has(nextTraceMap, ESM);
1529                     const it = this._iterateImportReferences(
1530                         specifier,
1531                         path,
1532                         esm
1533                             ? nextTraceMap
1534                             : this.mode === "legacy"
1535                             ? Object.assign(
1536                                   { default: nextTraceMap },
1537                                   nextTraceMap
1538                               )
1539                             : { default: nextTraceMap }
1540                     );
1541
1542                     if (esm) {
1543                         yield* it;
1544                     } else {
1545                         for (const report of it) {
1546                             report.path = report.path.filter(exceptDefault);
1547                             if (
1548                                 report.path.length >= 2 ||
1549                                 report.type !== READ
1550                             ) {
1551                                 yield report;
1552                             }
1553                         }
1554                     }
1555                 }
1556             }
1557         }
1558     }
1559
1560     /**
1561      * Iterate the references for a given variable.
1562      * @param {Variable} variable The variable to iterate that references.
1563      * @param {string[]} path The current path.
1564      * @param {object} traceMap The trace map.
1565      * @param {boolean} shouldReport = The flag to report those references.
1566      * @returns {IterableIterator<{node:Node,path:string[],type:symbol,info:any}>} The iterator to iterate references.
1567      */
1568     *_iterateVariableReferences(variable, path, traceMap, shouldReport) {
1569         if (this.variableStack.includes(variable)) {
1570             return
1571         }
1572         this.variableStack.push(variable);
1573         try {
1574             for (const reference of variable.references) {
1575                 if (!reference.isRead()) {
1576                     continue
1577                 }
1578                 const node = reference.identifier;
1579
1580                 if (shouldReport && traceMap[READ]) {
1581                     yield { node, path, type: READ, info: traceMap[READ] };
1582                 }
1583                 yield* this._iteratePropertyReferences(node, path, traceMap);
1584             }
1585         } finally {
1586             this.variableStack.pop();
1587         }
1588     }
1589
1590     /**
1591      * Iterate the references for a given AST node.
1592      * @param rootNode The AST node to iterate references.
1593      * @param {string[]} path The current path.
1594      * @param {object} traceMap The trace map.
1595      * @returns {IterableIterator<{node:Node,path:string[],type:symbol,info:any}>} The iterator to iterate references.
1596      */
1597     //eslint-disable-next-line complexity
1598     *_iteratePropertyReferences(rootNode, path, traceMap) {
1599         let node = rootNode;
1600         while (isPassThrough(node)) {
1601             node = node.parent;
1602         }
1603
1604         const parent = node.parent;
1605         if (parent.type === "MemberExpression") {
1606             if (parent.object === node) {
1607                 const key = getPropertyName(parent);
1608                 if (key == null || !has(traceMap, key)) {
1609                     return
1610                 }
1611
1612                 path = path.concat(key); //eslint-disable-line no-param-reassign
1613                 const nextTraceMap = traceMap[key];
1614                 if (nextTraceMap[READ]) {
1615                     yield {
1616                         node: parent,
1617                         path,
1618                         type: READ,
1619                         info: nextTraceMap[READ],
1620                     };
1621                 }
1622                 yield* this._iteratePropertyReferences(
1623                     parent,
1624                     path,
1625                     nextTraceMap
1626                 );
1627             }
1628             return
1629         }
1630         if (parent.type === "CallExpression") {
1631             if (parent.callee === node && traceMap[CALL]) {
1632                 yield { node: parent, path, type: CALL, info: traceMap[CALL] };
1633             }
1634             return
1635         }
1636         if (parent.type === "NewExpression") {
1637             if (parent.callee === node && traceMap[CONSTRUCT]) {
1638                 yield {
1639                     node: parent,
1640                     path,
1641                     type: CONSTRUCT,
1642                     info: traceMap[CONSTRUCT],
1643                 };
1644             }
1645             return
1646         }
1647         if (parent.type === "AssignmentExpression") {
1648             if (parent.right === node) {
1649                 yield* this._iterateLhsReferences(parent.left, path, traceMap);
1650                 yield* this._iteratePropertyReferences(parent, path, traceMap);
1651             }
1652             return
1653         }
1654         if (parent.type === "AssignmentPattern") {
1655             if (parent.right === node) {
1656                 yield* this._iterateLhsReferences(parent.left, path, traceMap);
1657             }
1658             return
1659         }
1660         if (parent.type === "VariableDeclarator") {
1661             if (parent.init === node) {
1662                 yield* this._iterateLhsReferences(parent.id, path, traceMap);
1663             }
1664         }
1665     }
1666
1667     /**
1668      * Iterate the references for a given Pattern node.
1669      * @param {Node} patternNode The Pattern node to iterate references.
1670      * @param {string[]} path The current path.
1671      * @param {object} traceMap The trace map.
1672      * @returns {IterableIterator<{node:Node,path:string[],type:symbol,info:any}>} The iterator to iterate references.
1673      */
1674     *_iterateLhsReferences(patternNode, path, traceMap) {
1675         if (patternNode.type === "Identifier") {
1676             const variable = findVariable(this.globalScope, patternNode);
1677             if (variable != null) {
1678                 yield* this._iterateVariableReferences(
1679                     variable,
1680                     path,
1681                     traceMap,
1682                     false
1683                 );
1684             }
1685             return
1686         }
1687         if (patternNode.type === "ObjectPattern") {
1688             for (const property of patternNode.properties) {
1689                 const key = getPropertyName(property);
1690
1691                 if (key == null || !has(traceMap, key)) {
1692                     continue
1693                 }
1694
1695                 const nextPath = path.concat(key);
1696                 const nextTraceMap = traceMap[key];
1697                 if (nextTraceMap[READ]) {
1698                     yield {
1699                         node: property,
1700                         path: nextPath,
1701                         type: READ,
1702                         info: nextTraceMap[READ],
1703                     };
1704                 }
1705                 yield* this._iterateLhsReferences(
1706                     property.value,
1707                     nextPath,
1708                     nextTraceMap
1709                 );
1710             }
1711             return
1712         }
1713         if (patternNode.type === "AssignmentPattern") {
1714             yield* this._iterateLhsReferences(patternNode.left, path, traceMap);
1715         }
1716     }
1717
1718     /**
1719      * Iterate the references for a given ModuleSpecifier node.
1720      * @param {Node} specifierNode The ModuleSpecifier node to iterate references.
1721      * @param {string[]} path The current path.
1722      * @param {object} traceMap The trace map.
1723      * @returns {IterableIterator<{node:Node,path:string[],type:symbol,info:any}>} The iterator to iterate references.
1724      */
1725     *_iterateImportReferences(specifierNode, path, traceMap) {
1726         const type = specifierNode.type;
1727
1728         if (type === "ImportSpecifier" || type === "ImportDefaultSpecifier") {
1729             const key =
1730                 type === "ImportDefaultSpecifier"
1731                     ? "default"
1732                     : specifierNode.imported.name;
1733             if (!has(traceMap, key)) {
1734                 return
1735             }
1736
1737             path = path.concat(key); //eslint-disable-line no-param-reassign
1738             const nextTraceMap = traceMap[key];
1739             if (nextTraceMap[READ]) {
1740                 yield {
1741                     node: specifierNode,
1742                     path,
1743                     type: READ,
1744                     info: nextTraceMap[READ],
1745                 };
1746             }
1747             yield* this._iterateVariableReferences(
1748                 findVariable(this.globalScope, specifierNode.local),
1749                 path,
1750                 nextTraceMap,
1751                 false
1752             );
1753
1754             return
1755         }
1756
1757         if (type === "ImportNamespaceSpecifier") {
1758             yield* this._iterateVariableReferences(
1759                 findVariable(this.globalScope, specifierNode.local),
1760                 path,
1761                 traceMap,
1762                 false
1763             );
1764             return
1765         }
1766
1767         if (type === "ExportSpecifier") {
1768             const key = specifierNode.local.name;
1769             if (!has(traceMap, key)) {
1770                 return
1771             }
1772
1773             path = path.concat(key); //eslint-disable-line no-param-reassign
1774             const nextTraceMap = traceMap[key];
1775             if (nextTraceMap[READ]) {
1776                 yield {
1777                     node: specifierNode,
1778                     path,
1779                     type: READ,
1780                     info: nextTraceMap[READ],
1781                 };
1782             }
1783         }
1784     }
1785 }
1786
1787 ReferenceTracker.READ = READ;
1788 ReferenceTracker.CALL = CALL;
1789 ReferenceTracker.CONSTRUCT = CONSTRUCT;
1790 ReferenceTracker.ESM = ESM;
1791
1792 /**
1793  * This is a predicate function for Array#filter.
1794  * @param {string} name A name part.
1795  * @param {number} index The index of the name.
1796  * @returns {boolean} `false` if it's default.
1797  */
1798 function exceptDefault(name, index) {
1799     return !(index === 1 && name === "default")
1800 }
1801
1802 var index = {
1803     CALL,
1804     CONSTRUCT,
1805     ESM,
1806     findVariable,
1807     getFunctionHeadLocation,
1808     getFunctionNameWithKind,
1809     getInnermostScope,
1810     getPropertyName,
1811     getStaticValue,
1812     getStringIfConstant,
1813     hasSideEffect,
1814     isArrowToken,
1815     isClosingBraceToken,
1816     isClosingBracketToken,
1817     isClosingParenToken,
1818     isColonToken,
1819     isCommaToken,
1820     isCommentToken,
1821     isNotArrowToken,
1822     isNotClosingBraceToken,
1823     isNotClosingBracketToken,
1824     isNotClosingParenToken,
1825     isNotColonToken,
1826     isNotCommaToken,
1827     isNotCommentToken,
1828     isNotOpeningBraceToken,
1829     isNotOpeningBracketToken,
1830     isNotOpeningParenToken,
1831     isNotSemicolonToken,
1832     isOpeningBraceToken,
1833     isOpeningBracketToken,
1834     isOpeningParenToken,
1835     isParenthesized,
1836     isSemicolonToken,
1837     PatternMatcher,
1838     READ,
1839     ReferenceTracker,
1840 };
1841
1842 exports.CALL = CALL;
1843 exports.CONSTRUCT = CONSTRUCT;
1844 exports.ESM = ESM;
1845 exports.PatternMatcher = PatternMatcher;
1846 exports.READ = READ;
1847 exports.ReferenceTracker = ReferenceTracker;
1848 exports.default = index;
1849 exports.findVariable = findVariable;
1850 exports.getFunctionHeadLocation = getFunctionHeadLocation;
1851 exports.getFunctionNameWithKind = getFunctionNameWithKind;
1852 exports.getInnermostScope = getInnermostScope;
1853 exports.getPropertyName = getPropertyName;
1854 exports.getStaticValue = getStaticValue;
1855 exports.getStringIfConstant = getStringIfConstant;
1856 exports.hasSideEffect = hasSideEffect;
1857 exports.isArrowToken = isArrowToken;
1858 exports.isClosingBraceToken = isClosingBraceToken;
1859 exports.isClosingBracketToken = isClosingBracketToken;
1860 exports.isClosingParenToken = isClosingParenToken;
1861 exports.isColonToken = isColonToken;
1862 exports.isCommaToken = isCommaToken;
1863 exports.isCommentToken = isCommentToken;
1864 exports.isNotArrowToken = isNotArrowToken;
1865 exports.isNotClosingBraceToken = isNotClosingBraceToken;
1866 exports.isNotClosingBracketToken = isNotClosingBracketToken;
1867 exports.isNotClosingParenToken = isNotClosingParenToken;
1868 exports.isNotColonToken = isNotColonToken;
1869 exports.isNotCommaToken = isNotCommaToken;
1870 exports.isNotCommentToken = isNotCommentToken;
1871 exports.isNotOpeningBraceToken = isNotOpeningBraceToken;
1872 exports.isNotOpeningBracketToken = isNotOpeningBracketToken;
1873 exports.isNotOpeningParenToken = isNotOpeningParenToken;
1874 exports.isNotSemicolonToken = isNotSemicolonToken;
1875 exports.isOpeningBraceToken = isOpeningBraceToken;
1876 exports.isOpeningBracketToken = isOpeningBracketToken;
1877 exports.isOpeningParenToken = isOpeningParenToken;
1878 exports.isParenthesized = isParenthesized;
1879 exports.isSemicolonToken = isSemicolonToken;
1880 //# sourceMappingURL=index.js.map