--- /dev/null
+"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 (Object.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.isChildOptionalChain = exports.isOptionalChain = 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 semver = __importStar(require("semver"));
+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 isOptionalChain(node) {
+ return (node.type === ts_estree_1.AST_NODE_TYPES.OptionalCallExpression ||
+ node.type == ts_estree_1.AST_NODE_TYPES.OptionalMemberExpression);
+}
+exports.isOptionalChain = isOptionalChain;
+/**
+ * Returns true if the current TS version is TS 3.9
+ */
+function isTSv3dot9() {
+ return !semver.satisfies(ts.version, '< 3.9.0 || < 3.9.1-rc || < 3.9.0-beta');
+}
+/**
+ * Returns true of the child of property access expression is an optional chain
+ */
+function isChildOptionalChain(node, object) {
+ if (isOptionalChain(object) &&
+ // (x?.y).z is semantically different, and as such .z is no longer optional
+ node.expression.kind !== ts.SyntaxKind.ParenthesizedExpression) {
+ return true;
+ }
+ if (!isTSv3dot9()) {
+ return false;
+ }
+ // TS3.9 made a breaking change to how non-null works with optional chains.
+ // Pre-3.9, `x?.y!.z` means `(x?.y).z` - i.e. it essentially scrubbed the optionality from the chain
+ // Post-3.9, `x?.y!.z` means `x?.y!.z` - i.e. it just asserts that the property `y` is non-null, not the result of `x?.y`
+ if (object.type !== ts_estree_1.AST_NODE_TYPES.TSNonNullExpression ||
+ !isOptionalChain(object.expression)) {
+ return false;
+ }
+ if (
+ // make sure it's not (x.y)!.z
+ node.expression.kind === ts.SyntaxKind.NonNullExpression &&
+ node.expression.expression.kind !==
+ ts.SyntaxKind.ParenthesizedExpression) {
+ return true;
+ }
+ return false;
+}
+exports.isChildOptionalChain = isChildOptionalChain;
+/**
+ * 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
\ No newline at end of file