ancestry.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.find = find;
  6. exports.findParent = findParent;
  7. exports.getAncestry = getAncestry;
  8. exports.getDeepestCommonAncestorFrom = getDeepestCommonAncestorFrom;
  9. exports.getEarliestCommonAncestorFrom = getEarliestCommonAncestorFrom;
  10. exports.getFunctionParent = getFunctionParent;
  11. exports.getStatementParent = getStatementParent;
  12. exports.inType = inType;
  13. exports.isAncestor = isAncestor;
  14. exports.isDescendant = isDescendant;
  15. var _t = require("@babel/types");
  16. const {
  17. VISITOR_KEYS
  18. } = _t;
  19. function findParent(callback) {
  20. let path = this;
  21. while (path = path.parentPath) {
  22. if (callback(path)) return path;
  23. }
  24. return null;
  25. }
  26. function find(callback) {
  27. let path = this;
  28. do {
  29. if (callback(path)) return path;
  30. } while (path = path.parentPath);
  31. return null;
  32. }
  33. function getFunctionParent() {
  34. return this.findParent(p => p.isFunction());
  35. }
  36. function getStatementParent() {
  37. let path = this;
  38. do {
  39. if (!path.parentPath || Array.isArray(path.container) && path.isStatement()) {
  40. break;
  41. } else {
  42. path = path.parentPath;
  43. }
  44. } while (path);
  45. if (path && (path.isProgram() || path.isFile())) {
  46. throw new Error("File/Program node, we can't possibly find a statement parent to this");
  47. }
  48. return path;
  49. }
  50. function getEarliestCommonAncestorFrom(paths) {
  51. return this.getDeepestCommonAncestorFrom(paths, function (deepest, i, ancestries) {
  52. let earliest;
  53. const keys = VISITOR_KEYS[deepest.type];
  54. for (const ancestry of ancestries) {
  55. const path = ancestry[i + 1];
  56. if (!earliest) {
  57. earliest = path;
  58. continue;
  59. }
  60. if (path.listKey && earliest.listKey === path.listKey) {
  61. if (path.key < earliest.key) {
  62. earliest = path;
  63. continue;
  64. }
  65. }
  66. const earliestKeyIndex = keys.indexOf(earliest.parentKey);
  67. const currentKeyIndex = keys.indexOf(path.parentKey);
  68. if (earliestKeyIndex > currentKeyIndex) {
  69. earliest = path;
  70. }
  71. }
  72. return earliest;
  73. });
  74. }
  75. function getDeepestCommonAncestorFrom(paths, filter) {
  76. if (!paths.length) {
  77. return this;
  78. }
  79. if (paths.length === 1) {
  80. return paths[0];
  81. }
  82. let minDepth = Infinity;
  83. let lastCommonIndex, lastCommon;
  84. const ancestries = paths.map(path => {
  85. const ancestry = [];
  86. do {
  87. ancestry.unshift(path);
  88. } while ((path = path.parentPath) && path !== this);
  89. if (ancestry.length < minDepth) {
  90. minDepth = ancestry.length;
  91. }
  92. return ancestry;
  93. });
  94. const first = ancestries[0];
  95. depthLoop: for (let i = 0; i < minDepth; i++) {
  96. const shouldMatch = first[i];
  97. for (const ancestry of ancestries) {
  98. if (ancestry[i] !== shouldMatch) {
  99. break depthLoop;
  100. }
  101. }
  102. lastCommonIndex = i;
  103. lastCommon = shouldMatch;
  104. }
  105. if (lastCommon) {
  106. if (filter) {
  107. return filter(lastCommon, lastCommonIndex, ancestries);
  108. } else {
  109. return lastCommon;
  110. }
  111. } else {
  112. throw new Error("Couldn't find intersection");
  113. }
  114. }
  115. function getAncestry() {
  116. let path = this;
  117. const paths = [];
  118. do {
  119. paths.push(path);
  120. } while (path = path.parentPath);
  121. return paths;
  122. }
  123. function isAncestor(maybeDescendant) {
  124. return maybeDescendant.isDescendant(this);
  125. }
  126. function isDescendant(maybeAncestor) {
  127. return !!this.findParent(parent => parent === maybeAncestor);
  128. }
  129. function inType(...candidateTypes) {
  130. let path = this;
  131. while (path) {
  132. for (const type of candidateTypes) {
  133. if (path.node.type === type) return true;
  134. }
  135. path = path.parentPath;
  136. }
  137. return false;
  138. }
  139. //# sourceMappingURL=ancestry.js.map