Skip to content

Linter 架构

本文最初发布于 @leaysgurleaysgur.github.io/posts

apps/oxlint

oxlint 二进制文件是构建 apps/oxlint crate 中的 main.rs 得到的结果。

Cargo.toml 配置

此处解析参数,然后运行 LintRunner

Linter 执行流程

crates/oxc_diagnostics

LintServicempsc::channel 的发送端传递给 oxc_diagnostics,以接收 lint 结果。

接收 lint 结果

它格式化并显示接收到的消息。格式化由 miette crate 完成。

miette crate 参考

crates/oxc_linter

LintService 开始:

  • 持有 self.runtime 作为 Arc<Runtime>
  • Runtime 持有 lint 所需的路径
  • 运行时,使用 rayon 并行遍历 Runtime 中的路径
  • 发送 None 以表示完成

LintService 实现

Runtime: process_path()

  • 从路径推断扩展名和内容
  • 支持 .[m|c]?[j|t]s.[j|t]sx 扩展名
  • .vue.astro.svelte 有例外处理,对 script 块提供部分支持
  • 处理 JavaScript 与 TypeScript 源码
  • 执行 lint 检查,并将结果发送至 DiagnosticService

Runtime 路径处理

Runtime: process_source()

  • 使用解析器处理源码,生成 AST
  • SemanticBuilder 创建 LintContext,并将其传递给 Linter 执行

Runtime 源码处理

crates/oxc_semantic: SemanticBuilder

SemanticBuilder 用于构建从源码中提取的语义信息。

SemanticBuilder 源码

  • source_text: 源代码
  • nodes: AST 节点
  • classes: 类
  • scopes: 作用域
  • trivias: 注释
  • jsdoc: JSDoc
  • 等等

SemanticBuilder 构建完成后,会生成 SemanticBuilderReturn,但只有 Semantic 会被传递给 LintContext

SemanticBuilder 返回值

crates/oxc_linter: LintContext

LintContext 源码

表示上下文,以 Semantic 为核心主体。包含每项信息的获取器,以及如 diagnostic() 等方法,用于通知 lint 问题。

crates/oxc_linter: Linter

Linter 源码

Linterrun() 函数是 lint 处理的核心。

  • Linterself.rules 中持有待执行的规则
  • 每个规则可根据特性实现三种类型的处理
  • 依次执行这三种模式

关于当前已实现的规则,请参考此列表。

已实现的规则

添加新规则时,请记得更新此列表。

Linter 示例

该仓库提供了创建 linter 所需的最小代码配置。

最小 Linter 代码