You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
4.6 KiB

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