Expand description
§ArchUnitRust
Architecture tests for Cargo projects, expressed as ordinary Rust tests. ArchUnitRust is part of ArchUnitEverything — one architecture-testing library per language.
Status: usable from Git and under active development. The crate is not published on crates.io yet; the current package version is
0.0.1and requires Rust 1.85 or newer.
§Install
ArchUnit rules belong in the project that they check, so add the crate as a development dependency:
cargo add --dev --git https://github.com/LukasNiessen/ArchUnitRust archunitThe equivalent Cargo.toml entry is:
[dev-dependencies]
archunit = { git = "https://github.com/LukasNiessen/ArchUnitRust" }Cargo records the resolved Git commit in Cargo.lock. Commit that lockfile when the consuming
project normally tracks it. After the first crates.io release, the Git dependency can be replaced
by a versioned registry dependency.
§File rules
§First rule: a file boundary
Create tests/architecture.rs, adapt the two project-relative paths, and add this ten-line test:
use archunit::{assert_passes, project_files};
#[test]
fn api_does_not_reach_database() {
let rule = project_files()
.in_path("src/api/**")
.should_not()
.depend_on_files()
.in_path("src/database/**");
assert_passes!(rule);
}Run it with cargo test --test architecture. project_files() discovers the containing Cargo
package or workspace, analyzes production targets, and returns a lazy rule value. assert_passes!
executes the rule and reports every violation with its dependency evidence. No test-framework
adapter or global initialization is required.
§Fluent API grammar
Check rules read from left to right:
entry point -> subject selectors -> mood -> condition -> optional condition selectors -> executeFor file rules, each stage has a small, fixed vocabulary:
| Stage | API |
|---|---|
| Entry point | project_files() or project_files_in(path) |
| Subject selectors | with_name, in_folder, in_path, in_file |
| Mood | should() or should_not() |
| Conditions | have_no_cycles, have_name, be_in_folder, be_in_path, depend_on_files, depend_on_external_modules, adhere_to |
| Execute | assert_passes!(rule), rule.check(), or rule.check_with(&options) |
Chained subject selectors use AND semantics. Target selectors after depend_on_files() use OR
semantics. A positive dependency condition is an allowlist for every outgoing dependency; a
negated dependency condition is a denylist. Plain strings are case-sensitive, complete-candidate
globs: * stays within one path segment, while ** crosses separators. Builders consume and
return values, so clone a partial builder when several rules share a scope.
Every check is strict about stale selectors. A scope that selects no files returns an
EmptyTestViolation instead of silently passing. Make an intentionally optional scope explicit:
use archunit::{CheckOptions, assert_passes, project_files};
let optional_rule = project_files()
.in_folder("generated/**")
.should()
.have_no_cycles();
let options = CheckOptions::new().with_allow_empty_tests(true);
assert_passes!(optional_rule, options);§More file conditions
Naming, placement, internal dependencies, external Cargo crates, and custom predicates all use the same grammar:
use archunit::{Checkable, FileInfo, project_files};
let services = project_files()
.in_folder("src/services")
.should()
.have_name("*_service.rs");
let approved_crates = project_files()
.should()
.depend_on_external_modules()
.matching("std")
.matching("serde");
let manageable_files = project_files().in_path("src/**").should().adhere_to(
|file: &FileInfo| file.non_blank_line_count <= 200,
"contain at most 200 non-blank lines",
);
let _: [&dyn Checkable; 3] = [&services, &approved_crates, &manageable_files];FileInfo exposes the normalized workspace-relative path, filename without extension, extension,
containing directory, source text, and non-blank line count. Stored predicates are
Send + Sync + 'static; captured configuration therefore needs owned, thread-safe values.
§Feature guide
The public API is re-exported from the archunit crate root. Its implemented feature areas each
have a source-checked example below:
| Feature area | Start with | Example |
|---|---|---|
| File rules | project_files() | File rules |
| Named layers | project_layers() | Named layer policies |
| Captured slices and PlantUML | project_slices() | Slice dependencies |
| Rust-native metrics | metrics() | Rust-native metrics |
| Dependency graph reports | project_graph() | Dependency graph snapshots |
| Test integration and structured results | assert_passes! / Checkable | Testing and framework-neutral results |
All Rust snippets in this README are included in the crate documentation and compiled as doctests. The sections after this guide are the detailed reference for the implemented surface.
§What is not implemented yet
- crates.io publication is tracked by #44, so installation currently uses the Git repository;
- extraction is syntax-based: it does not expand macros or inspect build-script-generated source,
evaluates
cfgbranches as a conservative union, and exposes files rather than Rust items as dependency nodes.
These are explicit boundaries, not implied compatibility claims. See the porting plan for the complete v0.1 scope.
§Pattern exclusions
Every pattern selector still accepts a plain string. Wrap the same string with pattern when that
one selector needs exclusions:
use archunit::{assert_passes, pattern, project_files};
let rule = project_files()
.in_path(
pattern("src/**")
.except_in_folder("src/generated/**")
.except_with_name("*_generated.rs"),
)
.should_not()
.depend_on_files()
.in_path(pattern("src/database/**").except("src/database/public.rs"));
assert_passes!(rule);except and except_all inherit the parent selector target. Target-explicit alternatives are
except_in_path, except_in_folder, except_with_name, and
except_for_types_matching. Exclusions on one selector use OR semantics—matching any one removes
the candidate from that parent match—while chained parent selectors retain their normal AND
semantics. The same contract covers file scopes and predicates, dependency objects, layer
definitions, graph queries, metric file/type scopes, and slice capture projections.
Exclusions use the same glob/regex syntax, exact matching, separator normalization, and case policy
as their parent factory. defined_by slice exclusions are globs; defined_by_regex exclusions are
Rust regular expressions. An invalid parent or exclusion remains a user configuration error and is
reported before Cargo project discovery.
§Rust-native metrics
Metrics expose immutable measurements rather than architecture verdicts. Count and LCOM families use Rust vocabulary; component-distance metrics combine file syntax with the complete internal dependency graph:
use archunit::{ArchUnitError, metrics};
fn inspect_metrics() -> Result<(), ArchUnitError> {
let measurements = metrics()
.in_folder("src/**")
.distance()
.instability()
.measure()?;
for measurement in measurements {
println!("{}: {:.3}", measurement.identifier(), measurement.value());
}
Ok(())
}In v0.1 one distance component is one analyzed Rust source file. Abstractness is the ratio of traits
to all declared types; instability uses distinct incoming and outgoing internal file dependencies.
The remaining terminals are distance_from_main_sequence(), coupling_factor(), and
normalized_distance(). File and type selectors choose reported components but do not shrink the
coupling universe.
The two discouraged regions are executable architecture rules with typed violations and the shared strict empty-selection guard:
use archunit::{assert_passes, metrics};
let rule = metrics()
.in_folder("src/**")
.distance()
.not_in_zone_of_pain();
assert_passes!(rule);Project-specific metrics use generic callbacks over the full immutable Rust type model. The same selection can be measured repeatedly or consumed into a typed predicate rule:
use archunit::{TypeInfo, assert_passes, metrics};
let member_count = metrics().custom_metric(
"member_count",
"methods plus fields must remain manageable",
|info: &TypeInfo| (info.methods().len() + info.fields().len()) as f64,
);
let rule = member_count.should_satisfy(|value, _info| value <= 20.0);
assert_passes!(rule);The calculation and predicate each run once per selected type on every execution. Panics from user callbacks propagate normally with their Rust backtrace; they are never converted into architecture violations. Non-finite custom values are preserved so a predicate can choose its own policy.
Every metric selection supports exactly five numeric threshold verbs plus should_satisfy:
use archunit::{MetricSubject, assert_passes, metrics};
let threshold = metrics()
.for_types_matching("*Service")
.count()
.method_count()
.should_be_below_or_equal(20.0);
assert_passes!(threshold);
let predicate = metrics()
.distance()
.instability()
.should_satisfy(|value, subject: &MetricSubject| {
subject.as_distance().is_some() && value <= 0.8
});
assert_passes!(predicate);The other threshold names are should_be_below, should_be_above, should_be, and
should_be_above_or_equal; there are intentionally no synonyms. Thresholds must be finite and
should_be uses exact f64 equality. Use should_satisfy when a project needs an explicit
floating-point tolerance. Built-in predicates receive MetricSubject; custom-metric predicates keep
the more precise TypeInfo argument.
Each built-in metric family can also be exported as one self-contained HTML document. The exporter
adds .html when needed, creates missing parent directories, and returns the final path:
use archunit::{ArchUnitError, MetricsExportOptions, metrics};
fn export_metrics() -> Result<(), ArchUnitError> {
let options = MetricsExportOptions::new()
.with_title("Service cohesion")
.with_timestamp(false);
metrics()
.for_types_matching("*Service")
.lcom()
.export_as_html_with("target/architecture/cohesion", &options)?;
Ok(())
}count(), lcom(), and distance() export every metric in their family from one project
snapshot. MetricsExporter also renders or writes a MetricsReportData map directly. Reports have
no scripts or network dependencies; names, values, and titles are HTML-escaped. Timestamps are UTC
and can be disabled for byte-stable build artifacts. Custom CSS replaces the built-in stylesheet.
§Per-check logging
Checks are quiet by default. Logging is enabled only by putting a LoggingOptions value into the
CheckOptions passed to that check; the crate never reads a global logger or an environment
variable:
use archunit::{
ArchUnitError, CheckOptions, Checkable, LogFileMode, LogLevel, LoggingOptions, project_files,
};
fn check_boundaries() -> Result<(), ArchUnitError> {
let logging = LoggingOptions::new()
.with_level(LogLevel::Debug)
.with_console_output(false)
.with_file_output("target/architecture-logs")
.with_file_mode(LogFileMode::Overwrite);
let log_path = logging
.file_path()
.expect("file output exposes its artifact path")
.to_path_buf();
let options = CheckOptions::new().with_logging(logging);
let rule = project_files()
.in_folder("src/api/**")
.should_not()
.depend_on_files()
.in_folder("src/database/**");
let violations = rule.check_with(&options)?;
println!("CI log: {}", log_path.display());
assert!(violations.is_empty());
Ok(())
}LoggingOptions::new() logs at Info level to the console. Debug adds progress and metric
records; violations and failed verdicts use Warn, while execution errors use Error. The fixed
event vocabulary is start check, end check, log progress, log violation, and log metric.
Ordinary debug, info, warn, and error records are also available through CheckLogger for
custom Checkable implementations.
File output creates missing directories and chooses a collision-resistant, UTC-timestamped .log
filename. file_path() exposes that path before execution so CI can archive it. Append preserves
an existing file; Overwrite truncates it once before the first record. Clones of one configuration
share only the lock and initialization state for that explicit file, making concurrent checks safe
without introducing ambient process state. A logger with neither console nor file output is a user
configuration error detected before project discovery. Filesystem and console failures are
technical check errors rather than silently lost diagnostics.
§Named layer policies
Layers turn a set of file selectors into a compact dependency policy. The target list is a borrowed slice in Rust; an empty allowlist seals a layer against every cross-layer dependency:
use archunit::{assert_passes, project_layers};
#[test]
fn dependencies_follow_the_declared_layers() {
let rule = project_layers()
.layer("api")
.defined_by("src/api/**")
.layer("application")
.defined_by_folder("src/application")
.layer("database")
.defined_by("src/database/**")
.where_layer("api")
.may_only_depend_on_layers(&["application"])
.where_layer("application")
.may_only_depend_on_layers(&["database"])
.where_layer("database")
.may_only_depend_on_layers(&[]);
assert_passes!(rule);
}layers() aliases project_layers(); explicit project entry points are layers_in(path) and
project_layers_in(path). Repeating layer(name) adds another OR selector to that layer. If layer
definitions overlap, the first declared layer wins. Dependencies within one layer and dependencies
with either endpoint outside every declared layer are ignored.
may_not_depend_on_layers(&[...]) adds a blocklist. Blocklists are evaluated before allowlists, so
one file edge produces at most one layer violation even when both policies reject it. Source layers
used by a policy receive the same strict empty-selection guard as file rules.
§Slice dependencies
Slices derive architectural component names from project-relative Rust file paths. A portable slice
pattern must contain exactly one (**) capture; that capture names the slice:
use archunit::{ArchUnitError, Checkable, project_slices};
fn check_slices() -> Result<(), ArchUnitError> {
let rule = project_slices()
.defined_by("src/(**)/")
.should_not()
.contain_dependency("api", "database");
let violations = rule.check()?;
assert!(violations.iter().all(|violation| {
violation
.as_slice_dependency()
.is_none_or(|data| data.source_slice == "api")
}));
Ok(())
}defined_by_regex(expression) uses the first capture in a Rust regular expression. Projection
definitions are reusable directly through slice_by_pattern, slice_by_regex,
slice_by_file_suffix, and slice_identity (also SliceProjection::identity). Pass a prepared
projection to with_projection:
use std::error::Error;
use archunit::{Checkable, project_slices, slice_by_file_suffix};
fn check_suffix_slices() -> Result<(), Box<dyn Error>> {
let projection = slice_by_file_suffix([
("_controller", "controllers"),
("_service", "services"),
])?;
let rule = project_slices()
.with_projection(projection)
.should_not()
.contain_dependency("controllers", "services");
let _violations = rule.check()?;
Ok(())
}Suffix projections remove the Rust filename extension and choose the longest matching suffix.
Internal self-edges and dependencies inside one slice are omitted. External Cargo dependencies keep
their crate name as the target slice, so a rule can explicitly forbid ("api", "tokio"). A slice
definition that selects no internal files produces the universal empty-test violation unless
CheckOptions::with_allow_empty_tests(true) is set.
PlantUML component diagrams can act as a dependency allowlist. The supported subset is intentionally
line-based: component [Name], [A] -> [B], [A] --> [B], apostrophe or // comments, and
@startuml/@enduml directives. Other styling lines are ignored.
use archunit::{ArchUnitError, Checkable, project_slices};
fn check_diagram() -> Result<(), ArchUnitError> {
let diagram = r#"
@startuml
component [api]
component [application]
[api] --> [application]
@enduml
"#;
let rule = project_slices()
.defined_by("src/(**)/")
.should()
.ignoring_external_slices()
.ignoring_orphan_slices()
.adhere_to_diagram(diagram);
let _violations = rule.check()?;
Ok(())
}Strict adherence reports every actual projected dependency not drawn in the diagram.
ignoring_external_slices() omits Cargo-module targets;
ignoring_orphan_slices() omits dependencies whose source or target component is undeclared.
adhere_to_diagram_in_file(path) reads UTF-8 only when the rule is checked.
The reverse path renders the actual slice graph, including isolated selected slices, in stable sorted order:
use archunit::{ArchUnitError, project_slices};
fn export_actual_diagram() -> Result<(), ArchUnitError> {
let slices = project_slices().defined_by("src/(**)/");
let text = slices.to_plantuml()?;
slices.export_as_plantuml("target/architecture/actual.puml")?;
assert!(text.starts_with("@startuml"));
Ok(())
}Use to_plantuml_with and export_as_plantuml_with for explicit CheckOptions. The lower-level
PlantUmlParser, PlantUmlDiagram, PlantUmlDependency, and PlantUmlRenderer APIs work entirely
on in-memory values.
§Dependency graph snapshots
Graph reports first build one renderer-neutral snapshot. Every query modifier is immutable and lazy;
only snapshot() or summary() locates and extracts the Cargo project:
use archunit::{ArchUnitError, CheckOptions, project_graph};
fn architecture_snapshot() -> Result<(), ArchUnitError> {
let snapshot = project_graph()
.include_external_dependencies()
.focus_on("src/**", 1)
.reachable_from("src/api/**")
.collapse_to_folder_depth(2)
.titled("Application Dependencies")
.with_check_options(CheckOptions::new().with_clear_cache(true))
.snapshot()?;
println!("{} nodes", snapshot.summary.node_count);
Ok(())
}dependency_graph() is an alias; project_graph_in(path) and dependency_graph_in(path) start at
an explicit directory or manifest. Queries include undirected focus_on(pattern, depth), transitive
outgoing reachable_from(pattern), and transitive incoming dependents_of(pattern). When several
are present, their selected nodes are combined as a union and the snapshot contains the induced
subgraph.
External dependencies and self dependencies are excluded by default. Collapse with
collapse_to_folder_depth(depth) or use a Rust regular expression whose first capture becomes the
label with collapse_by_pattern(expression). The explicit replacement form is
collapse_by_pattern_with_replacement(expression, replacement) and uses Rust regex syntax such as
$1 or ${component}.
The snapshot owns stable sorted node IDs, aggregated edges, Rust import-kind unions, a title, and
summary counts. raw_edge_count counts selected merged file-to-file edges before collapsing;
edge_count counts the final aggregated edges. This snapshot is the single input contract for every
output format.
§Dependency graph renderers
The graph builder renders DOT, Mermaid, D2, CSV, JSON, and self-contained HTML. Each format has a
to_*() string terminal and an export_as_*() UTF-8 file terminal. Export creates missing parent
directories; the chosen method determines the format rather than the file extension.
use archunit::{ArchUnitError, GraphRenderer, project_graph};
fn export_architecture() -> Result<(), ArchUnitError> {
let report = project_graph()
.collapse_to_folder_depth(2)
.titled("Application Dependencies");
let mermaid = report.to_mermaid()?;
println!("{mermaid}");
report.export_as_html("target/architecture/dependencies.html")?;
// Reuse one extraction explicitly when several formats are needed.
let snapshot = report.snapshot()?;
let dot = GraphRenderer::to_dot(&snapshot);
let json = GraphRenderer::to_json(&snapshot);
assert!(!dot.is_empty() && !json.is_empty());
Ok(())
}The six corresponding methods are to_dot, to_mermaid, to_d2, to_csv, to_json, and
to_html, plus export_as_dot, export_as_mermaid, export_as_d2, export_as_csv,
export_as_json, and export_as_html. GraphRenderer::render and GraphRenderer::export provide
typed dispatch through GraphReportFormat.
DOT, Mermaid, and D2 retain aggregated edge counts and visually distinguish external dependencies. CSV contains one row per aggregated edge. JSON contains the complete snapshot contract. HTML embeds its CSS and portable source views directly in the document: it has no scripts, remote assets, or network dependency.
§Testing and framework-neutral results
assert_passes!(rule) and assert_passes!(rule, check_options) are the native integration for
ordinary #[test] functions. They preserve both formatted architecture violations and classified
check errors in the assertion message. Rust’s built-in harness has no adapter registry, so importing
the macro is the complete setup.
Violations remain structured data until that testing layer formats them. ViolationFactory owns
the wording for every built-in violation; ResultFactory adds pass/fail semantics, numbering and
optional ANSI color. These values remain the low-level bridge for custom test or CI integration:
use archunit::{
Checkable, ColorChoice, ResultFactory, TestResultOptions, project_files,
};
let rule = project_files()
.in_folder("src/**")
.should()
.have_no_cycles();
let violations = rule.check().expect("the architecture check should run");
let display = TestResultOptions::new().with_color(ColorChoice::Never);
let result = ResultFactory::from_violations_with_options(&violations, &display);
assert_eq!(result.passed, violations.is_empty());ColorChoice::Auto is the default and respects terminal capability, NO_COLOR, TERM=dumb, and
CI=true; Always and Never make output deterministic. The assertion macro uses these same
factories, so message formatting does not drift between integrations.
The graph model is also available directly:
use archunit::{Edge, Graph, ImportKind};
let dependency = Edge::new(
"src/api.rs",
"src/db.rs",
false,
[ImportKind::Use],
);
let graph = Graph::from_edges([dependency.clone()]);
assert_eq!(graph.edges(), &[dependency]);§Rust dependency extraction
extract_graph discovers Cargo workspace sources, follows Rust module layout, classifies internal
and external dependencies, merges parallel edges, and returns non-fatal extraction diagnostics with
the graph. Results are memoized per project and extraction configuration; use clear_graph_cache
or CheckOptions::with_clear_cache(true) when source changes must be observed in the same process.
One use, pub use, extern crate, or mod declaration can be omitted from the graph with a Rust
comment on the same or immediately preceding line:
use legacy_client::Client; // archunit: ignore
// Only the matching member of a grouped import is ignored.
use crate::adapters::{legacy, current}; // archunit: ignore crate::adapters::legacyThe optional scope matches the written Rust path exactly or by :: prefix. The directive does not
suppress separate qualified-path expressions, and ignored imports still establish aliases for
resolving those expressions.
§Executable self-architecture
ArchUnitRust dogfoods its public API in tests/architecture.rs. The suite
keeps common limited to itself, the standard library, and the explicit Rust analysis toolchain;
forbids dependencies between the files, graph, layers, metrics, and slices domains; and
prevents implementation files from importing through src/lib.rs. lib.rs is therefore an
outward-only facade, while each top-level internal module owns the imports used by its
implementation.
Rust module ownership creates structural edges that other languages do not have: a parent declares
mod child and often pub uses the child’s API. A child importing a sibling through its private
parent facade is not an executable dependency cycle. Cycle rules can make that distinction without
discarding parallel evidence:
use archunit::{ImportKind, assert_passes, project_files};
let rule = project_files()
.in_path("src/files**")
.should()
.have_no_cycles()
.excluding_dependency_kinds([ImportKind::Mod, ImportKind::PubUse]);
assert_passes!(rule);If the same source-target pair also has a Use, PathReference, or other retained kind, it remains
in the cycle graph with that evidence. The self-suite applies this rule independently to the
top-level aggregation files and every architectural unit. This preserves the deliberate closed
Violation/Checkable aggregation seam while still rejecting cycles inside any unit. See
ADR 0022 for the dependency directions and
trade-offs.
Siblings: ArchUnitTS · ArchUnitPython
Macros§
- Asserts that an architecture rule produces no violations.
Structs§
- Cargo’s authoritative description of the selected workspace.
- One crate target reported by Cargo metadata.
- Stateless per-call façade over an explicitly borrowed
LoggingOptionsvalue. - Options that control how one terminal architecture check runs.
- ANSI color helpers shared by result formatters and test integration.
- Built-in count choices over one immutable selection.
- Renders aggregated graph edges as standards-compliant CSV.
- Executable rule that judges selected source files with a user-defined predicate.
- One selected file that disagrees with a user-defined predicate.
- Executable user-defined metric predicate over selected Rust types.
- A user-defined type metric that can be measured or turned into a predicate rule.
- A Rust type whose custom metric value did not satisfy a user predicate.
- Executable positive rule requiring the selected file graph to be acyclic.
- One closed circular path through a projected dependency graph.
- Renders D2 diagram source from a completed snapshot.
- Executable rule over dependencies from project files to external crates.
- Immutable object stage selecting external Cargo-visible crate names.
- Executable rule over dependencies between project files.
- Immutable object stage selecting internal dependency targets.
- The deterministic result of Rust dependency extraction before graph-edge merging.
- One dependency syntax occurrence extracted from a Rust source file.
- Immutable modifiers controlling PlantUML diagram adherence.
- Executable
slices should adhere to diagramrule. - Immutable inline or file-backed PlantUML source, read only by a terminal check.
- Metrics and dependency evidence for one file-level architectural component.
- Immutable numeric input for Robert C. Martin’s component-distance formulas.
- One selected component-distance formula ready for extraction and measurement.
- Distance formula and architectural-zone choices over file components.
- Renders a Graphviz DOT directed graph from a completed snapshot.
- One directed dependency in an extracted Rust project.
- A rule selected no subject and therefore judged nothing.
- One external crate dependency that disagrees with a file rule.
- One non-fatal limitation encountered while extracting Rust dependencies.
- One declared data field and the methods that syntactically access it.
- Immutable scope builder selecting the files to which a rule applies.
- One internal file dependency that disagrees with a relational rule.
- Immutable source-file facts supplied to a user-defined predicate.
- Extracted counts and type information for one Rust source file.
- One selected file that disagrees with a name or location predicate.
- A compiled pattern bound to the part of an identifier it describes.
- Collapses file nodes to their containing folder at a fixed path depth.
- Executable
slices should not contain dependencyrule. - The extracted dependency graph.
- A deterministic dependency graph together with non-fatal extraction diagnostics.
- Immutable selection, collapse, and presentation options for one graph snapshot.
- Dispatches every output format from the same completed snapshot.
- Aggregated dependency evidence in a graph report snapshot.
- Stable node identity and display label in a graph report snapshot.
- Immutable-by-default graph after filtering, collapsing, aggregation, and counting.
- Counts describing the selected and aggregated graph snapshot.
- Builds the one renderer-neutral representation of a queried graph.
- Renders a complete, offline, self-contained HTML report.
- One inherent or trait implementation block.
- A deterministically ordered set of
ImportKindvalues. - Renders the complete graph snapshot as stable JSON.
- A named architectural layer and the file selectors that define it.
- Immutable stage defining which files belong to one named layer.
- Immutable stage adding an allowlist or blocklist policy for one source layer.
- One cross-layer dependency rejected by a named-layer policy.
- Immutable, executable named-layer dependency policy.
- Immutable method/field incidence data used by every LCOM formula.
- One selected LCOM formula ready for extraction and measurement.
- LCOM formula choices over eligible structs in one immutable selection.
- One immutable, single-line logging record before destination-specific timestamping.
- Immutable per-check logging configuration.
- The labels produced when a raw dependency is mapped into a domain view.
- Executable filename, folder, or path predicate for selected files.
- Shared immutable state for positive and negated file-predicate builders.
- Renders a Mermaid flowchart from a completed snapshot.
- One associated function whose signature has a
selfreceiver. - One numeric metric value and the complete subject that produced it.
- Executable arbitrary predicate over one selected built-in metric.
- One built-in metric value that did not satisfy a user predicate.
- One selected count metric ready for extraction and measurement.
- Executable exact numeric threshold over one selected metric.
- A threshold that cannot define a meaningful ordered comparison.
- One metric value that did not meet its numeric threshold.
- Executable distance rule that rejects one architectural zone.
- A file component whose abstractness/instability point lies in a discouraged zone.
- Immutable file/type selection for metrics extraction.
- Immutable presentation options for one metrics HTML report.
- Renders and writes self-contained offline metrics reports.
- A syntax failure while extracting metrics from one source input.
- The
should_notmood for file predicates. - Immutable negated mood for forbidden slice dependencies.
- Options controlling projection of a raw graph to file nodes.
- A user pattern compiled to the regular-expression substrate used by every matcher.
- Collapses node labels through a regular-expression capture replacement.
- An invalid glob or regular expression supplied by the user.
- One exclusion attached to a
PatternSpec. - Pattern compilation options.
- One selector pattern together with its ordered per-selector exclusions.
- One allowed directed dependency in a PlantUML component diagram.
- Immutable components and allowed directed dependencies parsed from PlantUML.
- Invalid input in the supported PlantUML component-diagram subset.
- Line-based parser for the supported PlantUML component-diagram subset.
- Deterministic PlantUML generation from projected slice dependencies.
- The
shouldmood for file predicates. - Immutable positive mood and optional modifiers for diagram adherence.
- Immutable query builder for dependency-graph snapshots and reports.
- Where Cargo project discovery begins.
- A deterministic metrics snapshot for one Cargo project selection.
- A labeled dependency retaining every raw edge collapsed into it.
- A graph node with its incoming and outgoing raw dependency evidence.
- Compiles user patterns consistently and binds them to selector targets.
- Options shared by every matcher produced by a
RegexFactory. - Shapes structured violations into a framework-neutral pass flag and complete message.
- One projected slice dependency rejected by a slice architecture rule.
- An immutable, reusable mapping from project-relative Rust files to slice names.
- An invalid projection definition supplied by a caller.
- Immutable scope describing how project files become named slices.
- One Rust source file belonging to a Cargo workspace member.
- Options that change Cargo source discovery.
- A failure in ArchUnit or its execution environment.
- A framework-neutral pass flag and its complete display message.
- Presentation and expectation options for
crate::ResultFactory. - One human-readable rendering of structured architecture-violation data.
- Metrics information for one Rust type declaration.
- An invalid use of the ArchUnit API.
- The sole mapping from structured violation data to human-readable prose.
Enums§
- A failure that prevented a rule from reaching an architecture verdict.
- One rejected region in the abstractness/instability plane.
- A Cargo target category relevant to source analysis.
- Controls ANSI styling in architecture-test messages.
- A built-in count metric and its valid Rust subject population.
- The classified destination of one extracted Rust dependency reference.
- One metric in the abstractness/instability component-distance family.
- The category of a non-fatal source extraction diagnostic.
- One strategy for relabeling report nodes before edge aggregation.
- Invalid graph query input or a collapse that cannot produce a report node.
- A supported graph report output format.
- The Rust syntax that produced a dependency edge.
- The named-layer policy that rejected a dependency.
- One formula in the lack-of-cohesion-of-methods family.
- Stable vocabulary for records emitted during architecture checks.
- Initialization policy for an existing per-options log file.
- Severity threshold for one check’s log records.
- One exact numeric relationship used by the five threshold verbs.
- The extracted subject measured by a metric.
- The user-facing syntax from which a
Patternwas compiled. - The part of an identifier against which a
crate::Patternis matched. - The slice policy that rejected a projected dependency.
- A Rust type declaration category.
- One data-carrying disagreement between a project and an architecture rule.
- The machine-readable family of a
Violation.
Constants§
- Directory names omitted from source discovery wherever they occur.
- The title used when a graph query does not provide one.
- Complete built-in stylesheet used when no custom CSS is supplied.
- Largest discount applied to distance by normalized distance.
- Strict upper boundary for abstractness and instability in the zone of pain.
- File lines at which the normalized-distance size discount reaches its cap.
- Strict lower boundary for abstractness and instability in the zone of uselessness.
Traits§
- A terminal architecture rule that can judge a project.
Functions§
- Collapses and aggregates selected graph edges in deterministic endpoint order.
- Combines an already extracted syntax snapshot and dependency graph into distance inputs.
- Clears every memoized graph and its diagnostics in the current process.
- Applies one optional collapse strategy to a graph node label.
- Filters, selects, collapses, aggregates, and counts one graph.
- Alias for
project_graph. - Alias for
project_graph_in. - Enumerates Rust source files under Cargo workspace members.
- Writes a rendered graph report as UTF-8, creating missing parent directories.
- Writes an already-rendered PlantUML report as UTF-8, creating missing parents.
- Parses selected Cargo targets and extracts Rust dependency references.
- Extracts file-level distance inputs from one Cargo project and options bag.
- Extracts count and type information from one Rust source string.
- Extracts or reuses the graph for one Cargo project and source configuration.
- Extracts a graph using the extraction-related settings from one architecture check.
- Extracts deterministic metrics information from every selected source in a Cargo project.
- Alias for
project_files. - Alias for
project_files_in. - Judges immutable file facts with one user-defined predicate.
- Calculates and checks one custom metric for every supplied type.
- Converts every projected cycle into machine-readable violation data.
- Collects actual slice dependencies not permitted by the supplied diagram.
- Produces the defensive violation for a terminal that selected no subjects.
- Judges external dependencies from selected files against a crate allowlist or denylist.
- Judges internal dependencies from selected subject files to an object-file allowlist or denylist.
- Collects dependencies that match one forbidden source-to-target slice pair.
- Collects rejected cross-layer dependencies from an already projected file graph.
- Judges selected files against one filename, folder, or path requirement.
- Returns structured violations for built-in measurements rejected by
predicate. - Returns structured violations for measurements that fail an exact comparison.
- Returns one structured violation for every component inside
zone. - Returns a mapper for every raw edge, including source-file self-edges.
- Alias for
project_layers. - Alias for
project_layers_in. - Locates the Cargo project above the current working directory.
- Locates the Cargo project selected by an explicit or automatic locator.
- Starts a metrics query with Cargo discovery at the working directory.
- Starts a metrics query with explicit Cargo project discovery.
- Creates a selector pattern that can receive one or more
exceptcompanions. - Returns a mapper for every dependency except source-file self-edges.
- Returns a mapper for non-self dependencies targeting external crates.
- Returns a mapper for non-self dependencies within the extracted project.
- Returns every elementary directed cycle in an evidence-retaining projected graph.
- Relabels raw graph edges and cumulates equal projected endpoint pairs.
- Starts a file architecture rule using automatic Cargo project discovery.
- Starts a file architecture rule at an explicit directory or
Cargo.tomlmanifest. - Starts a dependency-graph report query using automatic Cargo project discovery.
- Starts a dependency-graph report query at an explicit directory or
Cargo.tomlmanifest. - Projects a raw graph to internal file dependencies and returns every elementary cycle.
- Starts a named-layer architecture policy using automatic Cargo project discovery.
- Starts a named-layer policy at an explicit directory or
Cargo.tomlmanifest. - Starts a lazy slice architecture scope with automatic Cargo project discovery.
- Starts a lazy slice architecture scope at an explicit directory or Cargo manifest.
- Projects a graph to its internal nodes using default options.
- Projects a graph to nodes using explicit options.
- Maps Rust filename stems to slices by their longest matching suffix.
- Captures a slice name through exactly one
(**)placeholder in a portable path pattern. - Captures a slice name through the first group in a Rust regular expression.
- Creates the identity slice projection.
- Alias for
project_slices. - Alias for
project_slices_in. - Validates the finite threshold required by every threshold terminal.
Type Aliases§
- The complete outcome of running one architecture rule.
- A reusable, thread-safe question about one source file.
- A graph relabeling hook. Returning
Nonedrops the raw edge from the projected view. - Deterministically ordered display data for a metrics report.
- Every elementary directed cycle found in a projected dependency graph.
- A dependency graph after domain-specific relabeling and grouping.