リンターのアーキテクチャ
本文は @leaysgur 氏による leaysgur.github.io/posts の記事を基にしています。
apps/oxlint
oxlint バイナリは apps/oxlint クレートの main.rs をビルドしたものです。
引数をパースしたあと LintRunner を実行します。
crates/oxc_diagnostics
LintService が mpsc::channel の Sender を oxc_diagnostics に渡し、リント結果を受け取ります。
受け取ったメッセージを整形して表示します。整形は miette クレートが担当します。
crates/oxc_linter
LintService から始まります。
self.runtimeをArc<Runtime>として保持Runtimeがリント対象のパスを保持- 実行時に
rayonでRuntimeのパスを並列に走査 - 最後に
Noneを送って終了
Runtime: process_path()
- パスから拡張子と内容を推論
.[m|c]?[j|t]sまたは.[j|t]sxをサポート.vue、.astro、.svelteは例外で、scriptブロックを部分的にサポート- JavaScript / TypeScript のソースを処理
- リントを実行し、結果を
DiagnosticServiceへ送る
Runtime: process_source()
- パーサでソースを AST にし、
SemanticBuilderからLintContextを作りLinterに通す
crates/oxc_semantic: SemanticBuilder
SemanticBuilder がソースから意味情報を構築します。
source_text: ソースコードnodes: AST ノードclasses: クラスscopes: スコープtrivias: コメントjsdoc: JSDoc- など
ビルド時に SemanticBuilderReturn が生成されますが、LintContext に渡るのは Semantic のみです。
crates/oxc_linter: LintContext
文脈を表し、主として Semantic を抱えます。各種情報用のゲッタと、リント問題を報告する diagnostic() などがあります。
crates/oxc_linter: Linter
この Linter の run() がリント処理の中核です。
Linterは対象ソースで実行するルールをself.rulesに保持- 各ルールはトレイトに従い三種類の処理を実装できる
- これらのパターンを順に実行する
現行のルール一覧は次を参照。
新しいルールを足すときはこの一覧も更新すること。
リンターの例
最小構成のリンターコードがリポジトリにあります。