メトリクスの選択
By default, every call to analyze computes the full metric suite: ABC, cognitive, cyclomatic, Halstead, LoC, MI, NArgs, NExits, NOM, NPA, NPM, tokens, and WMC (see Metrics for what each measures). That is the right default for the CLI, where the user has asked for the metrics, but it is heavyweight for callers that only want one number per file.
MetricsOptions::with_only(&[Metric]) restricts the walker to a subset of metrics. Unselected metrics are skipped at the per-node level (no T::Halstead::compute, no T::Cognitive::compute, and so on) and elided from the CodeMetrics serialization output.
具体例
LoC だけを計算し、その結果を読み取ります。
use big_code_analysis::{analyze, LANG, Metric, MetricsOptions, Source};
fn main() {
let source = b"fn f(x: i32) -> i32 { if x > 0 { 1 } else { 0 } }";
let opts = MetricsOptions::default().with_only(&[Metric::Loc]);
let space = analyze(
Source::new(LANG::Rust, source).with_name(Some("snippet.rs".to_owned())),
opts,
)
.expect("parses");
// LoC was selected, so it carries real numbers.
println!("ploc = {}", space.metrics.loc.ploc());
// Halstead、cognitive、cyclomatic などはスキップされました。
// それらの `Stats` フィールドは `Default` のままで、JSON 出力からは省略されます。
let json = serde_json::to_string_pretty(&space.metrics).unwrap();
println!("{json}");
}
この呼び出しの JSON 出力に含まれるのは loc オブジェクトだけで、その他のメトリクスは存在しません。
メトリクス間の依存関係
Some metrics are derived: they consume the outputs of other metrics during the finalize step, or divide by a count another metric owns. Metric::dependencies is the source of truth:
| メトリクス | 依存関係 |
|---|---|
Metric::Mi | Loc, Cyclomatic, Halstead |
Metric::Wmc | Cyclomatic, Nom |
Metric::Cognitive, Metric::Nexits, Metric::Nargs | Nom (the per-function average’s divisor) |
with_only automatically adds the selected metrics’ dependencies. Selecting Mi therefore also computes Loc, Cyclomatic and Halstead, rather than calculating MI from default-zero inputs:
#![allow(unused)]
fn main() {
use big_code_analysis::{Metric, MetricsOptions};
let opts = MetricsOptions::default().with_only(&[Metric::Mi]);
// The stored set now contains Mi + Loc + Cyclomatic + Halstead;
// `MetricsOptions::with_metric_set` closes a `MetricSet` the same way.
}
最終的な選択集合は、得られた FuncSpace から space.metrics.selected() を介して確認できます。
#![allow(unused)]
fn main() {
use big_code_analysis::{analyze, LANG, Metric, MetricsOptions, Source};
let space = analyze(
Source::new(LANG::Rust, b"fn f() {}"),
MetricsOptions::default().with_only(&[Metric::Mi]),
).unwrap();
let sel = space.metrics.selected();
assert!(sel.contains(Metric::Mi));
assert!(sel.contains(Metric::Loc)); // 自動的に追加された依存メトリクス
}
デフォルトの動作は変わりません
MetricsOptions::default() はすべてのメトリクスを選択します。with_only なしで analyze(または Ast::metrics)を呼び出すと、従来とバイト単位で同一の JSON が生成されます。
「X 以外のすべて」はどうするか
There is no built-in complement API: with_only takes a positive selection, not an exclusion list. The asymmetry is deliberate and keeps the dependency closure unambiguous. A positive list always grows through Metric::dependencies, whereas an exclusion list would need to decide what to do when the caller excludes a dependency of a metric they kept.
If you want “all except Halstead”, build the list explicitly. Because Metric is #[non_exhaustive], downstream crates can construct the variants but cannot exhaustively match on them. The conventional pattern is to enumerate the variants you want and accept that a future Metric variant will not silently opt you in:
#![allow(unused)]
fn main() {
use big_code_analysis::{Metric, MetricsOptions};
let opts = MetricsOptions::default().with_only(&[
Metric::Cognitive,
Metric::Cyclomatic,
Metric::Loc,
Metric::Nom,
Metric::Tokens,
Metric::Nargs,
Metric::Nexits,
Metric::Abc,
Metric::Npm,
Metric::Npa,
Metric::Wmc,
// Metric::Mi は意図的に省略しています。依存関係の閉包を通じて
// Halstead を再び引き込んでしまうためです。
]);
}
Note the trap: keeping Metric::Mi re-adds Metric::Halstead through Metric::dependencies. To drop Halstead you must also drop Mi.
with_only を使うべき場面
- Hot paths that need only one or two metrics per file. Halstead in particular owns its own per-space
HalsteadMapsallocation and is the headline saving for an LoC-only run. - CI integrations that display one number (a cognitive-complexity gate, say) and want the rest of
CodeMetricsto drop out of the cached JSON payload. big-code-analysisを自前のレポートに組み込むライブラリ呼び出し側。この機能がなければ、自分の UI にすべてのメトリクスのフィールドが表示されてしまいます。
メトリクス単位の Cargo フィーチャ(コンパイル時の除去)は、このノブの対象外です。