嗨,我是锈儿海老师,ast-grep的作者。
一说起SSR,是不是就想起了氪金抽卡Super Super Rare? 或者说Hydration Mismatch的服务端渲染Server Side Rendering? 今天我们讲一个你所不知道的SSR。
如果你曾以正则表达式方式搜索代码,可能已经遭遇过各种痛点:多行匹配困难、嵌套结构处理差强人意,甚至不能有效地忽略注释。
我要介绍的ast-grep VSCode,就是用来解决这些问题的。这个全新的扩展插件利用结构化搜索与替换(Structural Search/Replace)的技术,让你能执行更准确、更高效的搜索和替换。
文本搜索与替换的短板
我们举一个例子吧:假设你正打算重构JavaScript代码,将lodash库的_.filter
函数改成原生的Array.prototype.filter
方法。你可能会用以下方式进行简单的文本搜索与替换:
regex
// 查找
_.filter\((\.+), (.+)\)
// 替换
$1.filter($2)
在一些特定的场景下,这样做倒是挺有效的,但真的只适用于那些非常特定的场景:
- 它只能匹配单行表达式。一旦你的代码跨行,可能会导致匹配不准或替换失败。
- 对于括号、方括号或大括号这样的嵌套结构,它根本无能为力。如果你的代码有复杂表达式,可能会导致错误的匹配或替换。
- 它无法有效地忽略注释或其他无关紧要的代码部分。这就导致了一个尴尬的局面:如果你的代码中的注释包含了搜索模式,你可能会错匹配或者错替换。
- 它需要你使用匹配组或命名捕获组来保留函数的参数,使整个过程变得繁琐并且容易出错,尤其是在参数较多或有嵌套函数的情况下。
结构化搜索与替换(SSR):或许是我们需要的解决方案
现在问题来了,我们能不能让我们的搜索算法更智能一点,能更好地理解我们的代码,并且更易于使用呢?答案是,可以的!结构化搜索与替换(SSR)就能胜任这个任务!
结构化搜索与替换(SSR)这种技术,能够基于代码的语法和语义来识别并修改代码模式,而不仅仅是基于文本去操作。正因如此,SSR并不将代码视为纯文本,而是将代码视为包含类型、属性和关系的节点集合。
ast-grep就是一个实现了SSR技术的命令行工具。回到刚才lodash的例子,用ast-grep来进行操作,该查询的代码将会变得非常简洁和直接。
javascript
// 查询模式:
_.filter($ARR, $FUNC)
// 替换代码:
$ARR.filter($FUNC)
在这个样例中,你就已经看出ast-grep的基本用法了。$ARR
和$FUNC
是元变量。元变量的功能相近于正则表达式中的".",但是元变量匹配的是AST节点,而不仅仅是一个字符。在你重写代码时,你可以使用之前捕获到的元变量。
除此之外,查询模式和替换代码应该已经非常明了。
通过这个例子,你可以看到SSR相比于文本搜索和替换有以下显著的优点:
- 它对语法正确的代码,可以跨行进行匹配。
- 它可以处理诸如括号、方括号或大括号这样的嵌套结构,因为它们是AST的一部分。
- 它可以有效地忽略注释或代码的其他无关部分,因为它们并不在AST中。
- 在搜索模式中,元变量可以通过名字进行访问,因此它并不需要匹配组或命名捕获组。
ast-grep的独特之处
ast-grep使用了tree-sitter库,这是一个快速稳健的多语言解析器。ast-grep允许你用非常简单的模式语法编写查询------就像你写代码一样------并且可以将查询应用到代码文件或者文件夹上。ast-grep的独特特性有:
- 它支持众多的编程语言,包括JavaScript、TypeScript、Python、Ruby、Java、C#、Go、Rust等等。你甚至可以通过在设置中注册tree-sitter语法,以添加对新语言的支持。
- 它是Rust编写的,这使得它运行速度极快,同时具有高内存效率。
- 它提供了丰富的选项和标志,比如预运行、交互模式、彩色输出等等。你可以根据自己的需求和偏好来定制你的SSR使用体验。
然而,问题在于,ast-grep目前只提供了命令行接口。我们能否不需要在终端和编辑器间频繁切换,就能便捷高效地使用它呢?
ast-grep VSCode:将你的命令行接口与编辑器无缝衔接
ast-grep VSCode就是这样一款新扩展,将ast-grep与目前最火的代码编辑器Visual Studio Code融为一体。有了ast-grep VSCode,你就可以直接在编辑器内部使用SSR了,无需打断你的工作流程。
结构化搜索,替换,我全都要!!
ast-grep VSCode提供了下面这些功能:
- 用户界面,用于编辑和执行SSR查询,你还可以在侧边栏查看查询结果,包括预览和更改。
- 兼备linting和代码修复功能。你可以设定好一个ast-grep项目,然后按照自己的需求编写自定义规则。
- 完美集成VS Code,使你感觉就像在使用VS Code的一个原生功能。
特性 | 截图 |
---|---|
搜索模式 | |
在文件夹中搜索 | |
替换预览 | |
提交替换结果 | |
代码lint |
对比其它的SSR工具
目前市面上已有很多其他的SSR工具和扩展插件,我相信ast-grep VSCode是VS Code中所有SSR扩展插件中最好的一个,原因有以下几点:
- 它速度迅快,内存占用低,因为它是用Rust编写的,底层运用的是多线程命令行接口。
- 它支持多种语言,因为它使用了被广泛应用和维护的tree-sitter语法。
- 它的界面操作友好,直观易懂,甚至让人感觉它就是VS Code的内置功能。你可以在这里看到它的实际操作效果。
最后,我想分享一些在ast-grep VSCode中使用的React技术,使得它能实现快速响应:
- 使用了
useSyncExternalStore
来管理来自ast-grep CLI的流式结果。这个 hook允许组件订阅外部可变数据源,并相应地更新渲染。这样,扩展可以在结果可用时立即显示结果。 - 使用
useDeferredValue
来延迟结果列表的渲染。这个 hook可以避免阻塞用户输入,并通过延迟对派生状态的更新来改善 UI 的感知性能,直到下一个并发渲染。 - 为了减少JavaScript的工作量,精心利用了大量的memo和CSS技巧。
结语
我希望本文能帮助你了解SSR的优点以及ast-grep VSCode的特色功能。如果你对试用感兴趣,可以在VSCode Marketplace安装它。ast-grep VSCode还处在开发阶段,有很大的提升空间。我非常欢迎你提供反馈和建议,所以请随时在GitHub上提出问题或请求。也要感谢SoonIter、Steven Love、Nyakku Shigure和ssr.nvim带来的贡献和启发!
祝你搜索替换愉快!