Biome

GritQL

GritQL 在 Biome 中的基本用法。

GritQL 是一种查询语言,用于对源代码进行结构化搜索。这意味着在你的搜索查询中, 空白字符甚至字符串使用的引号类型等无关文本都会被忽略。此外,它还提供许多查询 语法结构的能力,例如代码片段、匹配、嵌套和变量。

GritQL 是开源项目,由 Grit.io 创建。

支持的语言

Biome 中的 GritQL 目前支持以下目标语言:

  • JavaScript/TypeScriptlanguage js(可选变体:typescriptjsx
  • CSSlanguage css
  • JSONlanguage json

Biome 将 GritQL 用于两个目的:

在 Analyzer 插件中使用 GritQL 时,模式还可以包含重写(=>),以提供可修复的 诊断信息。关于安全修复与不安全修复以及 fix_kind 的详情,参见 Linter 插件

模式

GritQL 查询通过_模式_工作。你最常看到的模式是代码片段,它看起来就像用反引号包裹的普通源代码:

`console.log('Hello, world!')`

该模式会匹配以字符串 'Hello, world!' 作为参数的任意 console.log() 调用。 但由于 GritQL 做的是_结构化_匹配,它不关心格式化细节。以下写法也能匹配:

console.log (
    'Hello, world!'
)

下面这个也可以(注意引号变了):

console.log("Hello, world!")
biome search '`console.log($message)`' # 查找所有 `console.log` 调用

变量

GritQL 查询还可以包含_变量_。下面这个会匹配任意对 console.log() 的调用,无论传入什么消息:

`console.log($message)`

这个也能匹配 console 对象上的任意方法:

`console.$method($message)`

同一个变量名可以在单个片段中出现多次:

`$fn && $fn()`

它会匹配 foo && foo(),甚至 foo.bar && foo.bar(),但不会匹配 foo && bar()

条件

你可以使用 where 操作符为模式添加条件。它通常与_匹配操作符_ <: 搭配使用:

`console.$method($message)` where {
    $method <: `log`
}

该查询与我们之前看到的 console.log($message) 模式等价,但加入其他操作符后它会迅速变得更有趣:

`console.$method($message)` where {
    $method <: or { `log`, `info`, `warn`, `error` }
}

匹配 Biome 语法节点

若需要更精确的查询,你可以直接匹配 Biome 的内部语法节点。每个节点由一个唯一的 PascalCase 名称标识。

例如,要查找所有 JavaScript if 语句,可以匹配 JsIfStatement 节点:

engine biome(1.0)
language js(typescript,jsx)

JsIfStatement() as $stmt where {
  register_diagnostic(
    span=$stmt,
    message="Found an if statement"
  )
}

你也可以按名称匹配节点的特定部分。例如,这个模式使用 Biome 的节点字段名捕获三元表达式的第一个分支:

JsConditionalExpression(consequent = $cons) where {
  register_diagnostic(
    span=$cons,
    message="Found the consequent branch of a conditional expression"
  )
}

你可以通过浏览 Biome Playground 中的语法树,找到代码对应的节点名和字段名。所有可用节点及其字段的完整列表也可以在 Biome 仓库 xtask/codegen 目录下的 .ungram 文件中找到。

JSON 模式

GritQL 可以匹配 JSON 文件中的模式,适合用于搜索和转换配置文件:

language json

`"foo": $value`

该模式匹配键为 "foo" 的任意 JSON 成员。

若要更精确地匹配,你可以直接使用 Biome 的 JSON 语法节点:

language json

JsonMember(name = JsonMemberName(value = `"version"`))

JSON 的 GritQL 还支持与 TreeSitter 兼容的节点别名,以便兼容已有的 Grit 模式:

Biome ASTTreeSitter 别名
JsonMemberpair
JsonObjectValueobject
JsonArrayValuearray

语言文档

关于 GritQL 及其语法的更多信息,参见官方 GritQL 语言文档

请注意,Biome 尚未支持 Grit 的全部功能。

集成状态

Biome 对 GritQL 的支持正在积极开发中。许多功能已经可用,但仍可能出现缺陷,也有些功能完全缺失。

关于哪些 GritQL 功能已获支持、哪些仍在开发中的详细概览,参见 GitHub issue: https://github.com/biomejs/biome/issues/2582。

我们还有一份详细的 RFC,为插件工作指明方向: https://github.com/biomejs/biome/discussions/1762

tl;dr:我们正在开发对插件的支持,插件可以是纯 GritQL 插件,也可以是使用 GritQL 选取要操作代码的 JS/TS 插件。敬请期待!