エラー処理

エントリポイント analyzeResult<FuncSpace, MetricsError> を返します。このページでは、各バリアントの意味と、それぞれへの対処方法を説明します。

注意。 MetricsError#[non_exhaustive] です。将来のバリアントに対する前方互換性を保つため、網羅的にマッチする際は必ず _ アームを含めてください。

エラーバリアントのパターンマッチ

use big_code_analysis::{analyze, LANG, MetricsError, MetricsOptions, Source};

fn main() {
    let result = analyze(
        Source::new(LANG::Rust, b"this is not rust")
            .with_name(Some("snippet.rs".to_owned())),
        MetricsOptions::default(),
    );

    match result {
        Ok(space) => println!("ok: {} lines", space.metrics.loc.sloc()),
        Err(MetricsError::EmptyRoot) => {
            eprintln!("walker produced no top-level FuncSpace");
        }
        Err(MetricsError::LanguageDisabled(lang)) => {
            eprintln!("language {:?} is not enabled in this build", lang);
        }
        // `MetricsError` は `#[non_exhaustive]` です。新しいバリアントが追加される可能性があります。
        Err(_) => eprintln!("unexpected MetricsError variant"),
    }
}

各バリアントの意味

  • EmptyRoot — 予約済みで、現在は生成されません。metrics_with_options は AST の走査前に必ず合成のトップレベル Unit FuncSpace をプッシュするため、空の入力・空白のみの入力・コメントのみの入力を含むすべてのパースが Ok(FuncSpace { kind: Unit, .. }) を返します。このバリアントは、状態スタックが正当に空になり得るような将来のウォーカー変更に備えて残されています。
  • LanguageDisabled(LANG) — 要求された LANG がこのビルドで有効になっていません。呼び出し側が、言語ごとの Cargo フィーチャが無効な LANG を選択すると、すべてのディスパッチエントリポイントがこのバリアントを生成します。デフォルトのフィーチャセット(all-languages)はすべての文法をコンパイルに含めるため、このバリアントを見るのは、より狭いセット(--no-default-features --features rust,…)にオプトインした後だけです。

MetricsError には ParseHasErrorsNonUtf8Path といったバリアントはありません。#[non_exhaustive] のままであるため、将来の厳格パースモードや厳格識別子モードは、破壊的変更なしにそれらを導入できます。非 UTF-8 のパスはすでに前段で処理されています。推奨エントリポイントの analyze は、呼び出し側が指定する Source::nameOption<String>)を受け取るため、損失のあるパスがそもそも往復されることはありません。

tree-sitter は常に「ノー」と言うわけではない

ほとんどのパースエラーは Err(_) としては 現れません。tree-sitter はエラー回復型のパーサーであり、構文的に壊れた入力に対してもツリーを生成し、問題のある領域を ERROR ノードでマークします。メトリクスの走査は、回復されたツリーの上で何事もなかったかのように数値を計算します。つまり次のことが起こります。

  • ゴミを入れれば、数値が出てきます。 C++ のソースを LANG::Python に与えても、たいていはメトリクスが無意味な Ok(FuncSpace) が返ります。結果を信頼する前に、正しい言語を選択していること(例えば guess_language を使って)を確認してください。
  • 不完全なファイルにもスコアが付きます。 閉じられていない波かっこを含む、途中で切れたファイルでも Ok(FuncSpace) が返ります。メトリクスは、意図されたソースではなく回復されたツリーを反映します。

入力が正常にパースされたかどうかを知る必要がある場合は、tree-sitter の AST を自分で走査して ERROR ノードを数えるか(STABILITY.mdNode エスケープハッチを参照)、CLI 側で bca find -t ERROR を使ってください(Nodes ページを参照)。

? による MetricsError の伝播

MetricsError は [std::error::Error] を実装しているため、ボイラープレートなしに任意の Result<_, Box<dyn Error>> チェーンを通して伝播させられます。

#![allow(unused)]
fn main() {
use std::error::Error;

use big_code_analysis::{analyze, FuncSpace, LANG, MetricsOptions, Source};

pub fn run(
    lang: LANG,
    source: &[u8],
    name: Option<String>,
) -> Result<FuncSpace, Box<dyn Error>> {
    Ok(analyze(
        Source::new(lang, source).with_name(name),
        MetricsOptions::default(),
    )?)
}
}

プロジェクト固有のエラー型が欲しい場合は、明示的な From 実装を書けば、呼び出し箇所を簡潔に保ちながら、追加のコンテキスト(ファイルパス、言語の推定結果など)を付与できます。

警告はエラーではない

ライブラリは、致命的でない問題(主に不正な形式の bca: 抑制マーカー)について stderr に警告を書き出します。警告は走査を中断させず、OkErr に変えることもありません。サーバーやライブラリの内部に組み込んで実行していて警告を捕捉する必要がある場合は、プロセスレベルで stderr をリダイレクトしてください。ライブラリは現在、プログラムから利用できる警告シンクを公開していません。