jscodeshift snippet - printing a whole MemberExpression
I’ve been writing codemods using jscodeshift. I find that while the main goal of codemods is to refactor code, I often have to print some output either for debugging or making sure I’m on the right path.
One of the things I had to do recently was to print a whole MemberExpression
based on a module name I was looking for. For example, consider the following code snippet.
myUtils.doAction();
// ...
myUtils.subModule.doAction();
// ...
myUtils[selectedSubModule][selectedAction]();
// ...
myUtils[selectedSubModule][SOME_NAMESPACE.CONSTANT_NAME];
From the code above, I want to be able to print, in full, all the MemberExpression
s related to myUtils
. Below is the desired output.
myUtils.doAction
myUtils.subModule.doAction
myUtils[selectedSubModule][selectedAction]
myUtils[selectedSubModule][SOME_NAMESPACE.CONSTANT_NAME]
This turns out to be a very simple thing to do. We just have to do the following.
- Locate a
MemberExpression
that has anIdentifier
namedmyUtils
as theobject
. -
If the
MemberExpression
from (1) is part of anotherMemberExpression
, find the rootMemberExpression
.(For example, the
myUtils.subModule
, though aMemberExpression
, is still theobject
inmyUtils.subModule.doAction
.) - Print the root
MemberExpression
usingtoSource()
.
We should end up with something like below.
// print-root-member-expressions.js
export default function printRootMemberExpressions(file, api) {
const j = api.jscodeshift;
const getRootMemberExpressionPath = p => {
if (j.MemberExpression.check(p.parent.node)) {
return p.parent;
}
return p;
};
const getRootMemberExpressionSource = p => {
const rootMemberExpressionPath = getRootMemberExpressionPath(p);
return j(rootMemberExpressionPath).toSource();
};
j(file.source)
.find(j.MemberExpression, {
object: {
name: "myUtils"
}
})
.forEach(path => {
console.log(getRootMemberExpressionSource(path));
});
}
See it in action on AST Explorer. Check the console log.