massive update, probably broken
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / utils / ast-utils.js
1 /**
2  * @fileoverview Common utils for AST.
3  * @author Gyandeep Singh
4  */
5
6 "use strict";
7
8 //------------------------------------------------------------------------------
9 // Requirements
10 //------------------------------------------------------------------------------
11
12 const esutils = require("esutils");
13 const espree = require("espree");
14 const escapeRegExp = require("escape-string-regexp");
15 const {
16     breakableTypePattern,
17     createGlobalLinebreakMatcher,
18     lineBreakPattern,
19     shebangPattern
20 } = require("../../shared/ast-utils");
21
22 //------------------------------------------------------------------------------
23 // Helpers
24 //------------------------------------------------------------------------------
25
26 const anyFunctionPattern = /^(?:Function(?:Declaration|Expression)|ArrowFunctionExpression)$/u;
27 const anyLoopPattern = /^(?:DoWhile|For|ForIn|ForOf|While)Statement$/u;
28 const arrayOrTypedArrayPattern = /Array$/u;
29 const arrayMethodPattern = /^(?:every|filter|find|findIndex|forEach|map|some)$/u;
30 const bindOrCallOrApplyPattern = /^(?:bind|call|apply)$/u;
31 const thisTagPattern = /^[\s*]*@this/mu;
32
33
34 const COMMENTS_IGNORE_PATTERN = /^\s*(?:eslint|jshint\s+|jslint\s+|istanbul\s+|globals?\s+|exported\s+|jscs)/u;
35 const LINEBREAKS = new Set(["\r\n", "\r", "\n", "\u2028", "\u2029"]);
36
37 // A set of node types that can contain a list of statements
38 const STATEMENT_LIST_PARENTS = new Set(["Program", "BlockStatement", "SwitchCase"]);
39
40 const DECIMAL_INTEGER_PATTERN = /^(?:0|0[0-7]*[89]\d*|[1-9](?:_?\d)*)$/u;
41
42 // Tests the presence of at least one LegacyOctalEscapeSequence or NonOctalDecimalEscapeSequence in a raw string
43 const OCTAL_OR_NON_OCTAL_DECIMAL_ESCAPE_PATTERN = /^(?:[^\\]|\\.)*\\(?:[1-9]|0[0-9])/su;
44
45 const LOGICAL_ASSIGNMENT_OPERATORS = new Set(["&&=", "||=", "??="]);
46
47 /**
48  * Checks reference if is non initializer and writable.
49  * @param {Reference} reference A reference to check.
50  * @param {int} index The index of the reference in the references.
51  * @param {Reference[]} references The array that the reference belongs to.
52  * @returns {boolean} Success/Failure
53  * @private
54  */
55 function isModifyingReference(reference, index, references) {
56     const identifier = reference.identifier;
57
58     /*
59      * Destructuring assignments can have multiple default value, so
60      * possibly there are multiple writeable references for the same
61      * identifier.
62      */
63     const modifyingDifferentIdentifier = index === 0 ||
64         references[index - 1].identifier !== identifier;
65
66     return (identifier &&
67         reference.init === false &&
68         reference.isWrite() &&
69         modifyingDifferentIdentifier
70     );
71 }
72
73 /**
74  * Checks whether the given string starts with uppercase or not.
75  * @param {string} s The string to check.
76  * @returns {boolean} `true` if the string starts with uppercase.
77  */
78 function startsWithUpperCase(s) {
79     return s[0] !== s[0].toLocaleLowerCase();
80 }
81
82 /**
83  * Checks whether or not a node is a constructor.
84  * @param {ASTNode} node A function node to check.
85  * @returns {boolean} Whether or not a node is a constructor.
86  */
87 function isES5Constructor(node) {
88     return (node.id && startsWithUpperCase(node.id.name));
89 }
90
91 /**
92  * Finds a function node from ancestors of a node.
93  * @param {ASTNode} node A start node to find.
94  * @returns {Node|null} A found function node.
95  */
96 function getUpperFunction(node) {
97     for (let currentNode = node; currentNode; currentNode = currentNode.parent) {
98         if (anyFunctionPattern.test(currentNode.type)) {
99             return currentNode;
100         }
101     }
102     return null;
103 }
104
105 /**
106  * Checks whether a given node is a function node or not.
107  * The following types are function nodes:
108  *
109  * - ArrowFunctionExpression
110  * - FunctionDeclaration
111  * - FunctionExpression
112  * @param {ASTNode|null} node A node to check.
113  * @returns {boolean} `true` if the node is a function node.
114  */
115 function isFunction(node) {
116     return Boolean(node && anyFunctionPattern.test(node.type));
117 }
118
119 /**
120  * Checks whether a given node is a loop node or not.
121  * The following types are loop nodes:
122  *
123  * - DoWhileStatement
124  * - ForInStatement
125  * - ForOfStatement
126  * - ForStatement
127  * - WhileStatement
128  * @param {ASTNode|null} node A node to check.
129  * @returns {boolean} `true` if the node is a loop node.
130  */
131 function isLoop(node) {
132     return Boolean(node && anyLoopPattern.test(node.type));
133 }
134
135 /**
136  * Checks whether the given node is in a loop or not.
137  * @param {ASTNode} node The node to check.
138  * @returns {boolean} `true` if the node is in a loop.
139  */
140 function isInLoop(node) {
141     for (let currentNode = node; currentNode && !isFunction(currentNode); currentNode = currentNode.parent) {
142         if (isLoop(currentNode)) {
143             return true;
144         }
145     }
146
147     return false;
148 }
149
150 /**
151  * Determines whether the given node is a `null` literal.
152  * @param {ASTNode} node The node to check
153  * @returns {boolean} `true` if the node is a `null` literal
154  */
155 function isNullLiteral(node) {
156
157     /*
158      * Checking `node.value === null` does not guarantee that a literal is a null literal.
159      * When parsing values that cannot be represented in the current environment (e.g. unicode
160      * regexes in Node 4), `node.value` is set to `null` because it wouldn't be possible to
161      * set `node.value` to a unicode regex. To make sure a literal is actually `null`, check
162      * `node.regex` instead. Also see: https://github.com/eslint/eslint/issues/8020
163      */
164     return node.type === "Literal" && node.value === null && !node.regex && !node.bigint;
165 }
166
167 /**
168  * Checks whether or not a node is `null` or `undefined`.
169  * @param {ASTNode} node A node to check.
170  * @returns {boolean} Whether or not the node is a `null` or `undefined`.
171  * @public
172  */
173 function isNullOrUndefined(node) {
174     return (
175         isNullLiteral(node) ||
176         (node.type === "Identifier" && node.name === "undefined") ||
177         (node.type === "UnaryExpression" && node.operator === "void")
178     );
179 }
180
181 /**
182  * Checks whether or not a node is callee.
183  * @param {ASTNode} node A node to check.
184  * @returns {boolean} Whether or not the node is callee.
185  */
186 function isCallee(node) {
187     return node.parent.type === "CallExpression" && node.parent.callee === node;
188 }
189
190 /**
191  * Returns the result of the string conversion applied to the evaluated value of the given expression node,
192  * if it can be determined statically.
193  *
194  * This function returns a `string` value for all `Literal` nodes and simple `TemplateLiteral` nodes only.
195  * In all other cases, this function returns `null`.
196  * @param {ASTNode} node Expression node.
197  * @returns {string|null} String value if it can be determined. Otherwise, `null`.
198  */
199 function getStaticStringValue(node) {
200     switch (node.type) {
201         case "Literal":
202             if (node.value === null) {
203                 if (isNullLiteral(node)) {
204                     return String(node.value); // "null"
205                 }
206                 if (node.regex) {
207                     return `/${node.regex.pattern}/${node.regex.flags}`;
208                 }
209                 if (node.bigint) {
210                     return node.bigint;
211                 }
212
213                 // Otherwise, this is an unknown literal. The function will return null.
214
215             } else {
216                 return String(node.value);
217             }
218             break;
219         case "TemplateLiteral":
220             if (node.expressions.length === 0 && node.quasis.length === 1) {
221                 return node.quasis[0].value.cooked;
222             }
223             break;
224
225             // no default
226     }
227
228     return null;
229 }
230
231 /**
232  * Gets the property name of a given node.
233  * The node can be a MemberExpression, a Property, or a MethodDefinition.
234  *
235  * If the name is dynamic, this returns `null`.
236  *
237  * For examples:
238  *
239  *     a.b           // => "b"
240  *     a["b"]        // => "b"
241  *     a['b']        // => "b"
242  *     a[`b`]        // => "b"
243  *     a[100]        // => "100"
244  *     a[b]          // => null
245  *     a["a" + "b"]  // => null
246  *     a[tag`b`]     // => null
247  *     a[`${b}`]     // => null
248  *
249  *     let a = {b: 1}            // => "b"
250  *     let a = {["b"]: 1}        // => "b"
251  *     let a = {['b']: 1}        // => "b"
252  *     let a = {[`b`]: 1}        // => "b"
253  *     let a = {[100]: 1}        // => "100"
254  *     let a = {[b]: 1}          // => null
255  *     let a = {["a" + "b"]: 1}  // => null
256  *     let a = {[tag`b`]: 1}     // => null
257  *     let a = {[`${b}`]: 1}     // => null
258  * @param {ASTNode} node The node to get.
259  * @returns {string|null} The property name if static. Otherwise, null.
260  */
261 function getStaticPropertyName(node) {
262     let prop;
263
264     switch (node && node.type) {
265         case "ChainExpression":
266             return getStaticPropertyName(node.expression);
267
268         case "Property":
269         case "MethodDefinition":
270             prop = node.key;
271             break;
272
273         case "MemberExpression":
274             prop = node.property;
275             break;
276
277             // no default
278     }
279
280     if (prop) {
281         if (prop.type === "Identifier" && !node.computed) {
282             return prop.name;
283         }
284
285         return getStaticStringValue(prop);
286     }
287
288     return null;
289 }
290
291 /**
292  * Retrieve `ChainExpression#expression` value if the given node a `ChainExpression` node. Otherwise, pass through it.
293  * @param {ASTNode} node The node to address.
294  * @returns {ASTNode} The `ChainExpression#expression` value if the node is a `ChainExpression` node. Otherwise, the node.
295  */
296 function skipChainExpression(node) {
297     return node && node.type === "ChainExpression" ? node.expression : node;
298 }
299
300 /**
301  * Check if the `actual` is an expected value.
302  * @param {string} actual The string value to check.
303  * @param {string | RegExp} expected The expected string value or pattern.
304  * @returns {boolean} `true` if the `actual` is an expected value.
305  */
306 function checkText(actual, expected) {
307     return typeof expected === "string"
308         ? actual === expected
309         : expected.test(actual);
310 }
311
312 /**
313  * Check if a given node is an Identifier node with a given name.
314  * @param {ASTNode} node The node to check.
315  * @param {string | RegExp} name The expected name or the expected pattern of the object name.
316  * @returns {boolean} `true` if the node is an Identifier node with the name.
317  */
318 function isSpecificId(node, name) {
319     return node.type === "Identifier" && checkText(node.name, name);
320 }
321
322 /**
323  * Check if a given node is member access with a given object name and property name pair.
324  * This is regardless of optional or not.
325  * @param {ASTNode} node The node to check.
326  * @param {string | RegExp | null} objectName The expected name or the expected pattern of the object name. If this is nullish, this method doesn't check object.
327  * @param {string | RegExp | null} propertyName The expected name or the expected pattern of the property name. If this is nullish, this method doesn't check property.
328  * @returns {boolean} `true` if the node is member access with the object name and property name pair.
329  * The node is a `MemberExpression` or `ChainExpression`.
330  */
331 function isSpecificMemberAccess(node, objectName, propertyName) {
332     const checkNode = skipChainExpression(node);
333
334     if (checkNode.type !== "MemberExpression") {
335         return false;
336     }
337
338     if (objectName && !isSpecificId(checkNode.object, objectName)) {
339         return false;
340     }
341
342     if (propertyName) {
343         const actualPropertyName = getStaticPropertyName(checkNode);
344
345         if (typeof actualPropertyName !== "string" || !checkText(actualPropertyName, propertyName)) {
346             return false;
347         }
348     }
349
350     return true;
351 }
352
353 /**
354  * Check if two literal nodes are the same value.
355  * @param {ASTNode} left The Literal node to compare.
356  * @param {ASTNode} right The other Literal node to compare.
357  * @returns {boolean} `true` if the two literal nodes are the same value.
358  */
359 function equalLiteralValue(left, right) {
360
361     // RegExp literal.
362     if (left.regex || right.regex) {
363         return Boolean(
364             left.regex &&
365             right.regex &&
366             left.regex.pattern === right.regex.pattern &&
367             left.regex.flags === right.regex.flags
368         );
369     }
370
371     // BigInt literal.
372     if (left.bigint || right.bigint) {
373         return left.bigint === right.bigint;
374     }
375
376     return left.value === right.value;
377 }
378
379 /**
380  * Check if two expressions reference the same value. For example:
381  *     a = a
382  *     a.b = a.b
383  *     a[0] = a[0]
384  *     a['b'] = a['b']
385  * @param {ASTNode} left The left side of the comparison.
386  * @param {ASTNode} right The right side of the comparison.
387  * @param {boolean} [disableStaticComputedKey] Don't address `a.b` and `a["b"]` are the same if `true`. For backward compatibility.
388  * @returns {boolean} `true` if both sides match and reference the same value.
389  */
390 function isSameReference(left, right, disableStaticComputedKey = false) {
391     if (left.type !== right.type) {
392
393         // Handle `a.b` and `a?.b` are samely.
394         if (left.type === "ChainExpression") {
395             return isSameReference(left.expression, right, disableStaticComputedKey);
396         }
397         if (right.type === "ChainExpression") {
398             return isSameReference(left, right.expression, disableStaticComputedKey);
399         }
400
401         return false;
402     }
403
404     switch (left.type) {
405         case "Super":
406         case "ThisExpression":
407             return true;
408
409         case "Identifier":
410             return left.name === right.name;
411         case "Literal":
412             return equalLiteralValue(left, right);
413
414         case "ChainExpression":
415             return isSameReference(left.expression, right.expression, disableStaticComputedKey);
416
417         case "MemberExpression": {
418             if (!disableStaticComputedKey) {
419                 const nameA = getStaticPropertyName(left);
420
421                 // x.y = x["y"]
422                 if (nameA !== null) {
423                     return (
424                         isSameReference(left.object, right.object, disableStaticComputedKey) &&
425                         nameA === getStaticPropertyName(right)
426                     );
427                 }
428             }
429
430             /*
431              * x[0] = x[0]
432              * x[y] = x[y]
433              * x.y = x.y
434              */
435             return (
436                 left.computed === right.computed &&
437                 isSameReference(left.object, right.object, disableStaticComputedKey) &&
438                 isSameReference(left.property, right.property, disableStaticComputedKey)
439             );
440         }
441
442         default:
443             return false;
444     }
445 }
446
447 /**
448  * Checks whether or not a node is `Reflect.apply`.
449  * @param {ASTNode} node A node to check.
450  * @returns {boolean} Whether or not the node is a `Reflect.apply`.
451  */
452 function isReflectApply(node) {
453     return isSpecificMemberAccess(node, "Reflect", "apply");
454 }
455
456 /**
457  * Checks whether or not a node is `Array.from`.
458  * @param {ASTNode} node A node to check.
459  * @returns {boolean} Whether or not the node is a `Array.from`.
460  */
461 function isArrayFromMethod(node) {
462     return isSpecificMemberAccess(node, arrayOrTypedArrayPattern, "from");
463 }
464
465 /**
466  * Checks whether or not a node is a method which has `thisArg`.
467  * @param {ASTNode} node A node to check.
468  * @returns {boolean} Whether or not the node is a method which has `thisArg`.
469  */
470 function isMethodWhichHasThisArg(node) {
471     return isSpecificMemberAccess(node, null, arrayMethodPattern);
472 }
473
474 /**
475  * Creates the negate function of the given function.
476  * @param {Function} f The function to negate.
477  * @returns {Function} Negated function.
478  */
479 function negate(f) {
480     return token => !f(token);
481 }
482
483 /**
484  * Checks whether or not a node has a `@this` tag in its comments.
485  * @param {ASTNode} node A node to check.
486  * @param {SourceCode} sourceCode A SourceCode instance to get comments.
487  * @returns {boolean} Whether or not the node has a `@this` tag in its comments.
488  */
489 function hasJSDocThisTag(node, sourceCode) {
490     const jsdocComment = sourceCode.getJSDocComment(node);
491
492     if (jsdocComment && thisTagPattern.test(jsdocComment.value)) {
493         return true;
494     }
495
496     // Checks `@this` in its leading comments for callbacks,
497     // because callbacks don't have its JSDoc comment.
498     // e.g.
499     //     sinon.test(/* @this sinon.Sandbox */function() { this.spy(); });
500     return sourceCode.getCommentsBefore(node).some(comment => thisTagPattern.test(comment.value));
501 }
502
503 /**
504  * Determines if a node is surrounded by parentheses.
505  * @param {SourceCode} sourceCode The ESLint source code object
506  * @param {ASTNode} node The node to be checked.
507  * @returns {boolean} True if the node is parenthesised.
508  * @private
509  */
510 function isParenthesised(sourceCode, node) {
511     const previousToken = sourceCode.getTokenBefore(node),
512         nextToken = sourceCode.getTokenAfter(node);
513
514     return Boolean(previousToken && nextToken) &&
515         previousToken.value === "(" && previousToken.range[1] <= node.range[0] &&
516         nextToken.value === ")" && nextToken.range[0] >= node.range[1];
517 }
518
519 /**
520  * Checks if the given token is an arrow token or not.
521  * @param {Token} token The token to check.
522  * @returns {boolean} `true` if the token is an arrow token.
523  */
524 function isArrowToken(token) {
525     return token.value === "=>" && token.type === "Punctuator";
526 }
527
528 /**
529  * Checks if the given token is a comma token or not.
530  * @param {Token} token The token to check.
531  * @returns {boolean} `true` if the token is a comma token.
532  */
533 function isCommaToken(token) {
534     return token.value === "," && token.type === "Punctuator";
535 }
536
537 /**
538  * Checks if the given token is a dot token or not.
539  * @param {Token} token The token to check.
540  * @returns {boolean} `true` if the token is a dot token.
541  */
542 function isDotToken(token) {
543     return token.value === "." && token.type === "Punctuator";
544 }
545
546 /**
547  * Checks if the given token is a `?.` token or not.
548  * @param {Token} token The token to check.
549  * @returns {boolean} `true` if the token is a `?.` token.
550  */
551 function isQuestionDotToken(token) {
552     return token.value === "?." && token.type === "Punctuator";
553 }
554
555 /**
556  * Checks if the given token is a semicolon token or not.
557  * @param {Token} token The token to check.
558  * @returns {boolean} `true` if the token is a semicolon token.
559  */
560 function isSemicolonToken(token) {
561     return token.value === ";" && token.type === "Punctuator";
562 }
563
564 /**
565  * Checks if the given token is a colon token or not.
566  * @param {Token} token The token to check.
567  * @returns {boolean} `true` if the token is a colon token.
568  */
569 function isColonToken(token) {
570     return token.value === ":" && token.type === "Punctuator";
571 }
572
573 /**
574  * Checks if the given token is an opening parenthesis token or not.
575  * @param {Token} token The token to check.
576  * @returns {boolean} `true` if the token is an opening parenthesis token.
577  */
578 function isOpeningParenToken(token) {
579     return token.value === "(" && token.type === "Punctuator";
580 }
581
582 /**
583  * Checks if the given token is a closing parenthesis token or not.
584  * @param {Token} token The token to check.
585  * @returns {boolean} `true` if the token is a closing parenthesis token.
586  */
587 function isClosingParenToken(token) {
588     return token.value === ")" && token.type === "Punctuator";
589 }
590
591 /**
592  * Checks if the given token is an opening square bracket token or not.
593  * @param {Token} token The token to check.
594  * @returns {boolean} `true` if the token is an opening square bracket token.
595  */
596 function isOpeningBracketToken(token) {
597     return token.value === "[" && token.type === "Punctuator";
598 }
599
600 /**
601  * Checks if the given token is a closing square bracket token or not.
602  * @param {Token} token The token to check.
603  * @returns {boolean} `true` if the token is a closing square bracket token.
604  */
605 function isClosingBracketToken(token) {
606     return token.value === "]" && token.type === "Punctuator";
607 }
608
609 /**
610  * Checks if the given token is an opening brace token or not.
611  * @param {Token} token The token to check.
612  * @returns {boolean} `true` if the token is an opening brace token.
613  */
614 function isOpeningBraceToken(token) {
615     return token.value === "{" && token.type === "Punctuator";
616 }
617
618 /**
619  * Checks if the given token is a closing brace token or not.
620  * @param {Token} token The token to check.
621  * @returns {boolean} `true` if the token is a closing brace token.
622  */
623 function isClosingBraceToken(token) {
624     return token.value === "}" && token.type === "Punctuator";
625 }
626
627 /**
628  * Checks if the given token is a comment token or not.
629  * @param {Token} token The token to check.
630  * @returns {boolean} `true` if the token is a comment token.
631  */
632 function isCommentToken(token) {
633     return token.type === "Line" || token.type === "Block" || token.type === "Shebang";
634 }
635
636 /**
637  * Checks if the given token is a keyword token or not.
638  * @param {Token} token The token to check.
639  * @returns {boolean} `true` if the token is a keyword token.
640  */
641 function isKeywordToken(token) {
642     return token.type === "Keyword";
643 }
644
645 /**
646  * Gets the `(` token of the given function node.
647  * @param {ASTNode} node The function node to get.
648  * @param {SourceCode} sourceCode The source code object to get tokens.
649  * @returns {Token} `(` token.
650  */
651 function getOpeningParenOfParams(node, sourceCode) {
652     return node.id
653         ? sourceCode.getTokenAfter(node.id, isOpeningParenToken)
654         : sourceCode.getFirstToken(node, isOpeningParenToken);
655 }
656
657 /**
658  * Checks whether or not the tokens of two given nodes are same.
659  * @param {ASTNode} left A node 1 to compare.
660  * @param {ASTNode} right A node 2 to compare.
661  * @param {SourceCode} sourceCode The ESLint source code object.
662  * @returns {boolean} the source code for the given node.
663  */
664 function equalTokens(left, right, sourceCode) {
665     const tokensL = sourceCode.getTokens(left);
666     const tokensR = sourceCode.getTokens(right);
667
668     if (tokensL.length !== tokensR.length) {
669         return false;
670     }
671     for (let i = 0; i < tokensL.length; ++i) {
672         if (tokensL[i].type !== tokensR[i].type ||
673             tokensL[i].value !== tokensR[i].value
674         ) {
675             return false;
676         }
677     }
678
679     return true;
680 }
681
682 /**
683  * Check if the given node is a true logical expression or not.
684  *
685  * The three binary expressions logical-or (`||`), logical-and (`&&`), and
686  * coalesce (`??`) are known as `ShortCircuitExpression`.
687  * But ESTree represents those by `LogicalExpression` node.
688  *
689  * This function rejects coalesce expressions of `LogicalExpression` node.
690  * @param {ASTNode} node The node to check.
691  * @returns {boolean} `true` if the node is `&&` or `||`.
692  * @see https://tc39.es/ecma262/#prod-ShortCircuitExpression
693  */
694 function isLogicalExpression(node) {
695     return (
696         node.type === "LogicalExpression" &&
697             (node.operator === "&&" || node.operator === "||")
698     );
699 }
700
701 /**
702  * Check if the given node is a nullish coalescing expression or not.
703  *
704  * The three binary expressions logical-or (`||`), logical-and (`&&`), and
705  * coalesce (`??`) are known as `ShortCircuitExpression`.
706  * But ESTree represents those by `LogicalExpression` node.
707  *
708  * This function finds only coalesce expressions of `LogicalExpression` node.
709  * @param {ASTNode} node The node to check.
710  * @returns {boolean} `true` if the node is `??`.
711  */
712 function isCoalesceExpression(node) {
713     return node.type === "LogicalExpression" && node.operator === "??";
714 }
715
716 /**
717  * Check if given two nodes are the pair of a logical expression and a coalesce expression.
718  * @param {ASTNode} left A node to check.
719  * @param {ASTNode} right Another node to check.
720  * @returns {boolean} `true` if the two nodes are the pair of a logical expression and a coalesce expression.
721  */
722 function isMixedLogicalAndCoalesceExpressions(left, right) {
723     return (
724         (isLogicalExpression(left) && isCoalesceExpression(right)) ||
725             (isCoalesceExpression(left) && isLogicalExpression(right))
726     );
727 }
728
729 /**
730  * Checks if the given operator is a logical assignment operator.
731  * @param {string} operator The operator to check.
732  * @returns {boolean} `true` if the operator is a logical assignment operator.
733  */
734 function isLogicalAssignmentOperator(operator) {
735     return LOGICAL_ASSIGNMENT_OPERATORS.has(operator);
736 }
737
738 //------------------------------------------------------------------------------
739 // Public Interface
740 //------------------------------------------------------------------------------
741
742 module.exports = {
743     COMMENTS_IGNORE_PATTERN,
744     LINEBREAKS,
745     LINEBREAK_MATCHER: lineBreakPattern,
746     SHEBANG_MATCHER: shebangPattern,
747     STATEMENT_LIST_PARENTS,
748
749     /**
750      * Determines whether two adjacent tokens are on the same line.
751      * @param {Object} left The left token object.
752      * @param {Object} right The right token object.
753      * @returns {boolean} Whether or not the tokens are on the same line.
754      * @public
755      */
756     isTokenOnSameLine(left, right) {
757         return left.loc.end.line === right.loc.start.line;
758     },
759
760     isNullOrUndefined,
761     isCallee,
762     isES5Constructor,
763     getUpperFunction,
764     isFunction,
765     isLoop,
766     isInLoop,
767     isArrayFromMethod,
768     isParenthesised,
769     createGlobalLinebreakMatcher,
770     equalTokens,
771
772     isArrowToken,
773     isClosingBraceToken,
774     isClosingBracketToken,
775     isClosingParenToken,
776     isColonToken,
777     isCommaToken,
778     isCommentToken,
779     isDotToken,
780     isQuestionDotToken,
781     isKeywordToken,
782     isNotClosingBraceToken: negate(isClosingBraceToken),
783     isNotClosingBracketToken: negate(isClosingBracketToken),
784     isNotClosingParenToken: negate(isClosingParenToken),
785     isNotColonToken: negate(isColonToken),
786     isNotCommaToken: negate(isCommaToken),
787     isNotDotToken: negate(isDotToken),
788     isNotQuestionDotToken: negate(isQuestionDotToken),
789     isNotOpeningBraceToken: negate(isOpeningBraceToken),
790     isNotOpeningBracketToken: negate(isOpeningBracketToken),
791     isNotOpeningParenToken: negate(isOpeningParenToken),
792     isNotSemicolonToken: negate(isSemicolonToken),
793     isOpeningBraceToken,
794     isOpeningBracketToken,
795     isOpeningParenToken,
796     isSemicolonToken,
797
798     /**
799      * Checks whether or not a given node is a string literal.
800      * @param {ASTNode} node A node to check.
801      * @returns {boolean} `true` if the node is a string literal.
802      */
803     isStringLiteral(node) {
804         return (
805             (node.type === "Literal" && typeof node.value === "string") ||
806             node.type === "TemplateLiteral"
807         );
808     },
809
810     /**
811      * Checks whether a given node is a breakable statement or not.
812      * The node is breakable if the node is one of the following type:
813      *
814      * - DoWhileStatement
815      * - ForInStatement
816      * - ForOfStatement
817      * - ForStatement
818      * - SwitchStatement
819      * - WhileStatement
820      * @param {ASTNode} node A node to check.
821      * @returns {boolean} `true` if the node is breakable.
822      */
823     isBreakableStatement(node) {
824         return breakableTypePattern.test(node.type);
825     },
826
827     /**
828      * Gets references which are non initializer and writable.
829      * @param {Reference[]} references An array of references.
830      * @returns {Reference[]} An array of only references which are non initializer and writable.
831      * @public
832      */
833     getModifyingReferences(references) {
834         return references.filter(isModifyingReference);
835     },
836
837     /**
838      * Validate that a string passed in is surrounded by the specified character
839      * @param  {string} val The text to check.
840      * @param  {string} character The character to see if it's surrounded by.
841      * @returns {boolean} True if the text is surrounded by the character, false if not.
842      * @private
843      */
844     isSurroundedBy(val, character) {
845         return val[0] === character && val[val.length - 1] === character;
846     },
847
848     /**
849      * Returns whether the provided node is an ESLint directive comment or not
850      * @param {Line|Block} node The comment token to be checked
851      * @returns {boolean} `true` if the node is an ESLint directive comment
852      */
853     isDirectiveComment(node) {
854         const comment = node.value.trim();
855
856         return (
857             node.type === "Line" && comment.indexOf("eslint-") === 0 ||
858             node.type === "Block" && (
859                 comment.indexOf("global ") === 0 ||
860                 comment.indexOf("eslint ") === 0 ||
861                 comment.indexOf("eslint-") === 0
862             )
863         );
864     },
865
866     /**
867      * Gets the trailing statement of a given node.
868      *
869      *     if (code)
870      *         consequent;
871      *
872      * When taking this `IfStatement`, returns `consequent;` statement.
873      * @param {ASTNode} A node to get.
874      * @returns {ASTNode|null} The trailing statement's node.
875      */
876     getTrailingStatement: esutils.ast.trailingStatement,
877
878     /**
879      * Finds the variable by a given name in a given scope and its upper scopes.
880      * @param {eslint-scope.Scope} initScope A scope to start find.
881      * @param {string} name A variable name to find.
882      * @returns {eslint-scope.Variable|null} A found variable or `null`.
883      */
884     getVariableByName(initScope, name) {
885         let scope = initScope;
886
887         while (scope) {
888             const variable = scope.set.get(name);
889
890             if (variable) {
891                 return variable;
892             }
893
894             scope = scope.upper;
895         }
896
897         return null;
898     },
899
900     /**
901      * Checks whether or not a given function node is the default `this` binding.
902      *
903      * First, this checks the node:
904      *
905      * - The function name does not start with uppercase. It's a convention to capitalize the names
906      *   of constructor functions. This check is not performed if `capIsConstructor` is set to `false`.
907      * - The function does not have a JSDoc comment that has a @this tag.
908      *
909      * Next, this checks the location of the node.
910      * If the location is below, this judges `this` is valid.
911      *
912      * - The location is not on an object literal.
913      * - The location is not assigned to a variable which starts with an uppercase letter. Applies to anonymous
914      *   functions only, as the name of the variable is considered to be the name of the function in this case.
915      *   This check is not performed if `capIsConstructor` is set to `false`.
916      * - The location is not on an ES2015 class.
917      * - Its `bind`/`call`/`apply` method is not called directly.
918      * - The function is not a callback of array methods (such as `.forEach()`) if `thisArg` is given.
919      * @param {ASTNode} node A function node to check.
920      * @param {SourceCode} sourceCode A SourceCode instance to get comments.
921      * @param {boolean} [capIsConstructor = true] `false` disables the assumption that functions which name starts
922      * with an uppercase or are assigned to a variable which name starts with an uppercase are constructors.
923      * @returns {boolean} The function node is the default `this` binding.
924      */
925     isDefaultThisBinding(node, sourceCode, { capIsConstructor = true } = {}) {
926         if (
927             (capIsConstructor && isES5Constructor(node)) ||
928             hasJSDocThisTag(node, sourceCode)
929         ) {
930             return false;
931         }
932         const isAnonymous = node.id === null;
933         let currentNode = node;
934
935         while (currentNode) {
936             const parent = currentNode.parent;
937
938             switch (parent.type) {
939
940                 /*
941                  * Looks up the destination.
942                  * e.g., obj.foo = nativeFoo || function foo() { ... };
943                  */
944                 case "LogicalExpression":
945                 case "ConditionalExpression":
946                 case "ChainExpression":
947                     currentNode = parent;
948                     break;
949
950                 /*
951                  * If the upper function is IIFE, checks the destination of the return value.
952                  * e.g.
953                  *   obj.foo = (function() {
954                  *     // setup...
955                  *     return function foo() { ... };
956                  *   })();
957                  *   obj.foo = (() =>
958                  *     function foo() { ... }
959                  *   )();
960                  */
961                 case "ReturnStatement": {
962                     const func = getUpperFunction(parent);
963
964                     if (func === null || !isCallee(func)) {
965                         return true;
966                     }
967                     currentNode = func.parent;
968                     break;
969                 }
970                 case "ArrowFunctionExpression":
971                     if (currentNode !== parent.body || !isCallee(parent)) {
972                         return true;
973                     }
974                     currentNode = parent.parent;
975                     break;
976
977                 /*
978                  * e.g.
979                  *   var obj = { foo() { ... } };
980                  *   var obj = { foo: function() { ... } };
981                  *   class A { constructor() { ... } }
982                  *   class A { foo() { ... } }
983                  *   class A { get foo() { ... } }
984                  *   class A { set foo() { ... } }
985                  *   class A { static foo() { ... } }
986                  */
987                 case "Property":
988                 case "MethodDefinition":
989                     return parent.value !== currentNode;
990
991                 /*
992                  * e.g.
993                  *   obj.foo = function foo() { ... };
994                  *   Foo = function() { ... };
995                  *   [obj.foo = function foo() { ... }] = a;
996                  *   [Foo = function() { ... }] = a;
997                  */
998                 case "AssignmentExpression":
999                 case "AssignmentPattern":
1000                     if (parent.left.type === "MemberExpression") {
1001                         return false;
1002                     }
1003                     if (
1004                         capIsConstructor &&
1005                         isAnonymous &&
1006                         parent.left.type === "Identifier" &&
1007                         startsWithUpperCase(parent.left.name)
1008                     ) {
1009                         return false;
1010                     }
1011                     return true;
1012
1013                 /*
1014                  * e.g.
1015                  *   var Foo = function() { ... };
1016                  */
1017                 case "VariableDeclarator":
1018                     return !(
1019                         capIsConstructor &&
1020                         isAnonymous &&
1021                         parent.init === currentNode &&
1022                         parent.id.type === "Identifier" &&
1023                         startsWithUpperCase(parent.id.name)
1024                     );
1025
1026                 /*
1027                  * e.g.
1028                  *   var foo = function foo() { ... }.bind(obj);
1029                  *   (function foo() { ... }).call(obj);
1030                  *   (function foo() { ... }).apply(obj, []);
1031                  */
1032                 case "MemberExpression":
1033                     if (
1034                         parent.object === currentNode &&
1035                         isSpecificMemberAccess(parent, null, bindOrCallOrApplyPattern)
1036                     ) {
1037                         const maybeCalleeNode = parent.parent.type === "ChainExpression"
1038                             ? parent.parent
1039                             : parent;
1040
1041                         return !(
1042                             isCallee(maybeCalleeNode) &&
1043                             maybeCalleeNode.parent.arguments.length >= 1 &&
1044                             !isNullOrUndefined(maybeCalleeNode.parent.arguments[0])
1045                         );
1046                     }
1047                     return true;
1048
1049                 /*
1050                  * e.g.
1051                  *   Reflect.apply(function() {}, obj, []);
1052                  *   Array.from([], function() {}, obj);
1053                  *   list.forEach(function() {}, obj);
1054                  */
1055                 case "CallExpression":
1056                     if (isReflectApply(parent.callee)) {
1057                         return (
1058                             parent.arguments.length !== 3 ||
1059                             parent.arguments[0] !== currentNode ||
1060                             isNullOrUndefined(parent.arguments[1])
1061                         );
1062                     }
1063                     if (isArrayFromMethod(parent.callee)) {
1064                         return (
1065                             parent.arguments.length !== 3 ||
1066                             parent.arguments[1] !== currentNode ||
1067                             isNullOrUndefined(parent.arguments[2])
1068                         );
1069                     }
1070                     if (isMethodWhichHasThisArg(parent.callee)) {
1071                         return (
1072                             parent.arguments.length !== 2 ||
1073                             parent.arguments[0] !== currentNode ||
1074                             isNullOrUndefined(parent.arguments[1])
1075                         );
1076                     }
1077                     return true;
1078
1079                 // Otherwise `this` is default.
1080                 default:
1081                     return true;
1082             }
1083         }
1084
1085         /* istanbul ignore next */
1086         return true;
1087     },
1088
1089     /**
1090      * Get the precedence level based on the node type
1091      * @param {ASTNode} node node to evaluate
1092      * @returns {int} precedence level
1093      * @private
1094      */
1095     getPrecedence(node) {
1096         switch (node.type) {
1097             case "SequenceExpression":
1098                 return 0;
1099
1100             case "AssignmentExpression":
1101             case "ArrowFunctionExpression":
1102             case "YieldExpression":
1103                 return 1;
1104
1105             case "ConditionalExpression":
1106                 return 3;
1107
1108             case "LogicalExpression":
1109                 switch (node.operator) {
1110                     case "||":
1111                     case "??":
1112                         return 4;
1113                     case "&&":
1114                         return 5;
1115
1116                     // no default
1117                 }
1118
1119                 /* falls through */
1120
1121             case "BinaryExpression":
1122
1123                 switch (node.operator) {
1124                     case "|":
1125                         return 6;
1126                     case "^":
1127                         return 7;
1128                     case "&":
1129                         return 8;
1130                     case "==":
1131                     case "!=":
1132                     case "===":
1133                     case "!==":
1134                         return 9;
1135                     case "<":
1136                     case "<=":
1137                     case ">":
1138                     case ">=":
1139                     case "in":
1140                     case "instanceof":
1141                         return 10;
1142                     case "<<":
1143                     case ">>":
1144                     case ">>>":
1145                         return 11;
1146                     case "+":
1147                     case "-":
1148                         return 12;
1149                     case "*":
1150                     case "/":
1151                     case "%":
1152                         return 13;
1153                     case "**":
1154                         return 15;
1155
1156                     // no default
1157                 }
1158
1159                 /* falls through */
1160
1161             case "UnaryExpression":
1162             case "AwaitExpression":
1163                 return 16;
1164
1165             case "UpdateExpression":
1166                 return 17;
1167
1168             case "CallExpression":
1169             case "ChainExpression":
1170             case "ImportExpression":
1171                 return 18;
1172
1173             case "NewExpression":
1174                 return 19;
1175
1176             default:
1177                 return 20;
1178         }
1179     },
1180
1181     /**
1182      * Checks whether the given node is an empty block node or not.
1183      * @param {ASTNode|null} node The node to check.
1184      * @returns {boolean} `true` if the node is an empty block.
1185      */
1186     isEmptyBlock(node) {
1187         return Boolean(node && node.type === "BlockStatement" && node.body.length === 0);
1188     },
1189
1190     /**
1191      * Checks whether the given node is an empty function node or not.
1192      * @param {ASTNode|null} node The node to check.
1193      * @returns {boolean} `true` if the node is an empty function.
1194      */
1195     isEmptyFunction(node) {
1196         return isFunction(node) && module.exports.isEmptyBlock(node.body);
1197     },
1198
1199     /**
1200      * Get directives from directive prologue of a Program or Function node.
1201      * @param {ASTNode} node The node to check.
1202      * @returns {ASTNode[]} The directives found in the directive prologue.
1203      */
1204     getDirectivePrologue(node) {
1205         const directives = [];
1206
1207         // Directive prologues only occur at the top of files or functions.
1208         if (
1209             node.type === "Program" ||
1210             node.type === "FunctionDeclaration" ||
1211             node.type === "FunctionExpression" ||
1212
1213             /*
1214              * Do not check arrow functions with implicit return.
1215              * `() => "use strict";` returns the string `"use strict"`.
1216              */
1217             (node.type === "ArrowFunctionExpression" && node.body.type === "BlockStatement")
1218         ) {
1219             const statements = node.type === "Program" ? node.body : node.body.body;
1220
1221             for (const statement of statements) {
1222                 if (
1223                     statement.type === "ExpressionStatement" &&
1224                     statement.expression.type === "Literal"
1225                 ) {
1226                     directives.push(statement);
1227                 } else {
1228                     break;
1229                 }
1230             }
1231         }
1232
1233         return directives;
1234     },
1235
1236
1237     /**
1238      * Determines whether this node is a decimal integer literal. If a node is a decimal integer literal, a dot added
1239      * after the node will be parsed as a decimal point, rather than a property-access dot.
1240      * @param {ASTNode} node The node to check.
1241      * @returns {boolean} `true` if this node is a decimal integer.
1242      * @example
1243      *
1244      * 0         // true
1245      * 5         // true
1246      * 50        // true
1247      * 5_000     // true
1248      * 1_234_56  // true
1249      * 08        // true
1250      * 0192      // true
1251      * 5.        // false
1252      * .5        // false
1253      * 5.0       // false
1254      * 5.00_00   // false
1255      * 05        // false
1256      * 0x5       // false
1257      * 0b101     // false
1258      * 0b11_01   // false
1259      * 0o5       // false
1260      * 5e0       // false
1261      * 5e1_000   // false
1262      * 5n        // false
1263      * 1_000n    // false
1264      * '5'       // false
1265      */
1266     isDecimalInteger(node) {
1267         return node.type === "Literal" && typeof node.value === "number" &&
1268             DECIMAL_INTEGER_PATTERN.test(node.raw);
1269     },
1270
1271     /**
1272      * Determines whether this token is a decimal integer numeric token.
1273      * This is similar to isDecimalInteger(), but for tokens.
1274      * @param {Token} token The token to check.
1275      * @returns {boolean} `true` if this token is a decimal integer.
1276      */
1277     isDecimalIntegerNumericToken(token) {
1278         return token.type === "Numeric" && DECIMAL_INTEGER_PATTERN.test(token.value);
1279     },
1280
1281     /**
1282      * Gets the name and kind of the given function node.
1283      *
1284      * - `function foo() {}`  .................... `function 'foo'`
1285      * - `(function foo() {})`  .................. `function 'foo'`
1286      * - `(function() {})`  ...................... `function`
1287      * - `function* foo() {}`  ................... `generator function 'foo'`
1288      * - `(function* foo() {})`  ................. `generator function 'foo'`
1289      * - `(function*() {})`  ..................... `generator function`
1290      * - `() => {}`  ............................. `arrow function`
1291      * - `async () => {}`  ....................... `async arrow function`
1292      * - `({ foo: function foo() {} })`  ......... `method 'foo'`
1293      * - `({ foo: function() {} })`  ............. `method 'foo'`
1294      * - `({ ['foo']: function() {} })`  ......... `method 'foo'`
1295      * - `({ [foo]: function() {} })`  ........... `method`
1296      * - `({ foo() {} })`  ....................... `method 'foo'`
1297      * - `({ foo: function* foo() {} })`  ........ `generator method 'foo'`
1298      * - `({ foo: function*() {} })`  ............ `generator method 'foo'`
1299      * - `({ ['foo']: function*() {} })`  ........ `generator method 'foo'`
1300      * - `({ [foo]: function*() {} })`  .......... `generator method`
1301      * - `({ *foo() {} })`  ...................... `generator method 'foo'`
1302      * - `({ foo: async function foo() {} })`  ... `async method 'foo'`
1303      * - `({ foo: async function() {} })`  ....... `async method 'foo'`
1304      * - `({ ['foo']: async function() {} })`  ... `async method 'foo'`
1305      * - `({ [foo]: async function() {} })`  ..... `async method`
1306      * - `({ async foo() {} })`  ................. `async method 'foo'`
1307      * - `({ get foo() {} })`  ................... `getter 'foo'`
1308      * - `({ set foo(a) {} })`  .................. `setter 'foo'`
1309      * - `class A { constructor() {} }`  ......... `constructor`
1310      * - `class A { foo() {} }`  ................. `method 'foo'`
1311      * - `class A { *foo() {} }`  ................ `generator method 'foo'`
1312      * - `class A { async foo() {} }`  ........... `async method 'foo'`
1313      * - `class A { ['foo']() {} }`  ............. `method 'foo'`
1314      * - `class A { *['foo']() {} }`  ............ `generator method 'foo'`
1315      * - `class A { async ['foo']() {} }`  ....... `async method 'foo'`
1316      * - `class A { [foo]() {} }`  ............... `method`
1317      * - `class A { *[foo]() {} }`  .............. `generator method`
1318      * - `class A { async [foo]() {} }`  ......... `async method`
1319      * - `class A { get foo() {} }`  ............. `getter 'foo'`
1320      * - `class A { set foo(a) {} }`  ............ `setter 'foo'`
1321      * - `class A { static foo() {} }`  .......... `static method 'foo'`
1322      * - `class A { static *foo() {} }`  ......... `static generator method 'foo'`
1323      * - `class A { static async foo() {} }`  .... `static async method 'foo'`
1324      * - `class A { static get foo() {} }`  ...... `static getter 'foo'`
1325      * - `class A { static set foo(a) {} }`  ..... `static setter 'foo'`
1326      * @param {ASTNode} node The function node to get.
1327      * @returns {string} The name and kind of the function node.
1328      */
1329     getFunctionNameWithKind(node) {
1330         const parent = node.parent;
1331         const tokens = [];
1332
1333         if (parent.type === "MethodDefinition" && parent.static) {
1334             tokens.push("static");
1335         }
1336         if (node.async) {
1337             tokens.push("async");
1338         }
1339         if (node.generator) {
1340             tokens.push("generator");
1341         }
1342
1343         if (node.type === "ArrowFunctionExpression") {
1344             tokens.push("arrow", "function");
1345         } else if (parent.type === "Property" || parent.type === "MethodDefinition") {
1346             if (parent.kind === "constructor") {
1347                 return "constructor";
1348             }
1349             if (parent.kind === "get") {
1350                 tokens.push("getter");
1351             } else if (parent.kind === "set") {
1352                 tokens.push("setter");
1353             } else {
1354                 tokens.push("method");
1355             }
1356         } else {
1357             tokens.push("function");
1358         }
1359
1360         if (node.id) {
1361             tokens.push(`'${node.id.name}'`);
1362         } else {
1363             const name = getStaticPropertyName(parent);
1364
1365             if (name !== null) {
1366                 tokens.push(`'${name}'`);
1367             }
1368         }
1369
1370         return tokens.join(" ");
1371     },
1372
1373     /**
1374      * Gets the location of the given function node for reporting.
1375      *
1376      * - `function foo() {}`
1377      *    ^^^^^^^^^^^^
1378      * - `(function foo() {})`
1379      *     ^^^^^^^^^^^^
1380      * - `(function() {})`
1381      *     ^^^^^^^^
1382      * - `function* foo() {}`
1383      *    ^^^^^^^^^^^^^
1384      * - `(function* foo() {})`
1385      *     ^^^^^^^^^^^^^
1386      * - `(function*() {})`
1387      *     ^^^^^^^^^
1388      * - `() => {}`
1389      *       ^^
1390      * - `async () => {}`
1391      *             ^^
1392      * - `({ foo: function foo() {} })`
1393      *       ^^^^^^^^^^^^^^^^^
1394      * - `({ foo: function() {} })`
1395      *       ^^^^^^^^^^^^^
1396      * - `({ ['foo']: function() {} })`
1397      *       ^^^^^^^^^^^^^^^^^
1398      * - `({ [foo]: function() {} })`
1399      *       ^^^^^^^^^^^^^^^
1400      * - `({ foo() {} })`
1401      *       ^^^
1402      * - `({ foo: function* foo() {} })`
1403      *       ^^^^^^^^^^^^^^^^^^
1404      * - `({ foo: function*() {} })`
1405      *       ^^^^^^^^^^^^^^
1406      * - `({ ['foo']: function*() {} })`
1407      *       ^^^^^^^^^^^^^^^^^^
1408      * - `({ [foo]: function*() {} })`
1409      *       ^^^^^^^^^^^^^^^^
1410      * - `({ *foo() {} })`
1411      *       ^^^^
1412      * - `({ foo: async function foo() {} })`
1413      *       ^^^^^^^^^^^^^^^^^^^^^^^
1414      * - `({ foo: async function() {} })`
1415      *       ^^^^^^^^^^^^^^^^^^^
1416      * - `({ ['foo']: async function() {} })`
1417      *       ^^^^^^^^^^^^^^^^^^^^^^^
1418      * - `({ [foo]: async function() {} })`
1419      *       ^^^^^^^^^^^^^^^^^^^^^
1420      * - `({ async foo() {} })`
1421      *       ^^^^^^^^^
1422      * - `({ get foo() {} })`
1423      *       ^^^^^^^
1424      * - `({ set foo(a) {} })`
1425      *       ^^^^^^^
1426      * - `class A { constructor() {} }`
1427      *              ^^^^^^^^^^^
1428      * - `class A { foo() {} }`
1429      *              ^^^
1430      * - `class A { *foo() {} }`
1431      *              ^^^^
1432      * - `class A { async foo() {} }`
1433      *              ^^^^^^^^^
1434      * - `class A { ['foo']() {} }`
1435      *              ^^^^^^^
1436      * - `class A { *['foo']() {} }`
1437      *              ^^^^^^^^
1438      * - `class A { async ['foo']() {} }`
1439      *              ^^^^^^^^^^^^^
1440      * - `class A { [foo]() {} }`
1441      *              ^^^^^
1442      * - `class A { *[foo]() {} }`
1443      *              ^^^^^^
1444      * - `class A { async [foo]() {} }`
1445      *              ^^^^^^^^^^^
1446      * - `class A { get foo() {} }`
1447      *              ^^^^^^^
1448      * - `class A { set foo(a) {} }`
1449      *              ^^^^^^^
1450      * - `class A { static foo() {} }`
1451      *              ^^^^^^^^^^
1452      * - `class A { static *foo() {} }`
1453      *              ^^^^^^^^^^^
1454      * - `class A { static async foo() {} }`
1455      *              ^^^^^^^^^^^^^^^^
1456      * - `class A { static get foo() {} }`
1457      *              ^^^^^^^^^^^^^^
1458      * - `class A { static set foo(a) {} }`
1459      *              ^^^^^^^^^^^^^^
1460      * @param {ASTNode} node The function node to get.
1461      * @param {SourceCode} sourceCode The source code object to get tokens.
1462      * @returns {string} The location of the function node for reporting.
1463      */
1464     getFunctionHeadLoc(node, sourceCode) {
1465         const parent = node.parent;
1466         let start = null;
1467         let end = null;
1468
1469         if (node.type === "ArrowFunctionExpression") {
1470             const arrowToken = sourceCode.getTokenBefore(node.body, isArrowToken);
1471
1472             start = arrowToken.loc.start;
1473             end = arrowToken.loc.end;
1474         } else if (parent.type === "Property" || parent.type === "MethodDefinition") {
1475             start = parent.loc.start;
1476             end = getOpeningParenOfParams(node, sourceCode).loc.start;
1477         } else {
1478             start = node.loc.start;
1479             end = getOpeningParenOfParams(node, sourceCode).loc.start;
1480         }
1481
1482         return {
1483             start: Object.assign({}, start),
1484             end: Object.assign({}, end)
1485         };
1486     },
1487
1488     /**
1489      * Gets next location when the result is not out of bound, otherwise returns null.
1490      *
1491      * Assumptions:
1492      *
1493      * - The given location represents a valid location in the given source code.
1494      * - Columns are 0-based.
1495      * - Lines are 1-based.
1496      * - Column immediately after the last character in a line (not incl. linebreaks) is considered to be a valid location.
1497      * - If the source code ends with a linebreak, `sourceCode.lines` array will have an extra element (empty string) at the end.
1498      *   The start (column 0) of that extra line is considered to be a valid location.
1499      *
1500      * Examples of successive locations (line, column):
1501      *
1502      * code: foo
1503      * locations: (1, 0) -> (1, 1) -> (1, 2) -> (1, 3) -> null
1504      *
1505      * code: foo<LF>
1506      * locations: (1, 0) -> (1, 1) -> (1, 2) -> (1, 3) -> (2, 0) -> null
1507      *
1508      * code: foo<CR><LF>
1509      * locations: (1, 0) -> (1, 1) -> (1, 2) -> (1, 3) -> (2, 0) -> null
1510      *
1511      * code: a<LF>b
1512      * locations: (1, 0) -> (1, 1) -> (2, 0) -> (2, 1) -> null
1513      *
1514      * code: a<LF>b<LF>
1515      * locations: (1, 0) -> (1, 1) -> (2, 0) -> (2, 1) -> (3, 0) -> null
1516      *
1517      * code: a<CR><LF>b<CR><LF>
1518      * locations: (1, 0) -> (1, 1) -> (2, 0) -> (2, 1) -> (3, 0) -> null
1519      *
1520      * code: a<LF><LF>
1521      * locations: (1, 0) -> (1, 1) -> (2, 0) -> (3, 0) -> null
1522      *
1523      * code: <LF>
1524      * locations: (1, 0) -> (2, 0) -> null
1525      *
1526      * code:
1527      * locations: (1, 0) -> null
1528      * @param {SourceCode} sourceCode The sourceCode
1529      * @param {{line: number, column: number}} location The location
1530      * @returns {{line: number, column: number} | null} Next location
1531      */
1532     getNextLocation(sourceCode, { line, column }) {
1533         if (column < sourceCode.lines[line - 1].length) {
1534             return {
1535                 line,
1536                 column: column + 1
1537             };
1538         }
1539
1540         if (line < sourceCode.lines.length) {
1541             return {
1542                 line: line + 1,
1543                 column: 0
1544             };
1545         }
1546
1547         return null;
1548     },
1549
1550     /**
1551      * Gets the parenthesized text of a node. This is similar to sourceCode.getText(node), but it also includes any parentheses
1552      * surrounding the node.
1553      * @param {SourceCode} sourceCode The source code object
1554      * @param {ASTNode} node An expression node
1555      * @returns {string} The text representing the node, with all surrounding parentheses included
1556      */
1557     getParenthesisedText(sourceCode, node) {
1558         let leftToken = sourceCode.getFirstToken(node);
1559         let rightToken = sourceCode.getLastToken(node);
1560
1561         while (
1562             sourceCode.getTokenBefore(leftToken) &&
1563             sourceCode.getTokenBefore(leftToken).type === "Punctuator" &&
1564             sourceCode.getTokenBefore(leftToken).value === "(" &&
1565             sourceCode.getTokenAfter(rightToken) &&
1566             sourceCode.getTokenAfter(rightToken).type === "Punctuator" &&
1567             sourceCode.getTokenAfter(rightToken).value === ")"
1568         ) {
1569             leftToken = sourceCode.getTokenBefore(leftToken);
1570             rightToken = sourceCode.getTokenAfter(rightToken);
1571         }
1572
1573         return sourceCode.getText().slice(leftToken.range[0], rightToken.range[1]);
1574     },
1575
1576     /*
1577      * Determine if a node has a possibility to be an Error object
1578      * @param  {ASTNode} node  ASTNode to check
1579      * @returns {boolean} True if there is a chance it contains an Error obj
1580      */
1581     couldBeError(node) {
1582         switch (node.type) {
1583             case "Identifier":
1584             case "CallExpression":
1585             case "NewExpression":
1586             case "MemberExpression":
1587             case "TaggedTemplateExpression":
1588             case "YieldExpression":
1589             case "AwaitExpression":
1590             case "ChainExpression":
1591                 return true; // possibly an error object.
1592
1593             case "AssignmentExpression":
1594                 if (["=", "&&="].includes(node.operator)) {
1595                     return module.exports.couldBeError(node.right);
1596                 }
1597
1598                 if (["||=", "??="].includes(node.operator)) {
1599                     return module.exports.couldBeError(node.left) || module.exports.couldBeError(node.right);
1600                 }
1601
1602                 /**
1603                  * All other assignment operators are mathematical assignment operators (arithmetic or bitwise).
1604                  * An assignment expression with a mathematical operator can either evaluate to a primitive value,
1605                  * or throw, depending on the operands. Thus, it cannot evaluate to an `Error` object.
1606                  */
1607                 return false;
1608
1609             case "SequenceExpression": {
1610                 const exprs = node.expressions;
1611
1612                 return exprs.length !== 0 && module.exports.couldBeError(exprs[exprs.length - 1]);
1613             }
1614
1615             case "LogicalExpression":
1616
1617                 /*
1618                  * If the && operator short-circuits, the left side was falsy and therefore not an error, and if it
1619                  * doesn't short-circuit, it takes the value from the right side, so the right side must always be
1620                  * a plausible error. A future improvement could verify that the left side could be truthy by
1621                  * excluding falsy literals.
1622                  */
1623                 if (node.operator === "&&") {
1624                     return module.exports.couldBeError(node.right);
1625                 }
1626
1627                 return module.exports.couldBeError(node.left) || module.exports.couldBeError(node.right);
1628
1629             case "ConditionalExpression":
1630                 return module.exports.couldBeError(node.consequent) || module.exports.couldBeError(node.alternate);
1631
1632             default:
1633                 return false;
1634         }
1635     },
1636
1637     /**
1638      * Check if a given node is a numeric literal or not.
1639      * @param {ASTNode} node The node to check.
1640      * @returns {boolean} `true` if the node is a number or bigint literal.
1641      */
1642     isNumericLiteral(node) {
1643         return (
1644             node.type === "Literal" &&
1645             (typeof node.value === "number" || Boolean(node.bigint))
1646         );
1647     },
1648
1649     /**
1650      * Determines whether two tokens can safely be placed next to each other without merging into a single token
1651      * @param {Token|string} leftValue The left token. If this is a string, it will be tokenized and the last token will be used.
1652      * @param {Token|string} rightValue The right token. If this is a string, it will be tokenized and the first token will be used.
1653      * @returns {boolean} If the tokens cannot be safely placed next to each other, returns `false`. If the tokens can be placed
1654      * next to each other, behavior is undefined (although it should return `true` in most cases).
1655      */
1656     canTokensBeAdjacent(leftValue, rightValue) {
1657         const espreeOptions = {
1658             ecmaVersion: espree.latestEcmaVersion,
1659             comment: true,
1660             range: true
1661         };
1662
1663         let leftToken;
1664
1665         if (typeof leftValue === "string") {
1666             let tokens;
1667
1668             try {
1669                 tokens = espree.tokenize(leftValue, espreeOptions);
1670             } catch {
1671                 return false;
1672             }
1673
1674             const comments = tokens.comments;
1675
1676             leftToken = tokens[tokens.length - 1];
1677             if (comments.length) {
1678                 const lastComment = comments[comments.length - 1];
1679
1680                 if (lastComment.range[0] > leftToken.range[0]) {
1681                     leftToken = lastComment;
1682                 }
1683             }
1684         } else {
1685             leftToken = leftValue;
1686         }
1687
1688         if (leftToken.type === "Shebang") {
1689             return false;
1690         }
1691
1692         let rightToken;
1693
1694         if (typeof rightValue === "string") {
1695             let tokens;
1696
1697             try {
1698                 tokens = espree.tokenize(rightValue, espreeOptions);
1699             } catch {
1700                 return false;
1701             }
1702
1703             const comments = tokens.comments;
1704
1705             rightToken = tokens[0];
1706             if (comments.length) {
1707                 const firstComment = comments[0];
1708
1709                 if (firstComment.range[0] < rightToken.range[0]) {
1710                     rightToken = firstComment;
1711                 }
1712             }
1713         } else {
1714             rightToken = rightValue;
1715         }
1716
1717         if (leftToken.type === "Punctuator" || rightToken.type === "Punctuator") {
1718             if (leftToken.type === "Punctuator" && rightToken.type === "Punctuator") {
1719                 const PLUS_TOKENS = new Set(["+", "++"]);
1720                 const MINUS_TOKENS = new Set(["-", "--"]);
1721
1722                 return !(
1723                     PLUS_TOKENS.has(leftToken.value) && PLUS_TOKENS.has(rightToken.value) ||
1724                     MINUS_TOKENS.has(leftToken.value) && MINUS_TOKENS.has(rightToken.value)
1725                 );
1726             }
1727             if (leftToken.type === "Punctuator" && leftToken.value === "/") {
1728                 return !["Block", "Line", "RegularExpression"].includes(rightToken.type);
1729             }
1730             return true;
1731         }
1732
1733         if (
1734             leftToken.type === "String" || rightToken.type === "String" ||
1735             leftToken.type === "Template" || rightToken.type === "Template"
1736         ) {
1737             return true;
1738         }
1739
1740         if (leftToken.type !== "Numeric" && rightToken.type === "Numeric" && rightToken.value.startsWith(".")) {
1741             return true;
1742         }
1743
1744         if (leftToken.type === "Block" || rightToken.type === "Block" || rightToken.type === "Line") {
1745             return true;
1746         }
1747
1748         return false;
1749     },
1750
1751     /**
1752      * Get the `loc` object of a given name in a `/*globals` directive comment.
1753      * @param {SourceCode} sourceCode The source code to convert index to loc.
1754      * @param {Comment} comment The `/*globals` directive comment which include the name.
1755      * @param {string} name The name to find.
1756      * @returns {SourceLocation} The `loc` object.
1757      */
1758     getNameLocationInGlobalDirectiveComment(sourceCode, comment, name) {
1759         const namePattern = new RegExp(`[\\s,]${escapeRegExp(name)}(?:$|[\\s,:])`, "gu");
1760
1761         // To ignore the first text "global".
1762         namePattern.lastIndex = comment.value.indexOf("global") + 6;
1763
1764         // Search a given variable name.
1765         const match = namePattern.exec(comment.value);
1766
1767         // Convert the index to loc.
1768         const start = sourceCode.getLocFromIndex(
1769             comment.range[0] +
1770             "/*".length +
1771             (match ? match.index + 1 : 0)
1772         );
1773         const end = {
1774             line: start.line,
1775             column: start.column + (match ? name.length : 1)
1776         };
1777
1778         return { start, end };
1779     },
1780
1781     /**
1782      * Determines whether the given raw string contains an octal escape sequence
1783      * or a non-octal decimal escape sequence ("\8", "\9").
1784      *
1785      * "\1", "\2" ... "\7", "\8", "\9"
1786      * "\00", "\01" ... "\07", "\08", "\09"
1787      *
1788      * "\0", when not followed by a digit, is not an octal escape sequence.
1789      * @param {string} rawString A string in its raw representation.
1790      * @returns {boolean} `true` if the string contains at least one octal escape sequence
1791      * or at least one non-octal decimal escape sequence.
1792      */
1793     hasOctalOrNonOctalDecimalEscapeSequence(rawString) {
1794         return OCTAL_OR_NON_OCTAL_DECIMAL_ESCAPE_PATTERN.test(rawString);
1795     },
1796
1797     isLogicalExpression,
1798     isCoalesceExpression,
1799     isMixedLogicalAndCoalesceExpressions,
1800     isNullLiteral,
1801     getStaticStringValue,
1802     getStaticPropertyName,
1803     skipChainExpression,
1804     isSpecificId,
1805     isSpecificMemberAccess,
1806     equalLiteralValue,
1807     isSameReference,
1808     isLogicalAssignmentOperator
1809 };