Full support for BEAM languages (Elixir, Erlang, Gleam) has been implemented in singularity-code-analysis with comprehensive complexity metrics.
2025-01-14
Features:
- Full AST parsing via tree-sitter
- Comment detection
- Function detection (def, defp)
- Anonymous function (closure) detection
- Function call detection
- String literal detection (String, Charlist, QuotedContent)
- Primitive type detection (Atom, Integer, Float, Boolean, Nil)
- All complexity metrics: Cyclomatic, Halstead, MI, ABC, Cognitive, etc.
Node Types: 66 distinct node types including Call, DoBlock, AnonymousFunction, StabClause, Map, Tuple, List, etc.
Features:
- Full AST parsing via tree-sitter
- Comment detection
- Function declaration detection (FunDecl, FunctionClause)
- Anonymous function detection (fun ... end)
- Function call detection
- Character literal detection (Erlang strings are lists)
- Primitive type detection (Atom, Integer, Float)
- Guard clause support
- Pattern matching support (case, receive, try/catch)
- All complexity metrics
Node Types: 101 distinct node types including FunDecl, CaseExpr, ReceiveExpr, TryExpr, Guard, MapExpr, Record, etc.
Features:
- Full AST parsing via tree-sitter
- Multiple comment types (ModuleComment, StatementComment, Comment)
- Function detection (pub fn, fn)
- Anonymous function detection
- Function call detection
- String literal detection
- Primitive type detection (Integer, Float)
- Type system support (TypeDefinition, TypeAlias)
- Pattern matching support (case expressions)
- All complexity metrics
Node Types: 129 distinct node types including Function, Case, Let, Use, Assert, Record, Tuple, List, BitString, etc.
All BEAM languages support the full suite of code metrics:
- ABC - Assignment, Branch, Condition complexity
- Cognitive - Cognitive complexity metric
- Cyclomatic - Cyclomatic complexity (McCabe)
- Exit - Exit point counting
- Halstead - Halstead complexity measures
- LOC - Lines of Code (SLOC, CLOC, PLOC)
- MI - Maintainability Index
- NArgs - Number of Arguments
- Nom - Number of Methods
- Npa - Number of Public Attributes
- Npm - Number of Public Methods
- WMC - Weighted Methods per Class
- Elixir:
.ex,.exs - Erlang:
.erl,.hrl - Gleam:
.gleam
Each language has a complete enum with node types extracted from the actual tree-sitter grammar:
src/languages/language_elixir.rs- 66 node typessrc/languages/language_erlang.rs- 101 node typessrc/languages/language_gleam.rs- 129 node types
Each language implements:
- Checker - Code structure analysis (comments, functions, closures, calls, strings, primitives)
- Alterator - AST node transformation for network serialization
- Getter - Name and identifier extraction
- All Metric Traits - ABC, Cognitive, Cyclomatic, Exit, Halstead, LOC, MI, NArgs, Nom, Npa, Npm, WMC
Languages are registered in src/langs.rs:
(Elixir, "The `Elixir` language", "elixir", ElixirCode, ElixirParser, tree_sitter_elixir, [ex, exs], ["elixir"]),
(Erlang, "The `Erlang` language", "erlang", ErlangCode, ErlangParser, tree_sitter_erlang, [erl, hrl], ["erlang"]),
(Gleam, "The `Gleam` language", "gleam", GleamCode, GleamParser, tree_sitter_gleam, [gleam], ["gleam"])Test examples provided in examples/ directory:
inspect_elixir.rs- Demonstrates Elixir AST parsinginspect_erlang.rs- Demonstrates Erlang AST parsinginspect_gleam.rs- Demonstrates Gleam AST parsing
Run with:
cargo run --example inspect_elixir
cargo run --example inspect_erlang
cargo run --example inspect_gleam/tmp/test_elixir.ex- Elixir test code (defmodule, def, defp, if, case)/tmp/test_erlang.erl- Erlang test code (factorial, guards, case)/tmp/test_gleam.gleam- Gleam test code (pub fn, case, pattern matching)
✅ All builds pass cleanly
- Debug build: ✅ Success
- Release build: ✅ Success
- No errors, only minor unused variable warnings
tree-sitter-elixir = "0.3.4" # Latest stable
tree-sitter-erlang = "0.15.0" # Latest stable
tree-sitter-gleam = "1.0.0" # Latest stable- Functions detected via
Callnodes withdef/defpidentifiers - Closures are
AnonymousFunctionnodes - String types include
String,Charlist,QuotedContent - Primitives:
Atom,Integer,Float,Boolean,Nil
- Functions are
FunDeclandFunctionClausenodes - Closures are
AnonymousFunnodes - Strings are character lists (no dedicated string type)
- Primitives:
Atom,Integer,Float - Rich support for OTP patterns: guards, pattern matching, receive blocks
- Functions are
Functionnodes with optionalVisibilityModifier(pub) - Closures are
AnonymousFunctionnodes - Strings are
StringwithQuotedContent - Primitives:
Integer,Float - Strong type system support with
TypeDefinitionandTypeAlias
Potential improvements:
- Enhanced Function Detection - More precise def/defp detection in Elixir
- Module Boundary Detection - Track defmodule boundaries for better metrics
- OTP Pattern Recognition - Detect GenServer, Supervisor patterns in Erlang/Elixir
- Macro Expansion - Handle Elixir macros for more accurate metrics
- Type-aware Metrics - Leverage Gleam's type system for additional insights
BEAM languages now have the same level of support as:
- Rust
- Python
- JavaScript/TypeScript/TSX
- C/C++
- Java
Making singularity-code-analysis one of the most comprehensive BEAM-aware complexity analyzers available.
Implementation based on:
- Singularity's singularity-code-analysis framework
- tree-sitter-elixir by @elixir-lang
- tree-sitter-erlang by @WhatsApp
- tree-sitter-gleam by @gleam-lang
MIT OR Apache-2.0 (same as singularity-code-analysis)