Изменение всех объявлений переменных let на const с помощью codemods в большой кодовой базе javascript

В кодовой базе я хочу использовать следующее соглашение:

      const a = 1;
const b = 2;

Однако в коде есть много областей, которые написаны следующим образом:

      let a = 1,
b = 2;

Я хочу написать codemod, возможно, используя JSCodeshift, который может изменить второй стиль объявления переменных на первый. Я проводил некоторые исследования AST и использую AST explorer. Однако у меня возникают проблемы с доступом к объявителю переменной "kind" в абстрактном синтаксическом дереве.

Вот пример того, что я пробовал:

      module.exports = function(file, api) {
  const j = api.jscodeshift;
  const root = j(file.source);

  // Step 1: Find all instances of the code to change
  const instances = root.find(VariableDeclarator.value.kind = 'let');

  // Step 2: Apply a code transformation and replace the code
  instances.forEach(instance => {
    j(path).replaceWith(VariableDeclarator.value.kind = 'const');
  });
  return root.toSource();
}
}

Любая помощь или направление будут оценены! Спасибо!

2 ответа

Вы можете использоватьPutoutпреобразователь кода, над которым я работаю, с@putout/plugin-split-variable-declarationsСюда:

      import putout from 'putout';

const {code} = putout('let a = 1, b = 2;', {
    plugins: [
        'split-variable-declarations',
        ['let-to-const', {
            report: () => 'convert let to const',
            replace: () => ({
                'let __a = __b': 'const __a = __b',
            }),
        }]
    ]
});
console.log(code);
// output
const a = 1;
const b = 2;

Вот пример изPutout Editor:

Похоже, что основная проблема, с которой вы сталкиваетесь, заключается в использовании правильного синтаксиса при использовании метода find. Например, изменение вашего

      const instances = root.find(VariableDeclarator.value.kind = 'let');

к

      const instances = root.find(j.VariableDeclaration, {kind: 'let'});

Вы должны использовать определение типа из api.jscodeshift.

Полный пример, который делает то, что вы просите, выглядит так:

      export default function transformer(file, api) {
  const j = api.jscodeshift;
  const root = j(file.source);
  
  const letDeclarations = root.find(j.VariableDeclaration, {kind: 'let'});

  letDeclarations.replaceWith(({value: {declarations}}) => {
    return declarations.map(dec => 
      j.variableDeclaration(dec.init ? 'const' : 'let', [dec])
    );
  });
  
  return root.toSource();
}

Это сделает следующее преобразование из:

      let a = 1,
    b = 2,
    c;
const d = 3;
let e = 4;
var f = 4;
c = 3;

к:

      const a = 1;
const b = 2;
let c;
const d = 3;
const e = 4;
var f = 4;
c = 3;

Этот кодмод будет преобразовывать только объявления let, которые включают инициализатор, поскольку это требуется для constдекларации.

См . полный пример в AST Explorer , чтобы поиграть с ним.

Другие вопросы по тегам