Skip to content

リンターのアーキテクチャ

本文は @leaysgur 氏による leaysgur.github.io/posts の記事を基にしています。

apps/oxlint

oxlint バイナリは apps/oxlint クレートの main.rs をビルドしたものです。

Cargo.toml の設定

引数をパースしたあと LintRunner を実行します。

リント実行フロー

crates/oxc_diagnostics

LintServicempsc::channel の Sender を oxc_diagnostics に渡し、リント結果を受け取ります。

リント結果の受信

受け取ったメッセージを整形して表示します。整形は miette クレートが担当します。

miette クレート

crates/oxc_linter

LintService から始まります。

  • self.runtimeArc<Runtime> として保持
  • Runtime がリント対象のパスを保持
  • 実行時に rayonRuntime のパスを並列に走査
  • 最後に None を送って終了

LintService の実装

Runtime: process_path()

  • パスから拡張子と内容を推論
  • .[m|c]?[j|t]s または .[j|t]sx をサポート
  • .vue.astro.svelte は例外で、script ブロックを部分的にサポート
  • JavaScript / TypeScript のソースを処理
  • リントを実行し、結果を 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
  • など

ビルド時に SemanticBuilderReturn が生成されますが、LintContext に渡るのは Semantic のみです。

SemanticBuilder の戻り値

crates/oxc_linter: LintContext

LintContext のソース

文脈を表し、主として Semantic を抱えます。各種情報用のゲッタと、リント問題を報告する diagnostic() などがあります。

crates/oxc_linter: Linter

Linter のソース

この Linterrun() がリント処理の中核です。

  • Linter は対象ソースで実行するルールを self.rules に保持
  • 各ルールはトレイトに従い三種類の処理を実装できる
  • これらのパターンを順に実行する

現行のルール一覧は次を参照。

実装済みルール

新しいルールを足すときはこの一覧も更新すること。

リンターの例

最小構成のリンターコードがリポジトリにあります。

最小リンターコード