140 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			140 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| "use strict";
 | |
| 
 | |
| Object.defineProperty(exports, "__esModule", {
 | |
|   value: true
 | |
| });
 | |
| exports.find = find;
 | |
| exports.findParent = findParent;
 | |
| exports.getAncestry = getAncestry;
 | |
| exports.getDeepestCommonAncestorFrom = getDeepestCommonAncestorFrom;
 | |
| exports.getEarliestCommonAncestorFrom = getEarliestCommonAncestorFrom;
 | |
| exports.getFunctionParent = getFunctionParent;
 | |
| exports.getStatementParent = getStatementParent;
 | |
| exports.inType = inType;
 | |
| exports.isAncestor = isAncestor;
 | |
| exports.isDescendant = isDescendant;
 | |
| var _t = require("@babel/types");
 | |
| const {
 | |
|   VISITOR_KEYS
 | |
| } = _t;
 | |
| function findParent(callback) {
 | |
|   let path = this;
 | |
|   while (path = path.parentPath) {
 | |
|     if (callback(path)) return path;
 | |
|   }
 | |
|   return null;
 | |
| }
 | |
| function find(callback) {
 | |
|   let path = this;
 | |
|   do {
 | |
|     if (callback(path)) return path;
 | |
|   } while (path = path.parentPath);
 | |
|   return null;
 | |
| }
 | |
| function getFunctionParent() {
 | |
|   return this.findParent(p => p.isFunction());
 | |
| }
 | |
| function getStatementParent() {
 | |
|   let path = this;
 | |
|   do {
 | |
|     if (!path.parentPath || Array.isArray(path.container) && path.isStatement()) {
 | |
|       break;
 | |
|     } else {
 | |
|       path = path.parentPath;
 | |
|     }
 | |
|   } while (path);
 | |
|   if (path && (path.isProgram() || path.isFile())) {
 | |
|     throw new Error("File/Program node, we can't possibly find a statement parent to this");
 | |
|   }
 | |
|   return path;
 | |
| }
 | |
| function getEarliestCommonAncestorFrom(paths) {
 | |
|   return this.getDeepestCommonAncestorFrom(paths, function (deepest, i, ancestries) {
 | |
|     let earliest;
 | |
|     const keys = VISITOR_KEYS[deepest.type];
 | |
|     for (const ancestry of ancestries) {
 | |
|       const path = ancestry[i + 1];
 | |
|       if (!earliest) {
 | |
|         earliest = path;
 | |
|         continue;
 | |
|       }
 | |
|       if (path.listKey && earliest.listKey === path.listKey) {
 | |
|         if (path.key < earliest.key) {
 | |
|           earliest = path;
 | |
|           continue;
 | |
|         }
 | |
|       }
 | |
|       const earliestKeyIndex = keys.indexOf(earliest.parentKey);
 | |
|       const currentKeyIndex = keys.indexOf(path.parentKey);
 | |
|       if (earliestKeyIndex > currentKeyIndex) {
 | |
|         earliest = path;
 | |
|       }
 | |
|     }
 | |
|     return earliest;
 | |
|   });
 | |
| }
 | |
| function getDeepestCommonAncestorFrom(paths, filter) {
 | |
|   if (!paths.length) {
 | |
|     return this;
 | |
|   }
 | |
|   if (paths.length === 1) {
 | |
|     return paths[0];
 | |
|   }
 | |
|   let minDepth = Infinity;
 | |
|   let lastCommonIndex, lastCommon;
 | |
|   const ancestries = paths.map(path => {
 | |
|     const ancestry = [];
 | |
|     do {
 | |
|       ancestry.unshift(path);
 | |
|     } while ((path = path.parentPath) && path !== this);
 | |
|     if (ancestry.length < minDepth) {
 | |
|       minDepth = ancestry.length;
 | |
|     }
 | |
|     return ancestry;
 | |
|   });
 | |
|   const first = ancestries[0];
 | |
|   depthLoop: for (let i = 0; i < minDepth; i++) {
 | |
|     const shouldMatch = first[i];
 | |
|     for (const ancestry of ancestries) {
 | |
|       if (ancestry[i] !== shouldMatch) {
 | |
|         break depthLoop;
 | |
|       }
 | |
|     }
 | |
|     lastCommonIndex = i;
 | |
|     lastCommon = shouldMatch;
 | |
|   }
 | |
|   if (lastCommon) {
 | |
|     if (filter) {
 | |
|       return filter(lastCommon, lastCommonIndex, ancestries);
 | |
|     } else {
 | |
|       return lastCommon;
 | |
|     }
 | |
|   } else {
 | |
|     throw new Error("Couldn't find intersection");
 | |
|   }
 | |
| }
 | |
| function getAncestry() {
 | |
|   let path = this;
 | |
|   const paths = [];
 | |
|   do {
 | |
|     paths.push(path);
 | |
|   } while (path = path.parentPath);
 | |
|   return paths;
 | |
| }
 | |
| function isAncestor(maybeDescendant) {
 | |
|   return maybeDescendant.isDescendant(this);
 | |
| }
 | |
| function isDescendant(maybeAncestor) {
 | |
|   return !!this.findParent(parent => parent === maybeAncestor);
 | |
| }
 | |
| function inType(...candidateTypes) {
 | |
|   let path = this;
 | |
|   while (path) {
 | |
|     if (candidateTypes.includes(path.node.type)) return true;
 | |
|     path = path.parentPath;
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| //# sourceMappingURL=ancestry.js.map
 |