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();

DEMO

Обратите внимание, что эти методы шаблона (expression, statement, statements) имеют свои ограничения (вы можете интерполировать только узлы AST, где вы можете поместить идентификатор).


Если вы хотите создать foo.length вручную, вам придется создать MemberExpression:

введите описание изображения здесь

j.memberExpression(
  prop,
  j.identifier('length')
);
Другие вопросы по тегам