Expand description
§Arborist
Multi-language code complexity metrics powered by tree-sitter.
Arborist computes cognitive complexity (SonarSource), cyclomatic complexity (McCabe), and source lines of code (SLOC) for functions and methods across 12 programming languages – all from a single, embeddable Rust library.
§Supported Languages
| Language | Feature flag | Extensions | Default |
|---|---|---|---|
| Rust | rust | .rs | Yes |
| Python | python | .py, .pyi | Yes |
| JavaScript | javascript | .js, .jsx, .mjs, .cjs | Yes |
| TypeScript | typescript | .ts, .tsx, .mts, .cts | Yes |
| Java | java | .java | Yes |
| Go | go | .go | Yes |
| C# | csharp | .cs | Opt-in |
| C++ | cpp | .cpp, .cc, .cxx, .hpp, .hxx, .hh | Opt-in |
| C | c | .c, .h | Opt-in |
| PHP | php | .php | Opt-in |
| Kotlin | kotlin | .kt, .kts | Opt-in |
| Swift | swift | .swift | Opt-in |
§Feature Flags
Arborist uses Cargo feature flags to control which tree-sitter grammars are compiled. Each language is an independent, optional feature that pulls in its corresponding tree-sitter grammar crate.
To enable all 12 languages, use features = ["all"].
§Tiers
- Tier 1 (default): Rust, Python, JavaScript, TypeScript, Java, Go –
the most mature tree-sitter grammars. Enabled automatically unless you
set
default-features = false. - Tier 2 (opt-in): C#, C++, C, PHP, Kotlin, Swift – require enabling
their feature flag explicitly or using the
allcomposite feature.
§Individual features
| Feature flag | Language | Tier | tree-sitter crate |
|---|---|---|---|
rust | Rust | 1 | tree-sitter-rust |
python | Python | 1 | tree-sitter-python |
javascript | JavaScript | 1 | tree-sitter-javascript |
typescript | TypeScript | 1 | tree-sitter-typescript |
java | Java | 1 | tree-sitter-java |
go | Go | 1 | tree-sitter-go |
csharp | C# | 2 | tree-sitter-c-sharp |
cpp | C++ | 2 | tree-sitter-cpp |
c | C | 2 | tree-sitter-c |
php | PHP | 2 | tree-sitter-php |
kotlin | Kotlin | 2 | tree-sitter-kotlin-ng |
swift | Swift | 2 | tree-sitter-swift |
§Composite features
| Feature | Expands to |
|---|---|
default | rust, python, javascript, typescript, java, go |
all | All 12 languages (default + csharp, cpp, c, php, kotlin, swift) |
Compile-time note: Each grammar adds compile time and binary size. Use
default-features = falsewith only the languages you need for minimal builds, orallwhen you need broad language coverage.
§Installation
Add to your Cargo.toml:
# Default features (Tier 1): Rust, Python, JavaScript, TypeScript, Java, Go
[dependencies]
arborist-metrics = "0.1"Select specific languages to reduce compile time:
[dependencies]
arborist-metrics = { version = "0.1", default-features = false, features = ["rust", "python"] }Enable all 12 languages:
[dependencies]
arborist-metrics = { version = "0.1", features = ["all"] }§Quick Start
§Analyze a file
use arborist::{analyze_file, FileReport};
fn main() -> Result<(), arborist::ArboristError> {
let report: FileReport = analyze_file("src/main.rs")?;
println!("File: {} ({:?})", report.path, report.language);
println!("Total cognitive: {}, SLOC: {}", report.file_cognitive, report.file_sloc);
for func in &report.functions {
println!(" {} (lines {}-{}): cognitive={}, cyclomatic={}, sloc={}",
func.name, func.start_line, func.end_line,
func.cognitive, func.cyclomatic, func.sloc);
}
Ok(())
}§Analyze source code from memory
use arborist::{analyze_source, Language};
let source = r#"
def hello(name):
if name:
print(f"Hello, {name}!")
else:
print("Hello, world!")
"#;
let report = analyze_source(source, Language::Python)?;
// report.functions[0].cognitive == 2 (if + else)§Configure thresholds
use arborist::{analyze_file_with_config, AnalysisConfig};
let config = AnalysisConfig {
cognitive_threshold: Some(8),
..Default::default()
};
let report = analyze_file_with_config("src/complex.rs", &config)?;
for func in &report.functions {
if func.exceeds_threshold == Some(true) {
eprintln!("WARNING: {} has cognitive complexity {} (threshold: 8)",
func.name, func.cognitive);
}
}§Serialize to JSON
let report = arborist::analyze_file("src/main.rs")?;
let json = serde_json::to_string_pretty(&report)?;
println!("{}", json);§Metrics
§Cognitive Complexity
Follows the SonarSource specification by G. Ann Campbell. Measures how difficult code is to understand:
- +1 for each control flow break (
if,for,while,match,catch, etc.) - Nesting penalty: nested control flow adds the current nesting depth
- Boolean operator sequences: one increment per operator switch (
&&to||) - Flat
else if: does not increase nesting - +1 for recursive calls and lambda/closure nesting
§Cyclomatic Complexity
Standard McCabe cyclomatic complexity (base 1 + decision points). Measures the number of linearly independent paths through a function.
§SLOC
Physical source lines of code, excluding blank lines and comment-only lines.
§Contributing
- Fork the repository
- Create a feature branch
- Follow TDD: write fixtures and failing tests before implementation
- Run
cargo clippy -- -D warningsandcargo test --all-features - Submit a pull request
§Adding a new language
- Create
src/languages/<lang>.rsimplementing theLanguageProfiletrait - Add the grammar crate as an optional dependency in
Cargo.toml - Add a feature flag and wire up detection in
src/languages/mod.rs - Create 6 test fixtures in
tests/fixtures/<lang>/ - Write integration tests
§Built with AI · Powered by StrayMark
Arborist is an experiment in disciplined AI-assisted development. The implementation — tree-sitter integration, the 177-test suite, all 12 language profiles — was authored largely by AI agents under human direction.
To make that velocity sustainable, we use StrayMark:
a CLI for cognitive discipline in AI-assisted engineering. It turned every
architectural choice into an AIDEC record, every implementation block into
an AILOG, and the test plan into a TES — all under .straymark/, append-only
and audit-ready. The governance artifacts emerged alongside the code,
not as homework after.
StrayMark is built by Strange Days Tech — the same team behind Arborist. It is the tool we made to solve our own problem.
§License
Licensed under either of:
at your option.
§Copyright
Arborist is © 2026 Strange Days Tech S.A.S. de C.V. — original author and intellectual-property holder of the source code.
The library is released under the dual MIT / Apache-2.0 license above; this notice records authorship and does not modify those license terms. Each source file carries an SPDX header reflecting the same.
Built by Strange Days Tech — México.
Re-exports§
pub use error::ArboristError;pub use languages::LanguageProfile;pub use types::AnalysisConfig;pub use types::FileReport;pub use types::FunctionMetrics;pub use types::Language;
Modules§
Functions§
- analyze_
file - Analyze a source file, auto-detecting language from its extension.
- analyze_
file_ with_ config - Analyze a source file with custom configuration.
- analyze_
source - Analyze source code provided as a string, with explicit language.
- analyze_
source_ with_ config - Analyze source code with explicit language and custom configuration.