NodeLexicalScopeUtils.ts 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import * as ESTree from 'estree';
  2. import { TNodeWithLexicalScope } from '../types/node/TNodeWithLexicalScope';
  3. import { NodeGuards } from './NodeGuards';
  4. export class NodeLexicalScopeUtils {
  5. /**
  6. * @param {Node} node
  7. * @returns {TNodeWithLexicalScope}
  8. */
  9. public static getLexicalScope (node: ESTree.Node): TNodeWithLexicalScope | undefined {
  10. return NodeLexicalScopeUtils.getLexicalScopesRecursive(node, 1)[0];
  11. }
  12. /**
  13. * @param {Node} node
  14. * @returns {TNodeWithLexicalScope[]}
  15. */
  16. public static getLexicalScopes (node: ESTree.Node): TNodeWithLexicalScope[] {
  17. return NodeLexicalScopeUtils.getLexicalScopesRecursive(node);
  18. }
  19. /**
  20. * @param {Node} node
  21. * @param {number} maxSize
  22. * @param {TNodeWithLexicalScope[]} nodesWithLexicalScope
  23. * @param {number} depth
  24. * @returns {TNodeWithLexicalScope[]}
  25. */
  26. private static getLexicalScopesRecursive (
  27. node: ESTree.Node,
  28. maxSize: number = Infinity,
  29. nodesWithLexicalScope: TNodeWithLexicalScope[] = [],
  30. depth: number = 0
  31. ): TNodeWithLexicalScope[] {
  32. if (nodesWithLexicalScope.length >= maxSize) {
  33. return nodesWithLexicalScope;
  34. }
  35. const parentNode: ESTree.Node | undefined = node.parentNode;
  36. if (!parentNode) {
  37. throw new ReferenceError('`parentNode` property of given node is `undefined`');
  38. }
  39. if (NodeGuards.isNodeWithLexicalScope(node)) {
  40. nodesWithLexicalScope.push(node);
  41. }
  42. if (node !== parentNode) {
  43. return NodeLexicalScopeUtils.getLexicalScopesRecursive(parentNode, maxSize, nodesWithLexicalScope, ++depth);
  44. }
  45. return nodesWithLexicalScope;
  46. }
  47. }