2 var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 if (k2 === undefined) k2 = k;
4 Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5 }) : (function(o, m, k, k2) {
6 if (k2 === undefined) k2 = k;
9 var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10 Object.defineProperty(o, "default", { enumerable: true, value: v });
14 var __importStar = (this && this.__importStar) || function (mod) {
15 if (mod && mod.__esModule) return mod;
17 if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18 __setModuleDefault(result, mod);
21 var __importDefault = (this && this.__importDefault) || function (mod) {
22 return (mod && mod.__esModule) ? mod : { "default": mod };
24 Object.defineProperty(exports, "__esModule", { value: true });
25 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;
26 const unescape_1 = __importDefault(require("lodash/unescape"));
27 const ts = __importStar(require("typescript"));
28 const ts_estree_1 = require("./ts-estree");
29 const version_check_1 = require("./version-check");
30 const SyntaxKind = ts.SyntaxKind;
31 const LOGICAL_OPERATORS = [
32 SyntaxKind.BarBarToken,
33 SyntaxKind.AmpersandAmpersandToken,
34 SyntaxKind.QuestionQuestionToken,
37 * Returns true if the given ts.Token is the assignment operator
38 * @param operator the operator token
39 * @returns is assignment
41 function isAssignmentOperator(operator) {
42 return (operator.kind >= SyntaxKind.FirstAssignment &&
43 operator.kind <= SyntaxKind.LastAssignment);
45 exports.isAssignmentOperator = isAssignmentOperator;
47 * Returns true if the given ts.Token is a logical operator
48 * @param operator the operator token
49 * @returns is a logical operator
51 function isLogicalOperator(operator) {
52 return LOGICAL_OPERATORS.includes(operator.kind);
54 exports.isLogicalOperator = isLogicalOperator;
56 * Returns the string form of the given TSToken SyntaxKind
57 * @param kind the token's SyntaxKind
58 * @returns the token applicable token as a string
60 function getTextForTokenKind(kind) {
61 return ts.tokenToString(kind);
63 exports.getTextForTokenKind = getTextForTokenKind;
65 * Returns true if the given ts.Node is a valid ESTree class member
66 * @param node TypeScript AST node
67 * @returns is valid ESTree class member
69 function isESTreeClassMember(node) {
70 return node.kind !== SyntaxKind.SemicolonClassElement;
72 exports.isESTreeClassMember = isESTreeClassMember;
74 * Checks if a ts.Node has a modifier
75 * @param modifierKind TypeScript SyntaxKind modifier
76 * @param node TypeScript AST node
77 * @returns has the modifier specified
79 function hasModifier(modifierKind, node) {
80 return (!!node.modifiers &&
81 !!node.modifiers.length &&
82 node.modifiers.some(modifier => modifier.kind === modifierKind));
84 exports.hasModifier = hasModifier;
86 * Get last last modifier in ast
87 * @param node TypeScript AST node
88 * @returns returns last modifier if present or null
90 function getLastModifier(node) {
91 return ((!!node.modifiers &&
92 !!node.modifiers.length &&
93 node.modifiers[node.modifiers.length - 1]) ||
96 exports.getLastModifier = getLastModifier;
98 * Returns true if the given ts.Token is a comma
99 * @param token the TypeScript token
102 function isComma(token) {
103 return token.kind === SyntaxKind.CommaToken;
105 exports.isComma = isComma;
107 * Returns true if the given ts.Node is a comment
108 * @param node the TypeScript node
109 * @returns is comment
111 function isComment(node) {
112 return (node.kind === SyntaxKind.SingleLineCommentTrivia ||
113 node.kind === SyntaxKind.MultiLineCommentTrivia);
115 exports.isComment = isComment;
117 * Returns true if the given ts.Node is a JSDoc comment
118 * @param node the TypeScript node
119 * @returns is JSDoc comment
121 function isJSDocComment(node) {
122 return node.kind === SyntaxKind.JSDocComment;
124 exports.isJSDocComment = isJSDocComment;
126 * Returns the binary expression type of the given ts.Token
127 * @param operator the operator token
128 * @returns the binary expression type
130 function getBinaryExpressionType(operator) {
131 if (isAssignmentOperator(operator)) {
132 return ts_estree_1.AST_NODE_TYPES.AssignmentExpression;
134 else if (isLogicalOperator(operator)) {
135 return ts_estree_1.AST_NODE_TYPES.LogicalExpression;
137 return ts_estree_1.AST_NODE_TYPES.BinaryExpression;
139 exports.getBinaryExpressionType = getBinaryExpressionType;
141 * Returns line and column data for the given positions,
142 * @param pos position to check
143 * @param ast the AST object
144 * @returns line and column
146 function getLineAndCharacterFor(pos, ast) {
147 const loc = ast.getLineAndCharacterOfPosition(pos);
150 column: loc.character,
153 exports.getLineAndCharacterFor = getLineAndCharacterFor;
155 * Returns line and column data for the given start and end positions,
157 * @param start start data
158 * @param end end data
159 * @param ast the AST object
160 * @returns the loc data
162 function getLocFor(start, end, ast) {
164 start: getLineAndCharacterFor(start, ast),
165 end: getLineAndCharacterFor(end, ast),
168 exports.getLocFor = getLocFor;
170 * Check whatever node can contain directive
172 * @returns returns true if node can contain directive
174 function canContainDirective(node) {
175 if (node.kind === ts.SyntaxKind.Block) {
176 switch (node.parent.kind) {
177 case ts.SyntaxKind.Constructor:
178 case ts.SyntaxKind.GetAccessor:
179 case ts.SyntaxKind.SetAccessor:
180 case ts.SyntaxKind.ArrowFunction:
181 case ts.SyntaxKind.FunctionExpression:
182 case ts.SyntaxKind.FunctionDeclaration:
183 case ts.SyntaxKind.MethodDeclaration:
191 exports.canContainDirective = canContainDirective;
193 * Returns range for the given ts.Node
194 * @param node the ts.Node or ts.Token
195 * @param ast the AST object
196 * @returns the range data
198 function getRange(node, ast) {
199 return [node.getStart(ast), node.getEnd()];
201 exports.getRange = getRange;
203 * Returns true if a given ts.Node is a token
204 * @param node the ts.Node
205 * @returns is a token
207 function isToken(node) {
208 return (node.kind >= SyntaxKind.FirstToken && node.kind <= SyntaxKind.LastToken);
210 exports.isToken = isToken;
212 * Returns true if a given ts.Node is a JSX token
213 * @param node ts.Node to be checked
214 * @returns is a JSX token
216 function isJSXToken(node) {
217 return (node.kind >= SyntaxKind.JsxElement && node.kind <= SyntaxKind.JsxAttribute);
219 exports.isJSXToken = isJSXToken;
221 * Returns the declaration kind of the given ts.Node
222 * @param node TypeScript AST node
223 * @returns declaration kind
225 function getDeclarationKind(node) {
226 if (node.flags & ts.NodeFlags.Let) {
229 if (node.flags & ts.NodeFlags.Const) {
234 exports.getDeclarationKind = getDeclarationKind;
236 * Gets a ts.Node's accessibility level
237 * @param node The ts.Node
238 * @returns accessibility "public", "protected", "private", or null
240 function getTSNodeAccessibility(node) {
241 const modifiers = node.modifiers;
245 for (let i = 0; i < modifiers.length; i++) {
246 const modifier = modifiers[i];
247 switch (modifier.kind) {
248 case SyntaxKind.PublicKeyword:
250 case SyntaxKind.ProtectedKeyword:
252 case SyntaxKind.PrivateKeyword:
260 exports.getTSNodeAccessibility = getTSNodeAccessibility;
262 * Finds the next token based on the previous one and its parent
263 * Had to copy this from TS instead of using TS's version because theirs doesn't pass the ast to getChildren
264 * @param previousToken The previous TSToken
265 * @param parent The parent TSNode
266 * @param ast The TS AST
267 * @returns the next TSToken
269 function findNextToken(previousToken, parent, ast) {
272 if (ts.isToken(n) && n.pos === previousToken.end) {
273 // this is token that starts at the end of previous token - return it
276 return firstDefined(n.getChildren(ast), (child) => {
277 const shouldDiveInChildNode =
278 // previous token is enclosed somewhere in the child
279 (child.pos <= previousToken.pos && child.end > previousToken.end) ||
280 // previous token ends exactly at the beginning of child
281 child.pos === previousToken.end;
282 return shouldDiveInChildNode && nodeHasTokens(child, ast)
288 exports.findNextToken = findNextToken;
290 * Find the first matching ancestor based on the given predicate function.
291 * @param node The current ts.Node
292 * @param predicate The predicate function to apply to each checked ancestor
293 * @returns a matching parent ts.Node
295 function findFirstMatchingAncestor(node, predicate) {
297 if (predicate(node)) {
304 exports.findFirstMatchingAncestor = findFirstMatchingAncestor;
306 * Returns true if a given ts.Node has a JSX token within its hierarchy
307 * @param node ts.Node to be checked
308 * @returns has JSX ancestor
310 function hasJSXAncestor(node) {
311 return !!findFirstMatchingAncestor(node, isJSXToken);
313 exports.hasJSXAncestor = hasJSXAncestor;
315 * Unescape the text content of string literals, e.g. & -> &
316 * @param text The escaped string literal text.
317 * @returns The unescaped string literal text.
319 function unescapeStringLiteralText(text) {
320 return unescape_1.default(text);
322 exports.unescapeStringLiteralText = unescapeStringLiteralText;
324 * Returns true if a given ts.Node is a computed property
325 * @param node ts.Node to be checked
326 * @returns is Computed Property
328 function isComputedProperty(node) {
329 return node.kind === SyntaxKind.ComputedPropertyName;
331 exports.isComputedProperty = isComputedProperty;
333 * Returns true if a given ts.Node is optional (has QuestionToken)
334 * @param node ts.Node to be checked
335 * @returns is Optional
337 function isOptional(node) {
338 return node.questionToken
339 ? node.questionToken.kind === SyntaxKind.QuestionToken
342 exports.isOptional = isOptional;
344 * Returns true if the node is an optional chain node
346 function isOptionalChain(node) {
347 return (node.type === ts_estree_1.AST_NODE_TYPES.OptionalCallExpression ||
348 node.type == ts_estree_1.AST_NODE_TYPES.OptionalMemberExpression);
350 exports.isOptionalChain = isOptionalChain;
352 * Returns true of the child of property access expression is an optional chain
354 function isChildOptionalChain(node, object) {
355 if (isOptionalChain(object) &&
356 // (x?.y).z is semantically different, and as such .z is no longer optional
357 node.expression.kind !== ts.SyntaxKind.ParenthesizedExpression) {
360 if (!version_check_1.typescriptVersionIsAtLeast['3.9']) {
363 // TS3.9 made a breaking change to how non-null works with optional chains.
364 // Pre-3.9, `x?.y!.z` means `(x?.y).z` - i.e. it essentially scrubbed the optionality from the chain
365 // 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`
366 if (object.type !== ts_estree_1.AST_NODE_TYPES.TSNonNullExpression ||
367 !isOptionalChain(object.expression)) {
371 // make sure it's not (x.y)!.z
372 node.expression.kind === ts.SyntaxKind.NonNullExpression &&
373 node.expression.expression.kind !==
374 ts.SyntaxKind.ParenthesizedExpression) {
379 exports.isChildOptionalChain = isChildOptionalChain;
381 * Returns the type of a given ts.Token
382 * @param token the ts.Token
383 * @returns the token type
385 function getTokenType(token) {
386 if ('originalKeywordKind' in token && token.originalKeywordKind) {
387 if (token.originalKeywordKind === SyntaxKind.NullKeyword) {
388 return ts_estree_1.AST_TOKEN_TYPES.Null;
390 else if (token.originalKeywordKind >= SyntaxKind.FirstFutureReservedWord &&
391 token.originalKeywordKind <= SyntaxKind.LastKeyword) {
392 return ts_estree_1.AST_TOKEN_TYPES.Identifier;
394 return ts_estree_1.AST_TOKEN_TYPES.Keyword;
396 if (token.kind >= SyntaxKind.FirstKeyword &&
397 token.kind <= SyntaxKind.LastFutureReservedWord) {
398 if (token.kind === SyntaxKind.FalseKeyword ||
399 token.kind === SyntaxKind.TrueKeyword) {
400 return ts_estree_1.AST_TOKEN_TYPES.Boolean;
402 return ts_estree_1.AST_TOKEN_TYPES.Keyword;
404 if (token.kind >= SyntaxKind.FirstPunctuation &&
405 token.kind <= SyntaxKind.LastBinaryOperator) {
406 return ts_estree_1.AST_TOKEN_TYPES.Punctuator;
408 if (token.kind >= SyntaxKind.NoSubstitutionTemplateLiteral &&
409 token.kind <= SyntaxKind.TemplateTail) {
410 return ts_estree_1.AST_TOKEN_TYPES.Template;
412 switch (token.kind) {
413 case SyntaxKind.NumericLiteral:
414 return ts_estree_1.AST_TOKEN_TYPES.Numeric;
415 case SyntaxKind.JsxText:
416 return ts_estree_1.AST_TOKEN_TYPES.JSXText;
417 case SyntaxKind.StringLiteral:
418 // A TypeScript-StringLiteral token with a TypeScript-JsxAttribute or TypeScript-JsxElement parent,
419 // must actually be an ESTree-JSXText token
421 (token.parent.kind === SyntaxKind.JsxAttribute ||
422 token.parent.kind === SyntaxKind.JsxElement)) {
423 return ts_estree_1.AST_TOKEN_TYPES.JSXText;
425 return ts_estree_1.AST_TOKEN_TYPES.String;
426 case SyntaxKind.RegularExpressionLiteral:
427 return ts_estree_1.AST_TOKEN_TYPES.RegularExpression;
428 case SyntaxKind.Identifier:
429 case SyntaxKind.ConstructorKeyword:
430 case SyntaxKind.GetKeyword:
431 case SyntaxKind.SetKeyword:
435 // Some JSX tokens have to be determined based on their parent
436 if (token.parent && token.kind === SyntaxKind.Identifier) {
437 if (isJSXToken(token.parent)) {
438 return ts_estree_1.AST_TOKEN_TYPES.JSXIdentifier;
440 if (token.parent.kind === SyntaxKind.PropertyAccessExpression &&
441 hasJSXAncestor(token)) {
442 return ts_estree_1.AST_TOKEN_TYPES.JSXIdentifier;
445 return ts_estree_1.AST_TOKEN_TYPES.Identifier;
447 exports.getTokenType = getTokenType;
449 * Extends and formats a given ts.Token, for a given AST
450 * @param token the ts.Token
451 * @param ast the AST object
452 * @returns the converted Token
454 function convertToken(token, ast) {
455 const start = token.kind === SyntaxKind.JsxText
456 ? token.getFullStart()
457 : token.getStart(ast);
458 const end = token.getEnd();
459 const value = ast.text.slice(start, end);
460 const tokenType = getTokenType(token);
461 if (tokenType === ts_estree_1.AST_TOKEN_TYPES.RegularExpression) {
466 loc: getLocFor(start, end, ast),
468 pattern: value.slice(1, value.lastIndexOf('/')),
469 flags: value.slice(value.lastIndexOf('/') + 1),
478 loc: getLocFor(start, end, ast),
482 exports.convertToken = convertToken;
484 * Converts all tokens for the given AST
485 * @param ast the AST object
486 * @returns the converted Tokens
488 function convertTokens(ast) {
491 * @param node the ts.Node
493 function walk(node) {
494 // TypeScript generates tokens for types in JSDoc blocks. Comment tokens
495 // and their children should not be walked or added to the resulting tokens list.
496 if (isComment(node) || isJSDocComment(node)) {
499 if (isToken(node) && node.kind !== SyntaxKind.EndOfFileToken) {
500 const converted = convertToken(node, ast);
502 result.push(converted);
506 node.getChildren(ast).forEach(walk);
512 exports.convertTokens = convertTokens;
514 * @param ast the AST object
515 * @param start the index at which the error starts
516 * @param message the error message
517 * @returns converted error object
519 function createError(ast, start, message) {
520 const loc = ast.getLineAndCharacterOfPosition(start);
523 lineNumber: loc.line + 1,
524 column: loc.character,
528 exports.createError = createError;
530 * @param n the TSNode
531 * @param ast the TS AST
533 function nodeHasTokens(n, ast) {
534 // If we have a token or node that has a non-zero width, it must have tokens.
535 // Note: getWidth() does not take trivia into account.
536 return n.kind === SyntaxKind.EndOfFileToken
537 ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
539 : n.getWidth(ast) !== 0;
541 exports.nodeHasTokens = nodeHasTokens;
543 * Like `forEach`, but suitable for use with numbers and strings (which may be falsy).
549 function firstDefined(array, callback) {
550 if (array === undefined) {
553 for (let i = 0; i < array.length; i++) {
554 const result = callback(array[i], i);
555 if (result !== undefined) {
561 exports.firstDefined = firstDefined;
562 //# sourceMappingURL=node-utils.js.map