singularity-code-analysis is a Rust library to analyze and extract information from source code written in many different programming languages. It is based on a parser generator tool and an incremental parsing library called Tree Sitter.
This crate is the Singularity-maintained continuation of Mozilla rust-code-analysis, with enhanced support for BEAM languages (Elixir, Erlang, Gleam) and additional code complexity metrics.
- Multi-language support: Rust, Python, JavaScript/TypeScript, Java, C/C++, Elixir, Erlang, Gleam, and more
- Comprehensive metrics: Cyclomatic complexity, Halstead metrics, Maintainability Index, Lines of Code
- BEAM language support: Enhanced parsing and analysis for Elixir, Erlang, and Gleam
- Tree-sitter integration: Fast, incremental parsing with Tree-sitter 0.25.10
- Command-line interface: Easy-to-use CLI for analyzing codebases
- Web API: REST API for web-based code analysis
- Production-ready: Comprehensive error handling, extensive test coverage, and CI/CD
Add this to your Cargo.toml:
[dependencies]
singularity-code-analysis = "0.1.0"use singularity_code_analysis::{get_function_spaces, LANG};
use std::path::Path;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Analyze a Rust file
let source_code = r#"
fn main() {
println!("Hello, world!");
}
fn calculate(x: i32, y: i32) -> i32 {
if x > 0 {
x + y
} else {
x - y
}
}
"#;
let path = Path::new("example.rs");
// Get function spaces with error handling
match get_function_spaces(&LANG::Rust, source_code.as_bytes().to_vec(), &path, None) {
Some(func_space) => {
println!("Found {} functions:", func_space.spaces.len());
for space in &func_space.spaces {
println!(" - {}: lines {}-{}",
space.name.as_ref().unwrap_or(&"unnamed".to_string()),
space.start_line,
space.end_line
);
}
// Access metrics
println!("Cyclomatic complexity: {}", func_space.metrics.cyclomatic.cyclomatic);
println!("Lines of code: {}", func_space.metrics.loc.sloc);
}
None => {
println!("No functions found in the code");
}
}
Ok(())
}| Language | Parsing & Function Detection | Metrics Coverage | Notes |
|---|---|---|---|
| Rust | ✅ Full | ✅ Full | |
| Python | ✅ Full | ✅ Full | |
| JavaScript | ✅ Full | ✅ Full | |
| TypeScript | ✅ Full | ✅ Full | Covers the LANG::Typescript parser. |
| TSX (TypeScript + JSX) | ✅ Full | ✅ Full | Covers the LANG::Tsx parser for mixed TS/JSX files. |
| Java | ✅ Full | ✅ Full | Weighted Methods per Class (WMC) implemented only for Java. |
| C/C++ | ✅ Full | ✅ Full | See the macro parsing note below for known limitations. |
| Kotlin | ✅ Full | LOC and exit counting metrics not yet implemented. Cognitive complexity, cyclomatic complexity, and Halstead metrics are fully supported. | |
| Go | ✅ Full | LOC and exit counting metrics not yet implemented. Cognitive complexity, cyclomatic complexity, and Halstead metrics are fully supported. | |
| C# | ✅ Full | LOC and exit counting metrics not yet implemented. Cognitive complexity, cyclomatic complexity, and Halstead metrics are fully supported. | |
| Elixir | ✅ Full | LOC and exit counting metrics not yet implemented. Cognitive complexity, cyclomatic complexity, and Halstead metrics are fully supported. | |
| Erlang | ✅ Full | LOC and exit counting metrics not yet implemented. Cognitive complexity, cyclomatic complexity, and Halstead metrics are fully supported. | |
| Gleam | ✅ Full | LOC and exit counting metrics not yet implemented. Cognitive complexity, cyclomatic complexity, and Halstead metrics are fully supported. | |
| Lua | ✅ Full | LOC and exit counting metrics not yet implemented. Cognitive complexity, cyclomatic complexity, and Halstead metrics are fully supported. |
Note
This library targets Tree-sitter 0.25.10 and favors the kind() string APIs for robust node type checks across grammar updates.
Language grammars are provided by their respective tree-sitter crates (e.g., tree-sitter-rust,
tree-sitter-elixir) and are automatically compiled when building the library. No separate
grammar files need to be shipped or maintained.
Important
Tree-sitter's C/C++ grammars still struggle with Mozilla-style macro expansions.
The three unit tests under c_langs_macros are expected to fail until the
upstream grammar exposes these constructs without parse errors. Function and
metrics analysis for typical C/C++ codebases works as expected; only heavily
macro-based signatures are affected.
The library computes various software metrics:
- Cyclomatic Complexity: Measures code complexity based on control flow
- Halstead Metrics: Volume, difficulty, effort, and time estimates
- Maintainability Index: Overall code maintainability score
- Lines of Code: Physical and logical LOC metrics
- Function Count: Number of functions and closures
- Cognitive Complexity: Measures human comprehension difficulty
- Nesting Depth: Maximum nesting level in functions
- ABC Metric: Assignments, Branches, Conditions complexity
Analyzes source code and returns function spaces with metrics.
Parameters:
lang: Language enum (e.g.,LANG::Rust)source: Source code as byte vectorpath: File path for contextpreproc: Optional preprocessor results
Returns: Function space data or None if no functions found
Runs custom analysis callbacks on source code.
Represents a function or code space with metrics.
pub struct FuncSpace {
pub name: Option<String>,
pub start_line: usize,
pub end_line: usize,
pub kind: SpaceKind,
pub spaces: Vec<FuncSpace>, // Nested functions
pub metrics: CodeMetrics,
}Contains all computed metrics for a code space.
pub struct CodeMetrics {
pub nargs: nargs::Stats,
pub nexits: exit::Stats,
pub cognitive: cognitive::Stats,
pub cyclomatic: cyclomatic::Stats,
pub halstead: halstead::Stats,
pub loc: loc::Stats,
pub nom: nom::Stats,
// ... additional metrics
}The library uses Option and Result types for error handling:
- Functions return
Option<T>when "no data" is a valid result - Parsing errors are handled gracefully
- Invalid input returns
Nonerather than panicking
- Fast parsing: Tree-sitter provides incremental parsing
- Memory efficient: Minimal allocations for large codebases
- Concurrent processing: Support for parallel analysis
To build the singularity-code-analysis library:
cargo build --releaseTo build with CLI:
cargo build --release --bin singularity-code-analysis-cliRun the comprehensive test suite:
cargo testRun specific language tests:
cargo test --lib -- cognitive # Test cognitive complexity
cargo test --lib -- halstead # Test Halstead metricsThis fork includes special enhancements for BEAM languages:
- Elixir: Improved macro analysis and module structure detection
- Erlang: Enhanced function clause and pattern matching analysis
- Gleam: Support for modern functional programming constructs
Contributions are welcome! Please see CONTRIBUTING.md for detailed guidelines.
Quick start:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
# Clone the repository
git clone https://github.com/Singularity-ng/singularity-analysis.git
cd singularity-analysis
# Run tests
cargo test --lib
# Check code quality
cargo clippy --lib
cargo fmt --check- Quick Start Guide: Get started quickly
- Quick Reference: API quick reference
- BEAM Support: Elixir, Erlang, Gleam support details
- Known Issues: Current test status and known limitations
- Contributing Guide: How to contribute
- Security Policy: Security reporting and policies
This project is dual-licensed under MIT OR Apache-2.0 - see the LICENSE file for details.
singularity-code-analysis started as a fork of Mozilla rust-code-analysis. Special thanks to the Mozilla team for their excellent work on code analysis tools.