codemod от ForInStatement к ForStatement
У меня есть codemod, где я хочу преобразовать
for (var key in foo){}
в
for (var keys = 0; key < foo; key++){}
Мне удалось это далеко:
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++)
{}
Я все еще немного потерян, создавая вещи с нуля...
Вопрос:
- Я делаю это правильно? чувствует себя довольно многословно, но, возможно, это путь.
- Как закончить? Мне не хватает например
foo.length
...
PS: Felix Kling, если вы читаете это, укажите мне, куда я могу отправить запросы на извлечение, чтобы улучшить документы! Я рад помочь с этим, когда я пытаюсь изучить этот API. О, и Феликс, какой замечательный инструмент вы сделали, ребята!
1 ответ
Создание узлов AST напрямую действительно многословно. Однако jscodeshift экспортирует некоторые вспомогательные "методы", которые позволяют генерировать узлы AST из строки и позволяют интерполировать существующие узлы AST (помеченные шаблоны ftw!).
Ваш приведенный выше пример может быть упрощен до:
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();
Обратите внимание, что эти методы шаблона (expression
, statement
, statements
) имеют свои ограничения (вы можете интерполировать только узлы AST, где вы можете поместить идентификатор).
Если вы хотите создать foo.length
вручную, вам придется создать MemberExpression
:
j.memberExpression(
prop,
j.identifier('length')
);