Zig 0.16 · v0.0.2 preview
Zig-native architecture metrics
Metrics analyze Zig declarations, source structure, and dependency coupling. They intentionally omit object-oriented measures that would turn absent Zig concepts into misleading zeros.
A compiled example
const std = @import("std");
const archunit = @import("archunit");
test "source files stay small" {
var project = try archunit.metrics(std.testing.allocator, .{});
defer project.deinit();
var source = try project.inPath(&.{.{ .glob = "src/**/*.zig" }});
defer source.deinit();
var counts = try source.count();
defer counts.deinit();
var functions = try counts.functions();
defer functions.deinit();
var rule = try functions.shouldBeBelowOrEqual(2);
defer rule.deinit(std.testing.allocator);
try archunit.expectPasses(&rule, .init(.init(std.testing.allocator, std.testing.io)));
}
Compiled source: test/readme/metrics.zig
Choose files, declarations, or containers
Begin with a file scope and its normal path selectors. Project that scope to named declarations or containers when the metric should operate at Zig declaration identity. Name filters compare both simple and qualified names consistently.
Structural counts
Count declarations, functions, tests, constants, variables, fields, structs, unions, enums, opaque types, error sets, anonymous containers, imports, statements, tokens, source lines, and non-blank lines. A measurement returns owned subject/value pairs; a threshold rule returns structured metric violations.
Dependency coupling
| Metric | Meaning |
|---|---|
| Afferent coupling | Selected incoming dependency count. |
| Efferent coupling | Selected outgoing dependency count. |
| Instability | Ce / (Ca + Ce) over the selected projection. |
| Coupling factor | Observed internal relationships relative to possible relationships. |
Thresholds and predicates
Integral counts stay integers through comparison. Ratios stay finite floating-point values. The API does not implicitly mix them because conversion can change an equality boundary. Built-in threshold rules support below, above, equal, and inclusive variants; shouldSatisfy accepts a borrowed callback and returns a distinct predicate violation when it rejects a subject.
Custom metrics
A custom metric receives borrowed structural facts, or full dependency facts for a dependency projection, plus an optional caller context. It returns one tagged scalar per selected subject. Custom definitions own their name and description so diagnostic and report lifetimes do not depend on callback storage.
Owned data and offline HTML
Count, dependency, and custom builders gather MetricsReportData before rendering. Sections and entries are sorted without mutating the caller's data. The HTML renderer escapes titles and labels, neutralizes embedded-style terminators in custom CSS, uses no scripts or remote assets, and supports deterministic output without a timestamp.