Created
June 15, 2021 08:41
-
-
Save nojvek/416560c9723da23f5aa0b72887c3286e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* returns a function that returns true when node matches the matcher. | |
* matchers can be built recursively. If a property of a matcher is a function, it is evaluated. | |
* | |
* @see https://astexplorer.net/ to explore how ESTree nodes are structured | |
* @example nodeMatcher({type: `Identifier`, name: `foo`})(node) | |
* | |
* @param {Obj} matcher | |
* @param {Obj} refObj | |
* @param {string} refKey | |
* @return {(node: Obj) => boolean} | |
*/ | |
exports.nodeMatcher = function nodeMatcher(matcher, refObj = null, refKey = ``) { | |
return function (node) { | |
// typeof null === `object`. handle that case | |
if (node === null || typeof node !== `object`) { | |
return false; | |
} | |
for (const [prop, matchValue] of Object.entries(matcher)) { | |
const nodeValue = node[prop]; | |
if (!(typeof matchValue === `function` && matchValue(nodeValue)) && matchValue !== nodeValue) { | |
// uncomment for debugging why a node didn't match | |
// console.log(`nodeMatcher '${prop}'`, typeof matchValue !== `function` ? `${matchValue} !== ${nodeValue}` : ``); | |
return false; | |
} | |
} | |
// if refObj is passed and node matches, save node reference | |
// this makes it easier to traverse an AST and capture reference of nodes of interest | |
if (refObj) { | |
refObj[refKey] = node; | |
} | |
return true; | |
}; | |
}; | |
/** | |
* returns a function that returns true when node matches any of the matchers. | |
* | |
* @param {Array<(node: Obj) => boolean>} matchers | |
* @return {(node: Obj) => boolean} | |
*/ | |
exports.anyMatcher = function anyMatcher(matchers) { | |
return function (node) { | |
for (const matcher of matchers) { | |
if (matcher(node)) { | |
return true; | |
} | |
} | |
return false; | |
}; | |
}; | |
/** | |
* returns a function that returns true when node matches all of the matchers. | |
* | |
* @param {Array<(node: Obj) => boolean>} matchers | |
* @return {(node: Obj) => boolean} | |
*/ | |
exports.allMatcher = function allMatcher(matchers) { | |
return function (node) { | |
for (const matcher of matchers) { | |
if (!matcher(node)) { | |
return false; | |
} | |
} | |
return true; | |
}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment