| "use strict"; |
| var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { |
| if (k2 === undefined) k2 = k; |
| Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); |
| }) : (function(o, m, k, k2) { |
| if (k2 === undefined) k2 = k; |
| o[k2] = m[k]; |
| })); |
| var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { |
| Object.defineProperty(o, "default", { enumerable: true, value: v }); |
| }) : function(o, v) { |
| o["default"] = v; |
| }); |
| var __importStar = (this && this.__importStar) || function (mod) { |
| if (mod && mod.__esModule) return mod; |
| var result = {}; |
| if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); |
| __setModuleDefault(result, mod); |
| return result; |
| }; |
| var __importDefault = (this && this.__importDefault) || function (mod) { |
| return (mod && mod.__esModule) ? mod : { "default": mod }; |
| }; |
| Object.defineProperty(exports, "__esModule", { value: true }); |
| exports.firstDefined = exports.nodeHasTokens = exports.createError = exports.convertTokens = exports.convertToken = exports.getTokenType = exports.isChildUnwrappableOptionalChain = exports.isChainExpression = exports.isOptional = exports.isComputedProperty = exports.unescapeStringLiteralText = exports.hasJSXAncestor = exports.findFirstMatchingAncestor = exports.findNextToken = exports.getTSNodeAccessibility = exports.getDeclarationKind = exports.isJSXToken = exports.isToken = exports.getRange = exports.canContainDirective = exports.getLocFor = exports.getLineAndCharacterFor = exports.getBinaryExpressionType = exports.isJSDocComment = exports.isComment = exports.isComma = exports.getLastModifier = exports.hasModifier = exports.isESTreeClassMember = exports.getTextForTokenKind = exports.isLogicalOperator = exports.isAssignmentOperator = void 0; |
| const unescape_1 = __importDefault(require("lodash/unescape")); |
| const ts = __importStar(require("typescript")); |
| const ts_estree_1 = require("./ts-estree"); |
| const SyntaxKind = ts.SyntaxKind; |
| const LOGICAL_OPERATORS = [ |
| SyntaxKind.BarBarToken, |
| SyntaxKind.AmpersandAmpersandToken, |
| SyntaxKind.QuestionQuestionToken, |
| ]; |
| /** |
| * Returns true if the given ts.Token is the assignment operator |
| * @param operator the operator token |
| * @returns is assignment |
| */ |
| function isAssignmentOperator(operator) { |
| return (operator.kind >= SyntaxKind.FirstAssignment && |
| operator.kind <= SyntaxKind.LastAssignment); |
| } |
| exports.isAssignmentOperator = isAssignmentOperator; |
| /** |
| * Returns true if the given ts.Token is a logical operator |
| * @param operator the operator token |
| * @returns is a logical operator |
| */ |
| function isLogicalOperator(operator) { |
| return LOGICAL_OPERATORS.includes(operator.kind); |
| } |
| exports.isLogicalOperator = isLogicalOperator; |
| /** |
| * Returns the string form of the given TSToken SyntaxKind |
| * @param kind the token's SyntaxKind |
| * @returns the token applicable token as a string |
| */ |
| function getTextForTokenKind(kind) { |
| return ts.tokenToString(kind); |
| } |
| exports.getTextForTokenKind = getTextForTokenKind; |
| /** |
| * Returns true if the given ts.Node is a valid ESTree class member |
| * @param node TypeScript AST node |
| * @returns is valid ESTree class member |
| */ |
| function isESTreeClassMember(node) { |
| return node.kind !== SyntaxKind.SemicolonClassElement; |
| } |
| exports.isESTreeClassMember = isESTreeClassMember; |
| /** |
| * Checks if a ts.Node has a modifier |
| * @param modifierKind TypeScript SyntaxKind modifier |
| * @param node TypeScript AST node |
| * @returns has the modifier specified |
| */ |
| function hasModifier(modifierKind, node) { |
| return (!!node.modifiers && |
| !!node.modifiers.length && |
| node.modifiers.some(modifier => modifier.kind === modifierKind)); |
| } |
| exports.hasModifier = hasModifier; |
| /** |
| * Get last last modifier in ast |
| * @param node TypeScript AST node |
| * @returns returns last modifier if present or null |
| */ |
| function getLastModifier(node) { |
| return ((!!node.modifiers && |
| !!node.modifiers.length && |
| node.modifiers[node.modifiers.length - 1]) || |
| null); |
| } |
| exports.getLastModifier = getLastModifier; |
| /** |
| * Returns true if the given ts.Token is a comma |
| * @param token the TypeScript token |
| * @returns is comma |
| */ |
| function isComma(token) { |
| return token.kind === SyntaxKind.CommaToken; |
| } |
| exports.isComma = isComma; |
| /** |
| * Returns true if the given ts.Node is a comment |
| * @param node the TypeScript node |
| * @returns is comment |
| */ |
| function isComment(node) { |
| return (node.kind === SyntaxKind.SingleLineCommentTrivia || |
| node.kind === SyntaxKind.MultiLineCommentTrivia); |
| } |
| exports.isComment = isComment; |
| /** |
| * Returns true if the given ts.Node is a JSDoc comment |
| * @param node the TypeScript node |
| * @returns is JSDoc comment |
| */ |
| function isJSDocComment(node) { |
| return node.kind === SyntaxKind.JSDocComment; |
| } |
| exports.isJSDocComment = isJSDocComment; |
| /** |
| * Returns the binary expression type of the given ts.Token |
| * @param operator the operator token |
| * @returns the binary expression type |
| */ |
| function getBinaryExpressionType(operator) { |
| if (isAssignmentOperator(operator)) { |
| return ts_estree_1.AST_NODE_TYPES.AssignmentExpression; |
| } |
| else if (isLogicalOperator(operator)) { |
| return ts_estree_1.AST_NODE_TYPES.LogicalExpression; |
| } |
| return ts_estree_1.AST_NODE_TYPES.BinaryExpression; |
| } |
| exports.getBinaryExpressionType = getBinaryExpressionType; |
| /** |
| * Returns line and column data for the given positions, |
| * @param pos position to check |
| * @param ast the AST object |
| * @returns line and column |
| */ |
| function getLineAndCharacterFor(pos, ast) { |
| const loc = ast.getLineAndCharacterOfPosition(pos); |
| return { |
| line: loc.line + 1, |
| column: loc.character, |
| }; |
| } |
| exports.getLineAndCharacterFor = getLineAndCharacterFor; |
| /** |
| * Returns line and column data for the given start and end positions, |
| * for the given AST |
| * @param start start data |
| * @param end end data |
| * @param ast the AST object |
| * @returns the loc data |
| */ |
| function getLocFor(start, end, ast) { |
| return { |
| start: getLineAndCharacterFor(start, ast), |
| end: getLineAndCharacterFor(end, ast), |
| }; |
| } |
| exports.getLocFor = getLocFor; |
| /** |
| * Check whatever node can contain directive |
| * @param node |
| * @returns returns true if node can contain directive |
| */ |
| function canContainDirective(node) { |
| if (node.kind === ts.SyntaxKind.Block) { |
| switch (node.parent.kind) { |
| case ts.SyntaxKind.Constructor: |
| case ts.SyntaxKind.GetAccessor: |
| case ts.SyntaxKind.SetAccessor: |
| case ts.SyntaxKind.ArrowFunction: |
| case ts.SyntaxKind.FunctionExpression: |
| case ts.SyntaxKind.FunctionDeclaration: |
| case ts.SyntaxKind.MethodDeclaration: |
| return true; |
| default: |
| return false; |
| } |
| } |
| return true; |
| } |
| exports.canContainDirective = canContainDirective; |
| /** |
| * Returns range for the given ts.Node |
| * @param node the ts.Node or ts.Token |
| * @param ast the AST object |
| * @returns the range data |
| */ |
| function getRange(node, ast) { |
| return [node.getStart(ast), node.getEnd()]; |
| } |
| exports.getRange = getRange; |
| /** |
| * Returns true if a given ts.Node is a token |
| * @param node the ts.Node |
| * @returns is a token |
| */ |
| function isToken(node) { |
| return (node.kind >= SyntaxKind.FirstToken && node.kind <= SyntaxKind.LastToken); |
| } |
| exports.isToken = isToken; |
| /** |
| * Returns true if a given ts.Node is a JSX token |
| * @param node ts.Node to be checked |
| * @returns is a JSX token |
| */ |
| function isJSXToken(node) { |
| return (node.kind >= SyntaxKind.JsxElement && node.kind <= SyntaxKind.JsxAttribute); |
| } |
| exports.isJSXToken = isJSXToken; |
| /** |
| * Returns the declaration kind of the given ts.Node |
| * @param node TypeScript AST node |
| * @returns declaration kind |
| */ |
| function getDeclarationKind(node) { |
| if (node.flags & ts.NodeFlags.Let) { |
| return 'let'; |
| } |
| if (node.flags & ts.NodeFlags.Const) { |
| return 'const'; |
| } |
| return 'var'; |
| } |
| exports.getDeclarationKind = getDeclarationKind; |
| /** |
| * Gets a ts.Node's accessibility level |
| * @param node The ts.Node |
| * @returns accessibility "public", "protected", "private", or null |
| */ |
| function getTSNodeAccessibility(node) { |
| const modifiers = node.modifiers; |
| if (!modifiers) { |
| return null; |
| } |
| for (let i = 0; i < modifiers.length; i++) { |
| const modifier = modifiers[i]; |
| switch (modifier.kind) { |
| case SyntaxKind.PublicKeyword: |
| return 'public'; |
| case SyntaxKind.ProtectedKeyword: |
| return 'protected'; |
| case SyntaxKind.PrivateKeyword: |
| return 'private'; |
| default: |
| break; |
| } |
| } |
| return null; |
| } |
| exports.getTSNodeAccessibility = getTSNodeAccessibility; |
| /** |
| * Finds the next token based on the previous one and its parent |
| * Had to copy this from TS instead of using TS's version because theirs doesn't pass the ast to getChildren |
| * @param previousToken The previous TSToken |
| * @param parent The parent TSNode |
| * @param ast The TS AST |
| * @returns the next TSToken |
| */ |
| function findNextToken(previousToken, parent, ast) { |
| return find(parent); |
| function find(n) { |
| if (ts.isToken(n) && n.pos === previousToken.end) { |
| // this is token that starts at the end of previous token - return it |
| return n; |
| } |
| return firstDefined(n.getChildren(ast), (child) => { |
| const shouldDiveInChildNode = |
| // previous token is enclosed somewhere in the child |
| (child.pos <= previousToken.pos && child.end > previousToken.end) || |
| // previous token ends exactly at the beginning of child |
| child.pos === previousToken.end; |
| return shouldDiveInChildNode && nodeHasTokens(child, ast) |
| ? find(child) |
| : undefined; |
| }); |
| } |
| } |
| exports.findNextToken = findNextToken; |
| /** |
| * Find the first matching ancestor based on the given predicate function. |
| * @param node The current ts.Node |
| * @param predicate The predicate function to apply to each checked ancestor |
| * @returns a matching parent ts.Node |
| */ |
| function findFirstMatchingAncestor(node, predicate) { |
| while (node) { |
| if (predicate(node)) { |
| return node; |
| } |
| node = node.parent; |
| } |
| return undefined; |
| } |
| exports.findFirstMatchingAncestor = findFirstMatchingAncestor; |
| /** |
| * Returns true if a given ts.Node has a JSX token within its hierarchy |
| * @param node ts.Node to be checked |
| * @returns has JSX ancestor |
| */ |
| function hasJSXAncestor(node) { |
| return !!findFirstMatchingAncestor(node, isJSXToken); |
| } |
| exports.hasJSXAncestor = hasJSXAncestor; |
| /** |
| * Unescape the text content of string literals, e.g. & -> & |
| * @param text The escaped string literal text. |
| * @returns The unescaped string literal text. |
| */ |
| function unescapeStringLiteralText(text) { |
| return unescape_1.default(text); |
| } |
| exports.unescapeStringLiteralText = unescapeStringLiteralText; |
| /** |
| * Returns true if a given ts.Node is a computed property |
| * @param node ts.Node to be checked |
| * @returns is Computed Property |
| */ |
| function isComputedProperty(node) { |
| return node.kind === SyntaxKind.ComputedPropertyName; |
| } |
| exports.isComputedProperty = isComputedProperty; |
| /** |
| * Returns true if a given ts.Node is optional (has QuestionToken) |
| * @param node ts.Node to be checked |
| * @returns is Optional |
| */ |
| function isOptional(node) { |
| return node.questionToken |
| ? node.questionToken.kind === SyntaxKind.QuestionToken |
| : false; |
| } |
| exports.isOptional = isOptional; |
| /** |
| * Returns true if the node is an optional chain node |
| */ |
| function isChainExpression(node) { |
| return node.type === ts_estree_1.AST_NODE_TYPES.ChainExpression; |
| } |
| exports.isChainExpression = isChainExpression; |
| /** |
| * Returns true of the child of property access expression is an optional chain |
| */ |
| function isChildUnwrappableOptionalChain(node, child) { |
| if (isChainExpression(child) && |
| // (x?.y).z is semantically different, and as such .z is no longer optional |
| node.expression.kind !== ts.SyntaxKind.ParenthesizedExpression) { |
| return true; |
| } |
| return false; |
| } |
| exports.isChildUnwrappableOptionalChain = isChildUnwrappableOptionalChain; |
| /** |
| * Returns the type of a given ts.Token |
| * @param token the ts.Token |
| * @returns the token type |
| */ |
| function getTokenType(token) { |
| if ('originalKeywordKind' in token && token.originalKeywordKind) { |
| if (token.originalKeywordKind === SyntaxKind.NullKeyword) { |
| return ts_estree_1.AST_TOKEN_TYPES.Null; |
| } |
| else if (token.originalKeywordKind >= SyntaxKind.FirstFutureReservedWord && |
| token.originalKeywordKind <= SyntaxKind.LastKeyword) { |
| return ts_estree_1.AST_TOKEN_TYPES.Identifier; |
| } |
| return ts_estree_1.AST_TOKEN_TYPES.Keyword; |
| } |
| if (token.kind >= SyntaxKind.FirstKeyword && |
| token.kind <= SyntaxKind.LastFutureReservedWord) { |
| if (token.kind === SyntaxKind.FalseKeyword || |
| token.kind === SyntaxKind.TrueKeyword) { |
| return ts_estree_1.AST_TOKEN_TYPES.Boolean; |
| } |
| return ts_estree_1.AST_TOKEN_TYPES.Keyword; |
| } |
| if (token.kind >= SyntaxKind.FirstPunctuation && |
| token.kind <= SyntaxKind.LastBinaryOperator) { |
| return ts_estree_1.AST_TOKEN_TYPES.Punctuator; |
| } |
| if (token.kind >= SyntaxKind.NoSubstitutionTemplateLiteral && |
| token.kind <= SyntaxKind.TemplateTail) { |
| return ts_estree_1.AST_TOKEN_TYPES.Template; |
| } |
| switch (token.kind) { |
| case SyntaxKind.NumericLiteral: |
| return ts_estree_1.AST_TOKEN_TYPES.Numeric; |
| case SyntaxKind.JsxText: |
| return ts_estree_1.AST_TOKEN_TYPES.JSXText; |
| case SyntaxKind.StringLiteral: |
| // A TypeScript-StringLiteral token with a TypeScript-JsxAttribute or TypeScript-JsxElement parent, |
| // must actually be an ESTree-JSXText token |
| if (token.parent && |
| (token.parent.kind === SyntaxKind.JsxAttribute || |
| token.parent.kind === SyntaxKind.JsxElement)) { |
| return ts_estree_1.AST_TOKEN_TYPES.JSXText; |
| } |
| return ts_estree_1.AST_TOKEN_TYPES.String; |
| case SyntaxKind.RegularExpressionLiteral: |
| return ts_estree_1.AST_TOKEN_TYPES.RegularExpression; |
| case SyntaxKind.Identifier: |
| case SyntaxKind.ConstructorKeyword: |
| case SyntaxKind.GetKeyword: |
| case SyntaxKind.SetKeyword: |
| // falls through |
| default: |
| } |
| // Some JSX tokens have to be determined based on their parent |
| if (token.parent && token.kind === SyntaxKind.Identifier) { |
| if (isJSXToken(token.parent)) { |
| return ts_estree_1.AST_TOKEN_TYPES.JSXIdentifier; |
| } |
| if (token.parent.kind === SyntaxKind.PropertyAccessExpression && |
| hasJSXAncestor(token)) { |
| return ts_estree_1.AST_TOKEN_TYPES.JSXIdentifier; |
| } |
| } |
| return ts_estree_1.AST_TOKEN_TYPES.Identifier; |
| } |
| exports.getTokenType = getTokenType; |
| /** |
| * Extends and formats a given ts.Token, for a given AST |
| * @param token the ts.Token |
| * @param ast the AST object |
| * @returns the converted Token |
| */ |
| function convertToken(token, ast) { |
| const start = token.kind === SyntaxKind.JsxText |
| ? token.getFullStart() |
| : token.getStart(ast); |
| const end = token.getEnd(); |
| const value = ast.text.slice(start, end); |
| const tokenType = getTokenType(token); |
| if (tokenType === ts_estree_1.AST_TOKEN_TYPES.RegularExpression) { |
| return { |
| type: tokenType, |
| value, |
| range: [start, end], |
| loc: getLocFor(start, end, ast), |
| regex: { |
| pattern: value.slice(1, value.lastIndexOf('/')), |
| flags: value.slice(value.lastIndexOf('/') + 1), |
| }, |
| }; |
| } |
| else { |
| return { |
| type: tokenType, |
| value, |
| range: [start, end], |
| loc: getLocFor(start, end, ast), |
| }; |
| } |
| } |
| exports.convertToken = convertToken; |
| /** |
| * Converts all tokens for the given AST |
| * @param ast the AST object |
| * @returns the converted Tokens |
| */ |
| function convertTokens(ast) { |
| const result = []; |
| /** |
| * @param node the ts.Node |
| */ |
| function walk(node) { |
| // TypeScript generates tokens for types in JSDoc blocks. Comment tokens |
| // and their children should not be walked or added to the resulting tokens list. |
| if (isComment(node) || isJSDocComment(node)) { |
| return; |
| } |
| if (isToken(node) && node.kind !== SyntaxKind.EndOfFileToken) { |
| const converted = convertToken(node, ast); |
| if (converted) { |
| result.push(converted); |
| } |
| } |
| else { |
| node.getChildren(ast).forEach(walk); |
| } |
| } |
| walk(ast); |
| return result; |
| } |
| exports.convertTokens = convertTokens; |
| /** |
| * @param ast the AST object |
| * @param start the index at which the error starts |
| * @param message the error message |
| * @returns converted error object |
| */ |
| function createError(ast, start, message) { |
| const loc = ast.getLineAndCharacterOfPosition(start); |
| return { |
| index: start, |
| lineNumber: loc.line + 1, |
| column: loc.character, |
| message, |
| }; |
| } |
| exports.createError = createError; |
| /** |
| * @param n the TSNode |
| * @param ast the TS AST |
| */ |
| function nodeHasTokens(n, ast) { |
| // If we have a token or node that has a non-zero width, it must have tokens. |
| // Note: getWidth() does not take trivia into account. |
| return n.kind === SyntaxKind.EndOfFileToken |
| ? // eslint-disable-next-line @typescript-eslint/no-explicit-any |
| !!n.jsDoc |
| : n.getWidth(ast) !== 0; |
| } |
| exports.nodeHasTokens = nodeHasTokens; |
| /** |
| * Like `forEach`, but suitable for use with numbers and strings (which may be falsy). |
| * @template T |
| * @template U |
| * @param array |
| * @param callback |
| */ |
| function firstDefined(array, callback) { |
| if (array === undefined) { |
| return undefined; |
| } |
| for (let i = 0; i < array.length; i++) { |
| const result = callback(array[i], i); |
| if (result !== undefined) { |
| return result; |
| } |
| } |
| return undefined; |
| } |
| exports.firstDefined = firstDefined; |
| //# sourceMappingURL=node-utils.js.map |