Apache License 2.0

项目介绍

StrangeDaysTech/arborist-metrics 是一个托管在 GitHub 上的开源项目,主要使用 Rust 编写,采用 Apache License 2.0 许可证,目前获得 15 个 Star、2 次 Fork。

仓库全名
StrangeDaysTech/arborist-metrics
开源许可证
Apache License 2.0
Star 数
15
Fork 数
2

README 摘要

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 |…

完整内容见 GitHub 原始 README 或本页 。

常见问题

arborist-metrics 用什么语言开发?

主要使用 Rust 编写,采用 Apache License 2.0 许可证,目前有 15 个 Star。

arborist-metrics 可以免费商用吗?

仓库采用 Apache License 2.0 许可证,可免费使用与修改,商业使用请遵守许可证条款(例如保留版权声明与许可声明)。

如何获取 arborist-metrics 的源码?

可以直接克隆仓库:git clone https://github.com/StrangeDaysTech/arborist-metrics.git,默认分支为 main;安装与运行步骤见仓库 README。

arborist-metrics 最近还在维护吗?

仓库最近一次更新为 5月20日,当前没有未关闭的 Issue;Star 数为 15,可作为社区活跃度的参考。

关于

Multi-language code complexity metrics (cognitive, cyclomatic, SLOC) powered by tree-sitter

描述取自 GitHub 官方 API,中文内容由 GitRead 中文社区 编辑团队整理。

简要分析

热度分
19
价值分
9
活跃状态
活跃

语言占比

PowerShell
Rust
Shell

Release

贡献者

README

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 all composite 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 = false with only the languages you need for minimal builds, or all when 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)
# Ok::<(), arborist::ArboristError>(())

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);
    }
}
# Ok::<(), arborist::ArboristError>(())

Serialize to JSON

let report = arborist::analyze_file("src/main.rs")?;
let json = serde_json::to_string_pretty(&report)?;
println!("{}", json);
# Ok::<(), Box<dyn std::error::Error>>(())

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

  1. Fork the repository
  2. Create a feature branch
  3. Follow TDD: write fixtures and failing tests before implementation
  4. Run cargo clippy -- -D warnings and cargo test --all-features
  5. Submit a pull request

Adding a new language

  1. Create src/languages/<lang>.rs implementing the LanguageProfile trait
  2. Add the grammar crate as an optional dependency in Cargo.toml
  3. Add a feature flag and wire up detection in src/languages/mod.rs
  4. Create 6 test fixtures in tests/fixtures/<lang>/
  5. 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 built 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.


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.

评论

暂无评论