Quick start
This page walks through the minimum amount of code needed to compute metrics from a string of source code.
1. Add the crate
# Cargo.toml
[dependencies]
big-code-analysis = "1.1.0"
The crate uses Rust edition 2024 and pins rust-version = "1.94".
Older toolchains will not build it — see the
MSRV section of STABILITY.md for the policy.
2. Compute metrics from a string
The recommended entry point is analyze: pass a Source
carrying the language, source bytes, and an optional display name,
plus a MetricsOptions for any per-traversal flags. No
filesystem path is needed.
use big_code_analysis::{analyze, MetricsOptions, Source, LANG}; fn main() { let source = "fn add(a: i32, b: i32) -> i32 { a + b }"; let space = analyze( Source::new(LANG::Rust, source.as_bytes()) .with_name(Some("snippet.rs".to_owned())), MetricsOptions::default(), ) .expect("Rust source should parse"); println!( "cognitive complexity (file-level): {}", space.metrics.cognitive.cognitive_sum(), ); }
Source::name ends up as the top-level FuncSpace::name; passing
None leaves the top-level name unset. The return type is
Result<FuncSpace, MetricsError>. The Err variant
tells parse-failure apart from empty-input apart from disabled-
language; see Error handling for the variant
set and matching patterns. MetricsError is #[non_exhaustive], so
always include a _ arm when matching.
Tip: use big_code_analysis::prelude::*; brings the recommended
entry points (analyze, Source, MetricsOptions, MetricsError,
LANG, FuncSpace, CodeMetrics, SpaceKind, Metric,
metrics_from_tree) into scope in one line. Anything outside the
prelude can still be reached by name — for example
use big_code_analysis::guess_language;.
The older
get_function_spaces(lang, bytes, path, pr)andmetrics_with_options(parser, path, options)entry points are still available but#[deprecated]— they derive the top-level name frompathvia lossy UTF-8 conversion. Use them only when you already have aParser<T>in hand from another seam.
3. What you got back
FuncSpace is a tree of spaces. The top-level node represents the
whole file; its spaces field holds nested function / class / impl
spaces. Every node carries the same CodeMetrics
struct, so you can read any metric at any level of granularity.
use big_code_analysis::{analyze, MetricsOptions, Source, SpaceKind, LANG}; fn main() { let source = "\ fn outer() { fn inner() {} } "; let space = analyze( Source::new(LANG::Rust, source.as_bytes()) .with_name(Some("snippet.rs".to_owned())), MetricsOptions::default(), ) .expect("Rust source should parse"); assert_eq!(space.kind, SpaceKind::Unit); assert_eq!(space.spaces.len(), 1); // `outer` assert_eq!(space.spaces[0].spaces.len(), 1); // `inner` }
For a deeper walk over FuncSpace, see
Walking FuncSpace results.
Picking a language
If you do not know the language up front, use guess_language —
it consults the path extension, an Emacs mode line in the buffer,
and the shebang in that order:
use std::path::PathBuf; use big_code_analysis::{analyze, guess_language, MetricsOptions, Source}; fn main() { let source = b"print('hi')\n"; let path = PathBuf::from("hello.py"); let (Some(lang), _name) = guess_language(source, &path) else { eprintln!("unrecognised language"); return; }; let _space = analyze( Source::new(lang, source).with_name(Some("hello.py".to_owned())), MetricsOptions::default(), ); }
guess_language returns (None, _) for unknown extensions; treat
that as "skip this file" rather than as a parse error.
What changes when
The recommended entry point is analyze(Source, MetricsOptions) and
returns Result<FuncSpace, MetricsError> (per #253 and #254).
The library-DX tracker collects the remaining shape changes —
naming, per-language features, and the parse seam.