| /** | 
|  * @fileoverview Object to handle access and retrieval of tokens. | 
|  * @author Brandon Mills | 
|  */ | 
| "use strict"; | 
|   | 
| //------------------------------------------------------------------------------ | 
| // Requirements | 
| //------------------------------------------------------------------------------ | 
|   | 
| const assert = require("assert"); | 
| const { isCommentToken } = require("eslint-utils"); | 
| const cursors = require("./cursors"); | 
| const ForwardTokenCursor = require("./forward-token-cursor"); | 
| const PaddedTokenCursor = require("./padded-token-cursor"); | 
| const utils = require("./utils"); | 
|   | 
| //------------------------------------------------------------------------------ | 
| // Helpers | 
| //------------------------------------------------------------------------------ | 
|   | 
| const TOKENS = Symbol("tokens"); | 
| const COMMENTS = Symbol("comments"); | 
| const INDEX_MAP = Symbol("indexMap"); | 
|   | 
| /** | 
|  * Creates the map from locations to indices in `tokens`. | 
|  * | 
|  * The first/last location of tokens is mapped to the index of the token. | 
|  * The first/last location of comments is mapped to the index of the next token of each comment. | 
|  * @param {Token[]} tokens The array of tokens. | 
|  * @param {Comment[]} comments The array of comments. | 
|  * @returns {Object} The map from locations to indices in `tokens`. | 
|  * @private | 
|  */ | 
| function createIndexMap(tokens, comments) { | 
|     const map = Object.create(null); | 
|     let tokenIndex = 0; | 
|     let commentIndex = 0; | 
|     let nextStart = 0; | 
|     let range = null; | 
|   | 
|     while (tokenIndex < tokens.length || commentIndex < comments.length) { | 
|         nextStart = (commentIndex < comments.length) ? comments[commentIndex].range[0] : Number.MAX_SAFE_INTEGER; | 
|         while (tokenIndex < tokens.length && (range = tokens[tokenIndex].range)[0] < nextStart) { | 
|             map[range[0]] = tokenIndex; | 
|             map[range[1] - 1] = tokenIndex; | 
|             tokenIndex += 1; | 
|         } | 
|   | 
|         nextStart = (tokenIndex < tokens.length) ? tokens[tokenIndex].range[0] : Number.MAX_SAFE_INTEGER; | 
|         while (commentIndex < comments.length && (range = comments[commentIndex].range)[0] < nextStart) { | 
|             map[range[0]] = tokenIndex; | 
|             map[range[1] - 1] = tokenIndex; | 
|             commentIndex += 1; | 
|         } | 
|     } | 
|   | 
|     return map; | 
| } | 
|   | 
| /** | 
|  * Creates the cursor iterates tokens with options. | 
|  * @param {CursorFactory} factory The cursor factory to initialize cursor. | 
|  * @param {Token[]} tokens The array of tokens. | 
|  * @param {Comment[]} comments The array of comments. | 
|  * @param {Object} indexMap The map from locations to indices in `tokens`. | 
|  * @param {number} startLoc The start location of the iteration range. | 
|  * @param {number} endLoc The end location of the iteration range. | 
|  * @param {number|Function|Object} [opts=0] The option object. If this is a number then it's `opts.skip`. If this is a function then it's `opts.filter`. | 
|  * @param {boolean} [opts.includeComments=false] The flag to iterate comments as well. | 
|  * @param {Function|null} [opts.filter=null] The predicate function to choose tokens. | 
|  * @param {number} [opts.skip=0] The count of tokens the cursor skips. | 
|  * @returns {Cursor} The created cursor. | 
|  * @private | 
|  */ | 
| function createCursorWithSkip(factory, tokens, comments, indexMap, startLoc, endLoc, opts) { | 
|     let includeComments = false; | 
|     let skip = 0; | 
|     let filter = null; | 
|   | 
|     if (typeof opts === "number") { | 
|         skip = opts | 0; | 
|     } else if (typeof opts === "function") { | 
|         filter = opts; | 
|     } else if (opts) { | 
|         includeComments = !!opts.includeComments; | 
|         skip = opts.skip | 0; | 
|         filter = opts.filter || null; | 
|     } | 
|     assert(skip >= 0, "options.skip should be zero or a positive integer."); | 
|     assert(!filter || typeof filter === "function", "options.filter should be a function."); | 
|   | 
|     return factory.createCursor(tokens, comments, indexMap, startLoc, endLoc, includeComments, filter, skip, -1); | 
| } | 
|   | 
| /** | 
|  * Creates the cursor iterates tokens with options. | 
|  * @param {CursorFactory} factory The cursor factory to initialize cursor. | 
|  * @param {Token[]} tokens The array of tokens. | 
|  * @param {Comment[]} comments The array of comments. | 
|  * @param {Object} indexMap The map from locations to indices in `tokens`. | 
|  * @param {number} startLoc The start location of the iteration range. | 
|  * @param {number} endLoc The end location of the iteration range. | 
|  * @param {number|Function|Object} [opts=0] The option object. If this is a number then it's `opts.count`. If this is a function then it's `opts.filter`. | 
|  * @param {boolean} [opts.includeComments] The flag to iterate comments as well. | 
|  * @param {Function|null} [opts.filter=null] The predicate function to choose tokens. | 
|  * @param {number} [opts.count=0] The maximum count of tokens the cursor iterates. Zero is no iteration for backward compatibility. | 
|  * @returns {Cursor} The created cursor. | 
|  * @private | 
|  */ | 
| function createCursorWithCount(factory, tokens, comments, indexMap, startLoc, endLoc, opts) { | 
|     let includeComments = false; | 
|     let count = 0; | 
|     let countExists = false; | 
|     let filter = null; | 
|   | 
|     if (typeof opts === "number") { | 
|         count = opts | 0; | 
|         countExists = true; | 
|     } else if (typeof opts === "function") { | 
|         filter = opts; | 
|     } else if (opts) { | 
|         includeComments = !!opts.includeComments; | 
|         count = opts.count | 0; | 
|         countExists = typeof opts.count === "number"; | 
|         filter = opts.filter || null; | 
|     } | 
|     assert(count >= 0, "options.count should be zero or a positive integer."); | 
|     assert(!filter || typeof filter === "function", "options.filter should be a function."); | 
|   | 
|     return factory.createCursor(tokens, comments, indexMap, startLoc, endLoc, includeComments, filter, 0, countExists ? count : -1); | 
| } | 
|   | 
| /** | 
|  * Creates the cursor iterates tokens with options. | 
|  * This is overload function of the below. | 
|  * @param {Token[]} tokens The array of tokens. | 
|  * @param {Comment[]} comments The array of comments. | 
|  * @param {Object} indexMap The map from locations to indices in `tokens`. | 
|  * @param {number} startLoc The start location of the iteration range. | 
|  * @param {number} endLoc The end location of the iteration range. | 
|  * @param {Function|Object} opts The option object. If this is a function then it's `opts.filter`. | 
|  * @param {boolean} [opts.includeComments] The flag to iterate comments as well. | 
|  * @param {Function|null} [opts.filter=null] The predicate function to choose tokens. | 
|  * @param {number} [opts.count=0] The maximum count of tokens the cursor iterates. Zero is no iteration for backward compatibility. | 
|  * @returns {Cursor} The created cursor. | 
|  * @private | 
|  */ | 
| /** | 
|  * Creates the cursor iterates tokens with options. | 
|  * @param {Token[]} tokens The array of tokens. | 
|  * @param {Comment[]} comments The array of comments. | 
|  * @param {Object} indexMap The map from locations to indices in `tokens`. | 
|  * @param {number} startLoc The start location of the iteration range. | 
|  * @param {number} endLoc The end location of the iteration range. | 
|  * @param {number} [beforeCount=0] The number of tokens before the node to retrieve. | 
|  * @param {boolean} [afterCount=0] The number of tokens after the node to retrieve. | 
|  * @returns {Cursor} The created cursor. | 
|  * @private | 
|  */ | 
| function createCursorWithPadding(tokens, comments, indexMap, startLoc, endLoc, beforeCount, afterCount) { | 
|     if (typeof beforeCount === "undefined" && typeof afterCount === "undefined") { | 
|         return new ForwardTokenCursor(tokens, comments, indexMap, startLoc, endLoc); | 
|     } | 
|     if (typeof beforeCount === "number" || typeof beforeCount === "undefined") { | 
|         return new PaddedTokenCursor(tokens, comments, indexMap, startLoc, endLoc, beforeCount | 0, afterCount | 0); | 
|     } | 
|     return createCursorWithCount(cursors.forward, tokens, comments, indexMap, startLoc, endLoc, beforeCount); | 
| } | 
|   | 
| /** | 
|  * Gets comment tokens that are adjacent to the current cursor position. | 
|  * @param {Cursor} cursor A cursor instance. | 
|  * @returns {Array} An array of comment tokens adjacent to the current cursor position. | 
|  * @private | 
|  */ | 
| function getAdjacentCommentTokensFromCursor(cursor) { | 
|     const tokens = []; | 
|     let currentToken = cursor.getOneToken(); | 
|   | 
|     while (currentToken && isCommentToken(currentToken)) { | 
|         tokens.push(currentToken); | 
|         currentToken = cursor.getOneToken(); | 
|     } | 
|   | 
|     return tokens; | 
| } | 
|   | 
| //------------------------------------------------------------------------------ | 
| // Exports | 
| //------------------------------------------------------------------------------ | 
|   | 
| /** | 
|  * The token store. | 
|  * | 
|  * This class provides methods to get tokens by locations as fast as possible. | 
|  * The methods are a part of public API, so we should be careful if it changes this class. | 
|  * | 
|  * People can get tokens in O(1) by the hash map which is mapping from the location of tokens/comments to tokens. | 
|  * Also people can get a mix of tokens and comments in O(log k), the k is the number of comments. | 
|  * Assuming that comments to be much fewer than tokens, this does not make hash map from token's locations to comments to reduce memory cost. | 
|  * This uses binary-searching instead for comments. | 
|  */ | 
| module.exports = class TokenStore { | 
|   | 
|     /** | 
|      * Initializes this token store. | 
|      * @param {Token[]} tokens The array of tokens. | 
|      * @param {Comment[]} comments The array of comments. | 
|      */ | 
|     constructor(tokens, comments) { | 
|         this[TOKENS] = tokens; | 
|         this[COMMENTS] = comments; | 
|         this[INDEX_MAP] = createIndexMap(tokens, comments); | 
|     } | 
|   | 
|     //-------------------------------------------------------------------------- | 
|     // Gets single token. | 
|     //-------------------------------------------------------------------------- | 
|   | 
|     /** | 
|      * Gets the token starting at the specified index. | 
|      * @param {number} offset Index of the start of the token's range. | 
|      * @param {Object} [options=0] The option object. | 
|      * @param {boolean} [options.includeComments=false] The flag to iterate comments as well. | 
|      * @returns {Token|null} The token starting at index, or null if no such token. | 
|      */ | 
|     getTokenByRangeStart(offset, options) { | 
|         const includeComments = options && options.includeComments; | 
|         const token = cursors.forward.createBaseCursor( | 
|             this[TOKENS], | 
|             this[COMMENTS], | 
|             this[INDEX_MAP], | 
|             offset, | 
|             -1, | 
|             includeComments | 
|         ).getOneToken(); | 
|   | 
|         if (token && token.range[0] === offset) { | 
|             return token; | 
|         } | 
|         return null; | 
|     } | 
|   | 
|     /** | 
|      * Gets the first token of the given node. | 
|      * @param {ASTNode} node The AST node. | 
|      * @param {number|Function|Object} [options=0] The option object. If this is a number then it's `options.skip`. If this is a function then it's `options.filter`. | 
|      * @param {boolean} [options.includeComments=false] The flag to iterate comments as well. | 
|      * @param {Function|null} [options.filter=null] The predicate function to choose tokens. | 
|      * @param {number} [options.skip=0] The count of tokens the cursor skips. | 
|      * @returns {Token|null} An object representing the token. | 
|      */ | 
|     getFirstToken(node, options) { | 
|         return createCursorWithSkip( | 
|             cursors.forward, | 
|             this[TOKENS], | 
|             this[COMMENTS], | 
|             this[INDEX_MAP], | 
|             node.range[0], | 
|             node.range[1], | 
|             options | 
|         ).getOneToken(); | 
|     } | 
|   | 
|     /** | 
|      * Gets the last token of the given node. | 
|      * @param {ASTNode} node The AST node. | 
|      * @param {number|Function|Object} [options=0] The option object. Same options as getFirstToken() | 
|      * @returns {Token|null} An object representing the token. | 
|      */ | 
|     getLastToken(node, options) { | 
|         return createCursorWithSkip( | 
|             cursors.backward, | 
|             this[TOKENS], | 
|             this[COMMENTS], | 
|             this[INDEX_MAP], | 
|             node.range[0], | 
|             node.range[1], | 
|             options | 
|         ).getOneToken(); | 
|     } | 
|   | 
|     /** | 
|      * Gets the token that precedes a given node or token. | 
|      * @param {ASTNode|Token|Comment} node The AST node or token. | 
|      * @param {number|Function|Object} [options=0] The option object. Same options as getFirstToken() | 
|      * @returns {Token|null} An object representing the token. | 
|      */ | 
|     getTokenBefore(node, options) { | 
|         return createCursorWithSkip( | 
|             cursors.backward, | 
|             this[TOKENS], | 
|             this[COMMENTS], | 
|             this[INDEX_MAP], | 
|             -1, | 
|             node.range[0], | 
|             options | 
|         ).getOneToken(); | 
|     } | 
|   | 
|     /** | 
|      * Gets the token that follows a given node or token. | 
|      * @param {ASTNode|Token|Comment} node The AST node or token. | 
|      * @param {number|Function|Object} [options=0] The option object. Same options as getFirstToken() | 
|      * @returns {Token|null} An object representing the token. | 
|      */ | 
|     getTokenAfter(node, options) { | 
|         return createCursorWithSkip( | 
|             cursors.forward, | 
|             this[TOKENS], | 
|             this[COMMENTS], | 
|             this[INDEX_MAP], | 
|             node.range[1], | 
|             -1, | 
|             options | 
|         ).getOneToken(); | 
|     } | 
|   | 
|     /** | 
|      * Gets the first token between two non-overlapping nodes. | 
|      * @param {ASTNode|Token|Comment} left Node before the desired token range. | 
|      * @param {ASTNode|Token|Comment} right Node after the desired token range. | 
|      * @param {number|Function|Object} [options=0] The option object. Same options as getFirstToken() | 
|      * @returns {Token|null} An object representing the token. | 
|      */ | 
|     getFirstTokenBetween(left, right, options) { | 
|         return createCursorWithSkip( | 
|             cursors.forward, | 
|             this[TOKENS], | 
|             this[COMMENTS], | 
|             this[INDEX_MAP], | 
|             left.range[1], | 
|             right.range[0], | 
|             options | 
|         ).getOneToken(); | 
|     } | 
|   | 
|     /** | 
|      * Gets the last token between two non-overlapping nodes. | 
|      * @param {ASTNode|Token|Comment} left Node before the desired token range. | 
|      * @param {ASTNode|Token|Comment} right Node after the desired token range. | 
|      * @param {number|Function|Object} [options=0] The option object. Same options as getFirstToken() | 
|      * @returns {Token|null} An object representing the token. | 
|      */ | 
|     getLastTokenBetween(left, right, options) { | 
|         return createCursorWithSkip( | 
|             cursors.backward, | 
|             this[TOKENS], | 
|             this[COMMENTS], | 
|             this[INDEX_MAP], | 
|             left.range[1], | 
|             right.range[0], | 
|             options | 
|         ).getOneToken(); | 
|     } | 
|   | 
|     /** | 
|      * Gets the token that precedes a given node or token in the token stream. | 
|      * This is defined for backward compatibility. Use `includeComments` option instead. | 
|      * TODO: We have a plan to remove this in a future major version. | 
|      * @param {ASTNode|Token|Comment} node The AST node or token. | 
|      * @param {number} [skip=0] A number of tokens to skip. | 
|      * @returns {Token|null} An object representing the token. | 
|      * @deprecated | 
|      */ | 
|     getTokenOrCommentBefore(node, skip) { | 
|         return this.getTokenBefore(node, { includeComments: true, skip }); | 
|     } | 
|   | 
|     /** | 
|      * Gets the token that follows a given node or token in the token stream. | 
|      * This is defined for backward compatibility. Use `includeComments` option instead. | 
|      * TODO: We have a plan to remove this in a future major version. | 
|      * @param {ASTNode|Token|Comment} node The AST node or token. | 
|      * @param {number} [skip=0] A number of tokens to skip. | 
|      * @returns {Token|null} An object representing the token. | 
|      * @deprecated | 
|      */ | 
|     getTokenOrCommentAfter(node, skip) { | 
|         return this.getTokenAfter(node, { includeComments: true, skip }); | 
|     } | 
|   | 
|     //-------------------------------------------------------------------------- | 
|     // Gets multiple tokens. | 
|     //-------------------------------------------------------------------------- | 
|   | 
|     /** | 
|      * Gets the first `count` tokens of the given node. | 
|      * @param {ASTNode} node The AST node. | 
|      * @param {number|Function|Object} [options=0] The option object. If this is a number then it's `options.count`. If this is a function then it's `options.filter`. | 
|      * @param {boolean} [options.includeComments=false] The flag to iterate comments as well. | 
|      * @param {Function|null} [options.filter=null] The predicate function to choose tokens. | 
|      * @param {number} [options.count=0] The maximum count of tokens the cursor iterates. | 
|      * @returns {Token[]} Tokens. | 
|      */ | 
|     getFirstTokens(node, options) { | 
|         return createCursorWithCount( | 
|             cursors.forward, | 
|             this[TOKENS], | 
|             this[COMMENTS], | 
|             this[INDEX_MAP], | 
|             node.range[0], | 
|             node.range[1], | 
|             options | 
|         ).getAllTokens(); | 
|     } | 
|   | 
|     /** | 
|      * Gets the last `count` tokens of the given node. | 
|      * @param {ASTNode} node The AST node. | 
|      * @param {number|Function|Object} [options=0] The option object. Same options as getFirstTokens() | 
|      * @returns {Token[]} Tokens. | 
|      */ | 
|     getLastTokens(node, options) { | 
|         return createCursorWithCount( | 
|             cursors.backward, | 
|             this[TOKENS], | 
|             this[COMMENTS], | 
|             this[INDEX_MAP], | 
|             node.range[0], | 
|             node.range[1], | 
|             options | 
|         ).getAllTokens().reverse(); | 
|     } | 
|   | 
|     /** | 
|      * Gets the `count` tokens that precedes a given node or token. | 
|      * @param {ASTNode|Token|Comment} node The AST node or token. | 
|      * @param {number|Function|Object} [options=0] The option object. Same options as getFirstTokens() | 
|      * @returns {Token[]} Tokens. | 
|      */ | 
|     getTokensBefore(node, options) { | 
|         return createCursorWithCount( | 
|             cursors.backward, | 
|             this[TOKENS], | 
|             this[COMMENTS], | 
|             this[INDEX_MAP], | 
|             -1, | 
|             node.range[0], | 
|             options | 
|         ).getAllTokens().reverse(); | 
|     } | 
|   | 
|     /** | 
|      * Gets the `count` tokens that follows a given node or token. | 
|      * @param {ASTNode|Token|Comment} node The AST node or token. | 
|      * @param {number|Function|Object} [options=0] The option object. Same options as getFirstTokens() | 
|      * @returns {Token[]} Tokens. | 
|      */ | 
|     getTokensAfter(node, options) { | 
|         return createCursorWithCount( | 
|             cursors.forward, | 
|             this[TOKENS], | 
|             this[COMMENTS], | 
|             this[INDEX_MAP], | 
|             node.range[1], | 
|             -1, | 
|             options | 
|         ).getAllTokens(); | 
|     } | 
|   | 
|     /** | 
|      * Gets the first `count` tokens between two non-overlapping nodes. | 
|      * @param {ASTNode|Token|Comment} left Node before the desired token range. | 
|      * @param {ASTNode|Token|Comment} right Node after the desired token range. | 
|      * @param {number|Function|Object} [options=0] The option object. Same options as getFirstTokens() | 
|      * @returns {Token[]} Tokens between left and right. | 
|      */ | 
|     getFirstTokensBetween(left, right, options) { | 
|         return createCursorWithCount( | 
|             cursors.forward, | 
|             this[TOKENS], | 
|             this[COMMENTS], | 
|             this[INDEX_MAP], | 
|             left.range[1], | 
|             right.range[0], | 
|             options | 
|         ).getAllTokens(); | 
|     } | 
|   | 
|     /** | 
|      * Gets the last `count` tokens between two non-overlapping nodes. | 
|      * @param {ASTNode|Token|Comment} left Node before the desired token range. | 
|      * @param {ASTNode|Token|Comment} right Node after the desired token range. | 
|      * @param {number|Function|Object} [options=0] The option object. Same options as getFirstTokens() | 
|      * @returns {Token[]} Tokens between left and right. | 
|      */ | 
|     getLastTokensBetween(left, right, options) { | 
|         return createCursorWithCount( | 
|             cursors.backward, | 
|             this[TOKENS], | 
|             this[COMMENTS], | 
|             this[INDEX_MAP], | 
|             left.range[1], | 
|             right.range[0], | 
|             options | 
|         ).getAllTokens().reverse(); | 
|     } | 
|   | 
|     /** | 
|      * Gets all tokens that are related to the given node. | 
|      * @param {ASTNode} node The AST node. | 
|      * @param {Function|Object} options The option object. If this is a function then it's `options.filter`. | 
|      * @param {boolean} [options.includeComments=false] The flag to iterate comments as well. | 
|      * @param {Function|null} [options.filter=null] The predicate function to choose tokens. | 
|      * @param {number} [options.count=0] The maximum count of tokens the cursor iterates. | 
|      * @returns {Token[]} Array of objects representing tokens. | 
|      */ | 
|     /** | 
|      * Gets all tokens that are related to the given node. | 
|      * @param {ASTNode} node The AST node. | 
|      * @param {int} [beforeCount=0] The number of tokens before the node to retrieve. | 
|      * @param {int} [afterCount=0] The number of tokens after the node to retrieve. | 
|      * @returns {Token[]} Array of objects representing tokens. | 
|      */ | 
|     getTokens(node, beforeCount, afterCount) { | 
|         return createCursorWithPadding( | 
|             this[TOKENS], | 
|             this[COMMENTS], | 
|             this[INDEX_MAP], | 
|             node.range[0], | 
|             node.range[1], | 
|             beforeCount, | 
|             afterCount | 
|         ).getAllTokens(); | 
|     } | 
|   | 
|     /** | 
|      * Gets all of the tokens between two non-overlapping nodes. | 
|      * @param {ASTNode|Token|Comment} left Node before the desired token range. | 
|      * @param {ASTNode|Token|Comment} right Node after the desired token range. | 
|      * @param {Function|Object} options The option object. If this is a function then it's `options.filter`. | 
|      * @param {boolean} [options.includeComments=false] The flag to iterate comments as well. | 
|      * @param {Function|null} [options.filter=null] The predicate function to choose tokens. | 
|      * @param {number} [options.count=0] The maximum count of tokens the cursor iterates. | 
|      * @returns {Token[]} Tokens between left and right. | 
|      */ | 
|     /** | 
|      * Gets all of the tokens between two non-overlapping nodes. | 
|      * @param {ASTNode|Token|Comment} left Node before the desired token range. | 
|      * @param {ASTNode|Token|Comment} right Node after the desired token range. | 
|      * @param {int} [padding=0] Number of extra tokens on either side of center. | 
|      * @returns {Token[]} Tokens between left and right. | 
|      */ | 
|     getTokensBetween(left, right, padding) { | 
|         return createCursorWithPadding( | 
|             this[TOKENS], | 
|             this[COMMENTS], | 
|             this[INDEX_MAP], | 
|             left.range[1], | 
|             right.range[0], | 
|             padding, | 
|             padding | 
|         ).getAllTokens(); | 
|     } | 
|   | 
|     //-------------------------------------------------------------------------- | 
|     // Others. | 
|     //-------------------------------------------------------------------------- | 
|   | 
|     /** | 
|      * Checks whether any comments exist or not between the given 2 nodes. | 
|      * @param {ASTNode} left The node to check. | 
|      * @param {ASTNode} right The node to check. | 
|      * @returns {boolean} `true` if one or more comments exist. | 
|      */ | 
|     commentsExistBetween(left, right) { | 
|         const index = utils.search(this[COMMENTS], left.range[1]); | 
|   | 
|         return ( | 
|             index < this[COMMENTS].length && | 
|             this[COMMENTS][index].range[1] <= right.range[0] | 
|         ); | 
|     } | 
|   | 
|     /** | 
|      * Gets all comment tokens directly before the given node or token. | 
|      * @param {ASTNode|token} nodeOrToken The AST node or token to check for adjacent comment tokens. | 
|      * @returns {Array} An array of comments in occurrence order. | 
|      */ | 
|     getCommentsBefore(nodeOrToken) { | 
|         const cursor = createCursorWithCount( | 
|             cursors.backward, | 
|             this[TOKENS], | 
|             this[COMMENTS], | 
|             this[INDEX_MAP], | 
|             -1, | 
|             nodeOrToken.range[0], | 
|             { includeComments: true } | 
|         ); | 
|   | 
|         return getAdjacentCommentTokensFromCursor(cursor).reverse(); | 
|     } | 
|   | 
|     /** | 
|      * Gets all comment tokens directly after the given node or token. | 
|      * @param {ASTNode|token} nodeOrToken The AST node or token to check for adjacent comment tokens. | 
|      * @returns {Array} An array of comments in occurrence order. | 
|      */ | 
|     getCommentsAfter(nodeOrToken) { | 
|         const cursor = createCursorWithCount( | 
|             cursors.forward, | 
|             this[TOKENS], | 
|             this[COMMENTS], | 
|             this[INDEX_MAP], | 
|             nodeOrToken.range[1], | 
|             -1, | 
|             { includeComments: true } | 
|         ); | 
|   | 
|         return getAdjacentCommentTokensFromCursor(cursor); | 
|     } | 
|   | 
|     /** | 
|      * Gets all comment tokens inside the given node. | 
|      * @param {ASTNode} node The AST node to get the comments for. | 
|      * @returns {Array} An array of comments in occurrence order. | 
|      */ | 
|     getCommentsInside(node) { | 
|         return this.getTokens(node, { | 
|             includeComments: true, | 
|             filter: isCommentToken | 
|         }); | 
|     } | 
| }; |