NodeUtils.ts 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. import * as estraverse from 'estraverse';
  2. import { IBlockStatementNode } from "./interfaces/nodes/IBlockStatementNode";
  3. import { IIdentifierNode } from "./interfaces/nodes/IIdentifierNode";
  4. import { ILiteralNode } from "./interfaces/nodes/ILiteralNode";
  5. import { IMemberExpressionNode } from "./interfaces/nodes/IMemberExpressionNode";
  6. import { IProgramNode } from "./interfaces/nodes/IProgramNode";
  7. import { IPropertyNode } from "./interfaces/nodes/IPropertyNode";
  8. import { INode } from './interfaces/nodes/INode';
  9. import { IVariableDeclaratorNode } from "./interfaces/nodes/IVariableDeclaratorNode";
  10. import { BlockScopeNode } from "./types/BlockScopeNode";
  11. import { NodeType } from "./enums/NodeType";
  12. import { Utils } from "./Utils";
  13. export class NodeUtils {
  14. /**
  15. * @type {string[]}
  16. */
  17. private static scopeNodes: string[] = [
  18. NodeType.ArrowFunctionExpression,
  19. NodeType.FunctionDeclaration,
  20. NodeType.FunctionExpression,
  21. NodeType.MethodDefinition
  22. ];
  23. /**
  24. * @param blockScopeBody
  25. * @param node
  26. */
  27. public static appendNode (blockScopeBody: INode[], node: INode): void {
  28. if (!NodeUtils.validateNode(node)) {
  29. return;
  30. }
  31. blockScopeBody.push(node);
  32. }
  33. /**
  34. * @param node
  35. * @param index
  36. * @returns {INode}
  37. */
  38. public static getBlockScopeNodeByIndex (node: INode, index: number = 0): INode {
  39. if (NodeUtils.isNodeHasBlockScope(node) && node.body[index]) {
  40. return node.body[index];
  41. }
  42. return node;
  43. }
  44. /**
  45. * @param node
  46. * @param depth
  47. * @returns {INode}
  48. */
  49. public static getBlockScopeOfNode (node: INode, depth: number = 0): BlockScopeNode {
  50. if (!node.parentNode) {
  51. throw new ReferenceError('`parentNode` property of given node is `undefined`');
  52. }
  53. if (node.parentNode.type === NodeType.Program) {
  54. return <BlockScopeNode> node.parentNode;
  55. }
  56. if (!Utils.arrayContains(NodeUtils.scopeNodes, node.parentNode.type)) {
  57. return NodeUtils.getBlockScopeOfNode(node.parentNode, depth);
  58. }
  59. if (depth > 0) {
  60. return NodeUtils.getBlockScopeOfNode(node.parentNode, --depth);
  61. }
  62. if (node.type !== NodeType.BlockStatement) {
  63. return NodeUtils.getBlockScopeOfNode(node.parentNode);
  64. }
  65. return <BlockScopeNode> node; // blocks statement of scopeNodes
  66. }
  67. /**
  68. * @param blockScopeBody
  69. * @param node
  70. * @param index
  71. */
  72. public static insertNodeAtIndex (blockScopeBody: INode[], node: INode, index: number): void {
  73. if (!NodeUtils.validateNode(node)) {
  74. return;
  75. }
  76. blockScopeBody.splice(index, 0, node);
  77. }
  78. /**
  79. * @param node
  80. * @returns {boolean}
  81. */
  82. public static isBlockStatementNode (node: INode): node is IBlockStatementNode {
  83. return node.type === NodeType.BlockStatement;
  84. }
  85. /**
  86. * @param node
  87. * @returns {boolean}
  88. */
  89. public static isIdentifierNode (node: INode): node is IIdentifierNode {
  90. return node.type === NodeType.Identifier;
  91. }
  92. /**
  93. * @param node
  94. * @returns {boolean}
  95. */
  96. public static isLiteralNode (node: INode): node is ILiteralNode {
  97. return node.type === NodeType.Literal;
  98. }
  99. /**
  100. * @param node
  101. * @returns {boolean}
  102. */
  103. public static isMemberExpressionNode (node: INode): node is IMemberExpressionNode {
  104. return node.type === NodeType.MemberExpression;
  105. }
  106. /**
  107. * @param node
  108. * @returns {boolean}
  109. */
  110. public static isNodeHasBlockScope (node: INode): node is BlockScopeNode {
  111. return node.hasOwnProperty('body');
  112. }
  113. /**
  114. *
  115. * @param node
  116. * @returns {boolean}
  117. */
  118. public static isProgramNode (node: INode): node is IProgramNode {
  119. return node.type === NodeType.Program;
  120. }
  121. /**
  122. *
  123. * @param node
  124. * @returns {boolean}
  125. */
  126. public static isPropertyNode (node: INode): node is IPropertyNode {
  127. return node.type === NodeType.Property;
  128. }
  129. /**
  130. *
  131. * @param node
  132. * @returns {boolean}
  133. */
  134. public static isVariableDeclaratorNode (node: INode): node is IVariableDeclaratorNode {
  135. return node.type === NodeType.VariableDeclarator;
  136. }
  137. /**
  138. * @param node
  139. */
  140. public static parentize (node: INode): void {
  141. estraverse.replace(node, {
  142. enter: (node: INode, parentNode: INode): any => {
  143. Object.defineProperty(node, 'parentNode', {
  144. configurable: true,
  145. enumerable: true,
  146. value: parentNode || node,
  147. writable: true
  148. });
  149. }
  150. });
  151. }
  152. /**
  153. * @param blockScopeBody
  154. * @param node
  155. */
  156. public static prependNode (blockScopeBody: INode[], node: INode): void {
  157. if (!NodeUtils.validateNode(node)) {
  158. return;
  159. }
  160. blockScopeBody.unshift(node);
  161. }
  162. /**
  163. * @param node
  164. * @returns {boolean}
  165. */
  166. private static validateNode (node: INode): boolean {
  167. return !!node;
  168. }
  169. }