replace一把梭!

阅读时间约 2 分钟

去掉console.log

对于一些简单的需求,比如去掉项目中 console.log(xxx) 代码,相信大家平时遇到这种需求第一个想法都是利用正则表达式,但这样真的能包含所有情况么?

console
	.log('aaa')

包含回车的情况下,或者面对更复杂的需求更严谨的场景,就需要编写更复杂的正则表达式。那么用GoGoCode怎么实现呢?

const $ = require('gogocode')

const output = $(input).replace('console.log()', '').generate()

GoGoCode会把你输入的 console.log() 解析成一段 AST 节点去源代码里做节点树的匹配,这样自然就没有代码格式的问题了。你输入的代码就相当于 jQuery 里面的选择器,只不过这一次选择的是代码节点。


枚举列表属性更名

我们经常使用这样的枚举列表:

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

突然有一天,为了统一代码里的各种枚举,我们需要把 text 属性更名为 name,把 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 里的 ... ,这段代码匹配出了 textvalue 这对应的值填给了 nameid,剩下的原封不动放回去。
而下半部分的「干扰代码」,以往通过字符串替换 text:name:的土办法遇到这样的就会误伤了,但GoGoCode不会。

jsx标签属性替换

对这样一份代码做修改:

  • 从 @alifd/next 导入改成 antd
  • 转译前 改成 转译后
  • Button 中 type 参数转换:normal -> default,medium -> middle
  • Button 中有 text 参数的改成 type="link"
  • Button 中warning 参数的改成 danger
import * as React from 'react';
import * as 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 用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();

相信你不要讲解也能知道这段代码是要做什么了~

$_$和$$$的区别

  • $_$1$_$2 相当于正则中的通配符,但是在这里只会匹配代码里有效的 AST 节点
  • $$$1 $$$2 则可以匹配剩下的节点,有点像 es6 里的 ...,体现在AST结构里,$$$节点需要在数组属性内

如下例:

function doSth (a, $$$1) {

  	sth(a)
  	
  	$$$2
}

$$$1在params属性内


$$$2在body属性内