NodeGuards.ts 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. /* eslint-disable max-lines */
  2. import * as ESTree from 'estree';
  3. import { TNodeWithLexicalScope } from '../types/node/TNodeWithLexicalScope';
  4. import { TNodeWithLexicalScopeStatements } from '../types/node/TNodeWithLexicalScopeStatements';
  5. import { TNodeWithSingleStatementBody } from '../types/node/TNodeWithSingleStatementBody';
  6. import { TNodeWithStatements } from '../types/node/TNodeWithStatements';
  7. import { NodeType } from '../enums/node/NodeType';
  8. export class NodeGuards {
  9. /**
  10. * @type {string[]}
  11. */
  12. private static readonly nodesWithLexicalStatements: string[] = [
  13. NodeType.ArrowFunctionExpression,
  14. NodeType.FunctionDeclaration,
  15. NodeType.FunctionExpression,
  16. NodeType.MethodDefinition,
  17. ];
  18. /**
  19. * @param {Node} node
  20. * @returns {boolean}
  21. */
  22. public static isArrayPatternNode (node: ESTree.Node): node is ESTree.ArrayPattern {
  23. return node.type === NodeType.ArrayPattern;
  24. }
  25. /**
  26. * @param {Node} node
  27. * @returns {boolean}
  28. */
  29. public static isArrowFunctionExpressionNode (node: ESTree.Node): node is ESTree.ArrowFunctionExpression {
  30. return node.type === NodeType.ArrowFunctionExpression;
  31. }
  32. /**
  33. * @param {Node} node
  34. * @returns {boolean}
  35. */
  36. public static isAssignmentExpressionNode (node: ESTree.Node): node is ESTree.AssignmentExpression {
  37. return node.type === NodeType.AssignmentExpression;
  38. }
  39. /**
  40. * @param {Node} node
  41. * @returns {boolean}
  42. */
  43. public static isAssignmentPatternNode (node: ESTree.Node): node is ESTree.AssignmentPattern {
  44. return node.type === NodeType.AssignmentPattern;
  45. }
  46. /**
  47. * @param {Node} node
  48. * @returns {boolean}
  49. */
  50. public static isAwaitExpressionNode (node: ESTree.Node): node is ESTree.AwaitExpression {
  51. return node.type === NodeType.AwaitExpression;
  52. }
  53. /**
  54. * @param {Node} node
  55. * @returns {boolean}
  56. */
  57. public static isBigIntLiteralNode (node: ESTree.Node): node is ESTree.BigIntLiteral {
  58. return NodeGuards.isLiteralNode(node) && !!(<ESTree.BigIntLiteral>node).bigint;
  59. }
  60. /**
  61. * @param {Node} node
  62. * @returns {boolean}
  63. */
  64. public static isBlockStatementNode (node: ESTree.Node): node is ESTree.BlockStatement {
  65. return node.type === NodeType.BlockStatement;
  66. }
  67. /**
  68. * @param {Node} node
  69. * @returns {boolean}
  70. */
  71. public static isBreakStatementNode (node: ESTree.Node): node is ESTree.BreakStatement {
  72. return node.type === NodeType.BreakStatement;
  73. }
  74. /**
  75. * @param {Node} node
  76. * @returns {boolean}
  77. */
  78. public static isCallExpressionNode (node: ESTree.Node): node is ESTree.CallExpression {
  79. return node.type === NodeType.CallExpression;
  80. }
  81. /**
  82. * @param {Node} node
  83. * @returns {boolean}
  84. */
  85. public static isClassDeclarationNode (
  86. node: ESTree.Node
  87. ): node is ESTree.ClassDeclaration & { id: ESTree.Identifier } {
  88. return node.type === NodeType.ClassDeclaration && node.id !== null;
  89. }
  90. /**
  91. * @param {Node} node
  92. * @returns {boolean}
  93. */
  94. public static isConditionalExpressionNode (node: ESTree.Node): node is ESTree.ConditionalExpression {
  95. return node.type === NodeType.ConditionalExpression;
  96. }
  97. /**
  98. * @param {Node} node
  99. * @returns {boolean}
  100. */
  101. public static isContinueStatementNode (node: ESTree.Node): node is ESTree.ContinueStatement {
  102. return node.type === NodeType.ContinueStatement;
  103. }
  104. /**
  105. * @param {Node} node
  106. * @returns {boolean}
  107. */
  108. public static isDirectiveNode (node: ESTree.Node): node is ESTree.Directive {
  109. return node.type === NodeType.ExpressionStatement
  110. && 'directive' in node;
  111. }
  112. /**
  113. * @param {Node} node
  114. * @returns {boolean}
  115. */
  116. public static isDoWhileStatementNode (node: ESTree.Node): node is ESTree.DoWhileStatement {
  117. return node.type === NodeType.DoWhileStatement;
  118. }
  119. /**
  120. * @param {Node} node
  121. * @returns {boolean}
  122. */
  123. public static isExportAllDeclarationNode (node: ESTree.Node): node is ESTree.ExportAllDeclaration {
  124. return node.type === NodeType.ExportAllDeclaration;
  125. }
  126. /**
  127. * @param {Node} node
  128. * @returns {boolean}
  129. */
  130. public static isExportNamedDeclarationNode (node: ESTree.Node): node is ESTree.ExportNamedDeclaration {
  131. return node.type === NodeType.ExportNamedDeclaration;
  132. }
  133. /**
  134. * @param {Node} node
  135. * @returns {boolean}
  136. */
  137. public static isExportSpecifierNode (node: ESTree.Node): node is ESTree.ExportSpecifier {
  138. return node.type === NodeType.ExportSpecifier;
  139. }
  140. /**
  141. * @param {Node} node
  142. * @returns {boolean}
  143. */
  144. public static isExpressionStatementNode (node: ESTree.Node): node is ESTree.ExpressionStatement {
  145. return node.type === NodeType.ExpressionStatement
  146. && !('directive' in node);
  147. }
  148. /**
  149. * @param {Node} node
  150. * @returns {boolean}
  151. */
  152. public static isForStatementNode (node: ESTree.Node): node is ESTree.ForStatement {
  153. return node.type === NodeType.ForStatement;
  154. }
  155. /**
  156. * @param {Node} node
  157. * @returns {boolean}
  158. */
  159. public static isForInStatementNode (node: ESTree.Node): node is ESTree.ForInStatement {
  160. return node.type === NodeType.ForInStatement;
  161. }
  162. /**
  163. * @param {Node} node
  164. * @returns {boolean}
  165. */
  166. public static isForOfStatementNode (node: ESTree.Node): node is ESTree.ForOfStatement {
  167. return node.type === NodeType.ForOfStatement;
  168. }
  169. /**
  170. * @param {Node} node
  171. * @returns {boolean}
  172. */
  173. public static isFunctionNode (node: ESTree.Node): node is ESTree.Function {
  174. return NodeGuards.isFunctionDeclarationNode(node) ||
  175. NodeGuards.isFunctionExpressionNode(node) ||
  176. NodeGuards.isArrowFunctionExpressionNode(node);
  177. }
  178. /**
  179. * @param {Node} node
  180. * @returns {boolean}
  181. */
  182. public static isFunctionDeclarationNode (
  183. node: ESTree.Node
  184. ): node is ESTree.FunctionDeclaration & { id: ESTree.Identifier } {
  185. return node.type === NodeType.FunctionDeclaration && node.id !== null;
  186. }
  187. /**
  188. * @param {Node} node
  189. * @returns {boolean}
  190. */
  191. public static isFunctionExpressionNode (node: ESTree.Node): node is ESTree.FunctionExpression {
  192. return node.type === NodeType.FunctionExpression;
  193. }
  194. /**
  195. * @param {Node} node
  196. * @returns {boolean}
  197. */
  198. public static isIdentifierNode (node: ESTree.Node): node is ESTree.Identifier {
  199. return node.type === NodeType.Identifier;
  200. }
  201. /**
  202. * @param {Node} node
  203. * @returns {boolean}
  204. */
  205. public static isIfStatementNode (node: ESTree.Node): node is ESTree.IfStatement {
  206. return node.type === NodeType.IfStatement;
  207. }
  208. /**
  209. * @param {Node} node
  210. * @returns {boolean}
  211. */
  212. public static isIfStatementNodeWithSingleStatementBody (node: ESTree.Node): node is ESTree.IfStatement {
  213. if (!NodeGuards.isIfStatementNode(node)) {
  214. return false;
  215. }
  216. return !NodeGuards.isBlockStatementNode(node.consequent)
  217. || (!!node.alternate && !NodeGuards.isBlockStatementNode(node.alternate));
  218. }
  219. /**
  220. * @param {Node} node
  221. * @returns {boolean}
  222. */
  223. public static isImportDeclarationNode (node: ESTree.Node): node is ESTree.ImportDeclaration {
  224. return node.type === NodeType.ImportDeclaration;
  225. }
  226. /**
  227. * @param {Node} node
  228. * @returns {boolean}
  229. */
  230. public static isImportSpecifierNode (node: ESTree.Node): node is ESTree.ImportSpecifier {
  231. return node.type === NodeType.ImportSpecifier;
  232. }
  233. /**
  234. * @param {Node} node
  235. * @param {Node} parentNode
  236. * @returns {boolean}
  237. */
  238. public static isLabelIdentifierNode (node: ESTree.Node, parentNode: ESTree.Node): node is ESTree.Identifier {
  239. const parentNodeIsLabeledStatementNode: boolean = NodeGuards.isLabeledStatementNode(parentNode) && parentNode.label === node;
  240. const parentNodeIsContinueStatementNode: boolean = NodeGuards.isContinueStatementNode(parentNode) && parentNode.label === node;
  241. const parentNodeIsBreakStatementNode: boolean = NodeGuards.isBreakStatementNode(parentNode) && parentNode.label === node;
  242. return parentNodeIsLabeledStatementNode || parentNodeIsContinueStatementNode || parentNodeIsBreakStatementNode;
  243. }
  244. /**
  245. * @param {Node} node
  246. * @returns {boolean}
  247. */
  248. public static isLabeledStatementNode (node: ESTree.Node): node is ESTree.LabeledStatement {
  249. return node.type === NodeType.LabeledStatement;
  250. }
  251. /**
  252. * @param {Node} node
  253. * @returns {boolean}
  254. */
  255. public static isLiteralNode (node: ESTree.Node): node is ESTree.Literal {
  256. return node.type === NodeType.Literal;
  257. }
  258. /**
  259. * @param {Node} node
  260. * @returns {boolean}
  261. */
  262. public static isLogicalExpressionNode (node: ESTree.Node): node is ESTree.LogicalExpression {
  263. return node.type === NodeType.LogicalExpression;
  264. }
  265. /**
  266. * @param {Node} node
  267. * @returns {boolean}
  268. */
  269. public static isMemberExpressionNode (node: ESTree.Node): node is ESTree.MemberExpression {
  270. return node.type === NodeType.MemberExpression;
  271. }
  272. /**
  273. * @param {Node} node
  274. * @returns {boolean}
  275. */
  276. public static isMethodDefinitionNode (node: ESTree.Node): node is ESTree.MethodDefinition {
  277. return node.type === NodeType.MethodDefinition;
  278. }
  279. /**
  280. * @param {Node} node
  281. * @returns {boolean}
  282. */
  283. public static isNewExpressionNode (node: ESTree.Node): node is ESTree.NewExpression {
  284. return node.type === NodeType.NewExpression;
  285. }
  286. /**
  287. * @param {Object} object
  288. * @returns {boolean}
  289. */
  290. // eslint-disable-next-line @typescript-eslint/ban-types
  291. public static isNode (object: Object & { type?: string }): object is ESTree.Node {
  292. return object && !object.type !== undefined;
  293. }
  294. /**
  295. * @param {Node} node
  296. * @returns {boolean}
  297. */
  298. public static isNodeWithLexicalScope (node: ESTree.Node): node is TNodeWithLexicalScope {
  299. return NodeGuards.isProgramNode(node) || NodeGuards.isFunctionNode(node);
  300. }
  301. /**
  302. * @param {Node} node
  303. * @returns {boolean}
  304. */
  305. public static isNodeWithBlockLexicalScope (node: ESTree.Node): node is TNodeWithLexicalScope {
  306. return NodeGuards.isNodeWithLexicalScope(node) || NodeGuards.isBlockStatementNode(node);
  307. }
  308. /**
  309. * Checks if a node is the node with single statement body, like:
  310. * while (true)
  311. * console.log(1);
  312. *
  313. * or:
  314. *
  315. *
  316. * @param {Node} node
  317. * @returns {boolean}
  318. */
  319. public static isNodeWithSingleStatementBody (node: ESTree.Node): node is TNodeWithSingleStatementBody {
  320. // Different approach for `IfStatement` node because this node hasn't `body` property
  321. if (NodeGuards.isIfStatementNode(node)) {
  322. return NodeGuards.isIfStatementNodeWithSingleStatementBody(node);
  323. }
  324. // All other nodes with `Statement` node as `body` property
  325. return (
  326. NodeGuards.isForStatementNode(node)
  327. || NodeGuards.isForOfStatementNode(node)
  328. || NodeGuards.isForInStatementNode(node)
  329. || NodeGuards.isWhileStatementNode(node)
  330. || NodeGuards.isDoWhileStatementNode(node)
  331. || NodeGuards.isWithStatementNode(node)
  332. || NodeGuards.isLabeledStatementNode(node)
  333. ) && !NodeGuards.isBlockStatementNode(node.body);
  334. }
  335. /**
  336. * @param {Node} node
  337. * @param {Node} parentNode
  338. * @returns {boolean}
  339. */
  340. public static isNodeWithLexicalScopeStatements (
  341. node: ESTree.Node,
  342. parentNode: ESTree.Node
  343. ): node is TNodeWithLexicalScopeStatements {
  344. return NodeGuards.isProgramNode(node)
  345. || (NodeGuards.isBlockStatementNode(node) && NodeGuards.nodesWithLexicalStatements.includes(parentNode.type));
  346. }
  347. /**
  348. * @param {Node} node
  349. * @returns {boolean}
  350. */
  351. public static isNodeWithStatements (node: ESTree.Node): node is TNodeWithStatements {
  352. return NodeGuards.isProgramNode(node)
  353. || NodeGuards.isBlockStatementNode(node)
  354. || NodeGuards.isSwitchCaseNode(node);
  355. }
  356. /**
  357. * @param {Node} node
  358. * @returns {boolean}
  359. */
  360. public static isNodeWithComments (node: ESTree.Node): node is ESTree.Node {
  361. return Boolean(node.leadingComments) || Boolean(node.trailingComments);
  362. }
  363. /**
  364. * @param {Node} node
  365. * @returns {boolean}
  366. */
  367. public static isObjectPatternNode (node: ESTree.Node): node is ESTree.ObjectPattern {
  368. return node.type === NodeType.ObjectPattern;
  369. }
  370. /**
  371. * @param {Node} node
  372. * @returns {boolean}
  373. */
  374. public static isObjectExpressionNode (node: ESTree.Node): node is ESTree.ObjectExpression {
  375. return node.type === NodeType.ObjectExpression;
  376. }
  377. /**
  378. * @param {Node} node
  379. * @returns {boolean}
  380. */
  381. public static isProgramNode (node: ESTree.Node): node is ESTree.Program {
  382. return node.type === NodeType.Program;
  383. }
  384. /**
  385. * @param {Node} node
  386. * @returns {boolean}
  387. */
  388. public static isPropertyNode (node: ESTree.Node): node is ESTree.Property {
  389. return node.type === NodeType.Property;
  390. }
  391. /**
  392. * @param {Node} node
  393. * @returns {boolean}
  394. */
  395. public static isRestElementNode (node: ESTree.Node): node is ESTree.RestElement {
  396. return node.type === NodeType.RestElement;
  397. }
  398. /**
  399. * @param {Node} node
  400. * @returns {boolean}
  401. */
  402. public static isReturnStatementNode (node: ESTree.Node): node is ESTree.ReturnStatement {
  403. return node.type === NodeType.ReturnStatement;
  404. }
  405. /**
  406. * @param {Node} node
  407. * @returns {boolean}
  408. */
  409. public static isSequenceExpressionNode (node: ESTree.Node): node is ESTree.SequenceExpression {
  410. return node.type === NodeType.SequenceExpression;
  411. }
  412. /**
  413. * @param {Node} node
  414. * @returns {boolean}
  415. */
  416. public static isSpreadElementNode (node: ESTree.Node): node is ESTree.SpreadElement {
  417. return node.type === NodeType.SpreadElement;
  418. }
  419. /**
  420. * @param {Node} node
  421. * @returns {boolean}
  422. */
  423. public static isSuperNode (node: ESTree.Node): node is ESTree.Super {
  424. return node.type === NodeType.Super;
  425. }
  426. /**
  427. * @param {Node} node
  428. * @returns {boolean}
  429. */
  430. public static isSwitchCaseNode (node: ESTree.Node): node is ESTree.SwitchCase {
  431. return node.type === NodeType.SwitchCase;
  432. }
  433. /**
  434. * @param {Node} node
  435. * @returns {boolean}
  436. */
  437. public static isTaggedTemplateExpressionNode (node: ESTree.Node): node is ESTree.TaggedTemplateExpression {
  438. return node.type === NodeType.TaggedTemplateExpression;
  439. }
  440. /**
  441. * @param {Node} node
  442. * @returns {boolean}
  443. */
  444. public static isTemplateLiteralNode (node: ESTree.Node): node is ESTree.TemplateLiteral {
  445. return node.type === NodeType.TemplateLiteral;
  446. }
  447. /**
  448. * @param {Node} node
  449. * @returns {boolean}
  450. */
  451. public static isThisExpressionNode (node: ESTree.Node): node is ESTree.ThisExpression {
  452. return node.type === NodeType.ThisExpression;
  453. }
  454. /**
  455. * @param {Node} node
  456. * @returns {boolean}
  457. */
  458. public static isUnaryExpressionNode (node: ESTree.Node): node is ESTree.UnaryExpression {
  459. return node.type === NodeType.UnaryExpression;
  460. }
  461. /**
  462. * @param {Node} node
  463. * @returns {boolean}
  464. */
  465. public static isVariableDeclarationNode (node: ESTree.Node): node is ESTree.VariableDeclaration {
  466. return node.type === NodeType.VariableDeclaration;
  467. }
  468. /**
  469. * @param {Node} node
  470. * @returns {boolean}
  471. */
  472. public static isVariableDeclaratorNode (node: ESTree.Node): node is ESTree.VariableDeclarator {
  473. return node.type === NodeType.VariableDeclarator;
  474. }
  475. /**
  476. * @param {Node} node
  477. * @returns {boolean}
  478. */
  479. public static isWithStatementNode (node: ESTree.Node): node is ESTree.WithStatement {
  480. return node.type === NodeType.WithStatement;
  481. }
  482. /**
  483. * @param {Node} node
  484. * @returns {boolean}
  485. */
  486. public static isWhileStatementNode (node: ESTree.Node): node is ESTree.WhileStatement {
  487. return node.type === NodeType.WhileStatement;
  488. }
  489. /**
  490. * @param {Node} node
  491. * @returns {boolean}
  492. */
  493. public static isYieldExpressionNode (node: ESTree.Node): node is ESTree.YieldExpression {
  494. return node.type === NodeType.YieldExpression;
  495. }
  496. }