I have a codemod where I want to transform
for (var key in foo){}
into
for (var keys = 0; key < foo; key++){}
I managed this far:
return j(file.source)
.find(j.ForInStatement)
.replaceWith(p => {
var prop = p.node.left.declarations[0].id;
var v = [j.variableDeclarator(prop, null)];
var varDec = j.variableDeclaration('var', v);
var binary = j.binaryExpression('<', prop, j.identifier('foo'));
var uE = j.updateExpression('++', prop, false);
var block = j.blockStatement([]);
var forIn = j.forStatement(varDec, binary, uE, block);
return forIn;
})
.toSource();
for (var key; key < foo; key++)
{}
I'm still a bit lost creating things from scratch...
Question:
foo.length
...PS: Felix, if you are reading this, do point me where can I send pull requests to improve the docs! I am happy to help with that while I trying to learn this API. Oh, and Felix, what a nice tool you guys made!
Creating AST nodes directly is indeed verbose. However, jscodeshift exports some helper "methods" that allow you to generate AST nodes from a string and let you interpolate existing AST nodes (tagged templates ftw!).
Your above example could be simplified to:
return j(file.source)
.find(j.ForInStatement)
.replaceWith(p => {
var prop = p.node.left.declarations[0].id;
return statement`for (var ${prop} = 0; ${prop} < foo.length; ${prop}++) ${p.node.body}`;
})
.toSource();
Note though that those template methods (expression
, statement
, statements
) have their limitations (you can only interpolate AST nodes where you can put an identifier).
If you wanted to create foo.length
manually, you would have to create a MemberExpression
:
j.memberExpression(
prop,
j.identifier('length')
);