188 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			188 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | "use strict"; | ||
|  | 
 | ||
|  | Object.defineProperty(exports, "__esModule", { | ||
|  |   value: true | ||
|  | }); | ||
|  | exports.findParent = findParent; | ||
|  | exports.find = find; | ||
|  | exports.getFunctionParent = getFunctionParent; | ||
|  | exports.getStatementParent = getStatementParent; | ||
|  | exports.getEarliestCommonAncestorFrom = getEarliestCommonAncestorFrom; | ||
|  | exports.getDeepestCommonAncestorFrom = getDeepestCommonAncestorFrom; | ||
|  | exports.getAncestry = getAncestry; | ||
|  | exports.isAncestor = isAncestor; | ||
|  | exports.isDescendant = isDescendant; | ||
|  | exports.inType = inType; | ||
|  | 
 | ||
|  | function t() { | ||
|  |   const data = _interopRequireWildcard(require("@babel/types")); | ||
|  | 
 | ||
|  |   t = function () { | ||
|  |     return data; | ||
|  |   }; | ||
|  | 
 | ||
|  |   return data; | ||
|  | } | ||
|  | 
 | ||
|  | var _index = _interopRequireDefault(require("./index")); | ||
|  | 
 | ||
|  | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
|  | 
 | ||
|  | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } | ||
|  | 
 | ||
|  | 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 = t().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() { | ||
|  |   let path = this; | ||
|  | 
 | ||
|  |   while (path) { | ||
|  |     for (const type of arguments) { | ||
|  |       if (path.node.type === type) return true; | ||
|  |     } | ||
|  | 
 | ||
|  |     path = path.parentPath; | ||
|  |   } | ||
|  | 
 | ||
|  |   return false; | ||
|  | } |