想要像大神一样用jscodeshift改代码吗?别再用那些烦人的命令式API了。试试ast-grep的Find & Patch,一个用声明式语言改代码的新玩法。它既强大又简单,美美哒。😍
ast-grep重写代码简简单单就两个概念:一、 用规则来找到代码,二、生成修复代码替换ast节点。你可以用它来搞各种代码转换,比如重构,修bug,代码迁移,或者代码生成。想怎么玩就怎么玩!!🚀
下面就是一个简单的把console.log
改写成logger
的规则。
rule:
pattern: console.log($MSG) # 找到console.log
fix: logger.log($MSG) # 改写成logger.log
但是有个坑。ast-grep里简单的“Find & Patch”流程只能一次换一个节点。这意味着我们不能搞涉及多个节点或节点列表的转换。比如,把barrel import改成single import。
import {a, b, c} from './barrel';
// 改写成
import a from './barrel/a';
import b from './barrel/b';
import c from './barrel/c';
别怕,我们有招。ast-grep通过加rewriter子规则来升级Find & Patch,可以在匹配过程中应用到特定节点的单独规则。这让我们可以用多个不同的规则来搞多个节点。聪明吧?
# 找import语句
rule:
pattern: import {$$$IDENTS} from './barrel'
# 注册子规则
rewriters:
- id: rewrite-identifer
rule:
pattern: $IDENT # 继续找identifier语句
kind: identifier
fix: import $IDENT from './barrel/$IDENT' # 改写成import
# 使用子规则
transform:
IMPORTS:
rewrite:
source: $$$IDENTS # 找到AST子树
rewriters: [rewrite-identifer] # 运用子规则
joinBy: "\n"
rewriter子规则就像旧的“Find and Patch”流程,但是递归的。就像把旧流程反复应用到匹配的节点上。我们可以用rewriter子规则来把barrel import里的每个标识符改成单个import语句。在线演示
编程在树上
Find & Patch是ast-grep专门为AST操作而设计的新玩法,但是它可以做到和函数式编程语言类似的功能,帮助你用声明式和优雅的方式转换你的代码。我们可以把Find & Patch看作是AST上的“函数式编程”。
如果你觉得Find & Patch有用和有趣,可以看看博客文章或者在线演示来试试ast-grep。
请转发这个摘要,阅读完整文章,或者回复你的想法。我很想听听你的意见!