Новый инструмент от Alimama облегчает процесс пакетной модификации кодов проектов

внешний интерфейс

Были опубликованы последующие фактические боевые статьи:«Практика GogoCode» Узнайте, что подсказки для замены кода AST в одном Go


Как программист, вы, конечно, всегда ожидаете, что ваш код будет «написан один раз, работает везде», но реальный опыт часто таков: «одна модификация — сто заделок дыр», зависимости отстают на несколько версий, хочется обновить, старый код Я уже выгляжу очень неловко и планирую рефакторинг, и нам всем нужно принять твердое решение. Ведь там, где мы упускаем или допускаем ошибки, это может привести к катастрофе. Что мы обычно делаем?

сдаться


Мгновенно боль утихает, нет... но если вы настаиваете на этом, читайте ниже!

Истинный аромат и ограничения местных методов


Для некоторых простых нужд, таких как пример, недавно замеченный на Nuggets, удалите проект изconsole.log(xxx)Код, я полагаю, что первая идея, с которой обычно сталкивается каждый, — это прямой выбор редактора для замены основного текста пустой строкой:

image.png
С помощью регулярных выражений мы по-прежнему можем справиться со многими требованиями, но действительно ли они охватывают все случаи? Некоторым коллегам очень нравится возврат каретки.

console
	.log('aaa')

В этом случае, если мы сталкиваемся с более сложными требованиями или строгими сценариями, либо мы пишем более сложные регулярные выражения, либо нам приходится переходить к жестким операциям AST.

AST немного сложно


Поискав в интернете, я действительно нашел пример использования jscodeshift для работы AST для удаления console.log:

export default (fileInfo, api) => {
  const j = api.jscodeshift;

  const root = j(fileInfo.source)

  const callExpressions = root.find(j.CallExpression, {
      callee: {
        type: 'MemberExpression',
        object: { type: 'Identifier', name: 'console' },
      },
    }
  );

  callExpressions.remove();

  return root.toSource();
};

Это требует от всех знакомства со структурой AST.При написании необходимо писать медленно против разобранной структуры узла.Если смотреть через некоторое время,то лучше не будет,чем регулярность намотки-каждый Обычно слишком мало контакта с АСТ.

попробуй совместить


Однажды, когда я переживал за капитальный рефакторинг API проекта и готовился к взрыву, барышня рядом со мной уже не выдержала — ее проект рефакторили раньше меня, и мало того, что они не взорвались. , а также сделал инструментGoGoCode, этот инструмент заимствует две идеи из jQuery:

Селектора такжецепной вызов

удалить с помощью этого инструментаconsole.log(xxx), что на самом деле является предложением:

const $ = require('gogocode')

/** 刻意凌乱的代码 **/
const input = `
	console
.log(\`a, b,c\`);
`

// 关键代码
const output = $(input).replace('console.log()', '').generate()

console.log(output)

Что инновационно по этому поводу, это то, что он принимает ваш вкладconsole.log()Проанализируйте соответствие дерева узлов в разделе узла AST исходному коду, чтобы не было проблем с форматом кода. Введенный код эквивалентен селектору в jQuery, но на этот раз выбран узел кода.

больше примеров


очиститьconsole.logЭта операция еще слишком проста, я дам еще один каштан!

Мы часто используем перечисляемые списки следующим образом:

const list = [
  {
    text: "A策略",
    value: 1,
    tips: "Atip",
  },
  {
    text: "B策略",
    value: 2,
    tips: "Btip",
  },
  {
    text: "C策略",
    value: 3,
    tips: "Ctip",
  },
];

Внезапно однажды, чтобы унифицировать различные перечисления в коде, нам нужно переименовать атрибут text в имя и атрибут value в id.Это трудно точно сопоставить с обычными правилами и легко случайно повредить.Это немного неудобно работать с деревом AST.GoGoCodeПросто замените его на это:

const $ = require('gogocode')

const input = `

const list = [
  {
    text: "A策略",
    value: 1,
    tips: "Atip",
  },
  {
    text: "B策略",
    value: 2,
    tips: "Btip",
  },
  {
    text: "C策略",
    value: 3,
    tips: "Ctip",
  },
];

// ts的类型标记,这种正则替换会被错误替换的,在 gogocode 里就不会
const text: string = ''
// 这一段因为没有 value 就不会被选择器匹配到,也不会被错误替换
const cfg = {
  text: ''
}

`
  
const output = $(input2).replace(
  '{ text: $_$1, value: $_$2, $$$ }',
  '{ name: $_$1, id: $_$2, $$$ }'
).generate();

в$_$1а также$_$2Это эквивалентно подстановочному знаку в обычном, но здесь он будет соответствовать только действительным узлам AST в коде,$$$Затем вы можете сопоставить оставшиеся узлы, как в es6...., этот код соответствуетtextа такжеvalueСоответствующее значение заполняетсяnameа такжеid, а остальные верните обратно целыми.

Во второй части я намеренно добавил несколько «кодов помех», раньше использовал замену строкtext:дляname:Локальный способ столкнуться с такой ситуацией приведет к случайной травме, ноGoGoCodeНе будет.

Посмотрите на пример из сообщества в предыдущем абзаце


Случайно увидел статью в Наггетс в предыдущем абзацеИграйте в AST как в jQuery, в котором представлен пример преобразования кода React jsx с помощью jscodeshift:

Я планирую внести изменения в этот код:

  • Изменен импорт с @alifd/next на antd
  • до перевода после перевода
  • Преобразование параметра типа в кнопке: обычное -> по умолчанию, среднее -> среднее
  • Измените текстовый параметр в кнопке на type="link"
  • Измените параметр предупреждения в кнопке на опасность
import * as React from 'react';
import styles from './index.module.scss';
import { Button } from "@alifd/next";

const Btn = () => {
  return (
    <div>
      <h2>转译前</h2>
      <div>
        <Button type="normal">Normal</Button>
        <Button type="primary">Prirmary</Button>
        <Button type="secondary">Secondary</Button>
        
        <Button type="normal" text>Normal</Button>
        <Button type="primary" text>Primary</Button>
        <Button type="secondary" text>Secondary</Button>
        
        <Button type="normal" warning>Normal</Button>
      </div>
    </div>
  );
};

export default Btn;

Вероятно, что-то вроде этого:

image.png
Такого рода требования на самом деле довольно распространены.Реализация на основе jscodeshift, вглубь AST для манипуляций, но если использоватьGoGoCodeЭто будет гораздо более интуитивно понятно:

// 省略依赖和 input
const output = $(input)
  .replace(`import { $$$ } from "@alifd/next"`, `import { $$$ } from "antd"`)
  .replace(`<h2>转译前</h2>`, `<h2>转译后</h2>`)
  .replace(
    `<Button type="normal" $$$></Button>`,
    `<Button type="default" $$$></Button>`
  )
  .replace(
    `<Button size="medium" $$$></Button>`,
    `<Button size="middle" $$$></Button>`
  )
  .replace(`<Button text $$$></Button>`, `<Button type="link" $$$></Button>`)
  .replace(`<Button warning $$$></Button>`, `<Button danger $$$></Button>`)
  .generate();

Я полагаю, что вы можете понять, что делает этот код, не объясняя его ~

Открытый исходный код, надеюсь получить ваши отзывы


Я считаю этот проект очень интересным.Можно сказать,что программа замены специально сделана для кода.Дама сказала,что я слишком ясно увидела.На самом деле этот проект не только трюк замены,этот проект нас поддержал несколько десятков тысяч Выполнение плана модернизации архитектуры фронтенд-инжиниринга, даже если требования более сложные, способ все же естьвозьмиДа, вы можете подписаться на нашу учетную запись или колонку, и позже автор опубликует более профессиональную и исчерпывающую вводную статью.

Мисс Йе Си из нашей команды Alimama MUX.iconfont,Rap,MockJSТакой проект приветствуется сообществом, на этот раз мы ставимGoGoCodeТакже с открытым исходным кодом на Github:GitHub.com/thx/gogo код…, я надеюсь, что это может быть полезно для друзей, у которых также есть много потребностей в модификации кода.

Мы хотели бы знать, с какими проблемами конвертации вы часто сталкиваетесь, если используете текущуюGoGoCodeНеудобно решать или делать ошибки, надеюсь, вы можете указать нам на это (проблема:GitHub.com/thx/gogo код…Группа QQ: 735216094).

Напоследок: новые проекты просят звездной поддержки!

Гитхаб:GitHub.com/thx/gogo код…
Официальный сайт:gogocode.io