Skip to content

Linter 架构

本文最初发布于 leaysgur.github.io/posts,作者为 @leaysgur

apps/oxlint

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

Cargo.toml 配置

在这里,它解析参数然后运行 LintRunner

Lint 执行流程

crates/oxc_diagnostics

LintServicempsc::channel Sender 传递给 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 源文件
  • 执行 linting 并将结果发送到 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 为主体。它包含每条信息的 getter 以及像 diagnostic() 这样用于通知 lint 问题的方法。

crates/oxc_linter: Linter

Linter 源码

Linterrun() 函数是 lint 过程的核心。

  • Linterself.rules 中持有要在目标源上执行的规则
  • 每个规则可以根据 trait 实现三种类型的处理
  • 它按顺序执行这三种模式

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

已实现的规则

对于添加新规则,记得更新此列表。

Linter 示例

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

最小化 Linter 代码