crap4rust computes CRAP scores for Rust functions by combining complexity and test coverage.
What is a CRAP score? CRAP (Change Risk Anti-Patterns) combines cognitive complexity and test coverage: CRAP(m) = comp(m)² × (1 − cov(m))³ + comp(m). Functions above a score of 30 are flagged as crappy — they are complex enough that their lack of test coverage makes them a maintenance risk.
Full derivation of every term — how cognitive complexity is scored construct
by construct, how coverage is matched and duplicate records resolved, and
how a project-level verdict is computed from every function's own — is in
docs/FORMULA.md.
It is published as the Cargo subcommand package cargo-crap4rust, so the command is cargo crap4rust.
| Doc | What's in it |
|---|---|
docs/ARCHITECTURE.md |
How a crap4rust invocation flows through the code, module by module. |
docs/FORMULA.md |
Every scoring term, in full, kept in sync with src/. |
docs/ADRs/ |
Why the codebase is shaped the way it is. |
docs/ROADMAP.md |
What's shipped, what's next. |
docs/OPEN_POINTS.md |
Known gaps, deliberately deferred. |
docs/IMPLEMENTED-FEATURES.md |
The full shipped feature set. |
CHANGELOG.md |
Release history. |
cargo install cargo-crap4rust
cargo install cargo-llvm-cov
rustup component add llvm-toolscrap4rust scores complexity against coverage, and it measures that coverage by
running cargo-llvm-cov, which in
turn needs the llvm-tools rustup component. Neither comes with crap4rust, and
neither is optional: without them any run that has to generate coverage fails.
Passing --coverage <PATH> with a report you already produced is the one way to
run without them.
just stage1
just stage2Both must be green before a change is complete. Stage 1 is formatting, clippy
and tests; stage 2 is cargo xtask stage2, which runs, in order:
cargo stern4rust (house coding rules, every one of them, on every workspace
member), cargo shear (every declared dependency used), cargo dry4rust (no duplication beyond dry4rust-baseline.json),
cargo crap4rust (complexity against coverage), cargo twin4rust (every
source file has a mirrored test file) and cargo iceberg4rust (file risk).
Stage 1 is not cargo built-ins alone here, which is the one way this
repository differs from its siblings: crap4rust is the coverage tool, so its
own validation tests drive the built binary through the path that shells out to
cargo llvm-cov. A checkout without that install fails stage 1, before ever
reaching the gate.
Everything the two stages need, none of which ships with cargo:
| Tool | Install | Needed by |
|---|---|---|
just |
cargo install just |
both stages |
cargo-llvm-cov |
cargo install cargo-llvm-cov |
both stages |
llvm-tools rustup component |
rustup component add llvm-tools |
both stages |
cargo-stern4rust |
cargo install cargo-stern4rust |
stage 2 |
cargo-dry4rust |
cargo install cargo-dry4rust |
stage 2 |
cargo-crap4rust |
cargo install cargo-crap4rust |
stage 2 |
cargo-twin4rust |
cargo install cargo-twin4rust |
stage 2 |
cargo-iceberg4rust |
cargo install cargo-iceberg4rust |
stage 2 |
cargo-shear |
cargo install --locked cargo-shear --version 1.14.0 |
stage 2 |
cargo-llvm-cov is needed by stage 1 as well, not only by the gate: this
repository is the coverage tool, so its own validation tests drive the built
binary down the path that shells out to it.
The CRAP gate measures this repository with the published cargo-crap4rust
rather than the binary in the working tree, so a regression in the tree cannot
excuse itself.
CI (.github/workflows/ci.yml) runs both stages on Ubuntu, Windows and macOS
for every pull request and every push to main.
Licensed under the MIT License.
- Computes a CRAP score for each discovered Rust function
- Generates coverage automatically with
cargo llvm-covwhen--coverageis omitted - Prints a single report to the console
- Supports multiple
--packageflags for one aggregated report - Defaults to analysing all workspace members when
--packageis omitted in a multi-package workspace - Does not count try-operator propagation with
?as cognitive complexity - Supports
--output-format jsonfor structured CI-friendly output - Supports
--warn-thresholdto set the warning level independently from the crappy threshold - Supports
--warn-onlyto report without failing the exit code even when thresholds are exceeded - Supports
--all-featuresto activate all Cargo features during the coverage build - Excludes test-only code from discovery whether it's an inline
#[cfg(test)] mod tests { ... }block or a file-based#[cfg(test)] mod tests;submodule - Cognitive complexity scoring lives in its own dedicated module
Analyse the default scope for a manifest:
- single-package manifest: analyses the root package
- multi-package workspace: analyses all workspace members unless
--packageis provided
cargo crap4rust --manifest-path C:\Projects\my-workspace\Cargo.tomlAnalyse one specific package in a workspace and override the default all-members selection:
cargo crap4rust --manifest-path C:\Projects\my-workspace\Cargo.toml --package app-coreAnalyse multiple packages and produce one combined console report:
cargo crap4rust --manifest-path C:\Projects\my-workspace\Cargo.toml --package app-core --package app-validationUse a precomputed coverage export instead of generating coverage automatically:
cargo crap4rust --manifest-path C:\Projects\my-workspace\Cargo.toml --package app-core --coverage C:\Projects\my-workspace\target\coverage.jsonUse stricter project thresholds:
cargo crap4rust --manifest-path C:\Projects\my-workspace\Cargo.toml --threshold 25 --project-threshold 3.0 --strictPass Cargo feature flags to the coverage build:
cargo crap4rust --manifest-path C:\Projects\my-workspace\Cargo.toml --package app-core --features host-testsDisable default features and enable specific ones:
cargo crap4rust --manifest-path C:\Projects\my-workspace\Cargo.toml --package app-core --no-default-features --features host-analysisActivate all Cargo features during the coverage build:
cargo crap4rust --manifest-path C:\Projects\my-workspace\Cargo.toml --package app-core --all-featuresInclude test targets in the analysis:
cargo crap4rust --manifest-path C:\Projects\my-workspace\Cargo.toml --package app-validation --include-test-targetsExclude specific source paths from analysis:
cargo crap4rust --manifest-path C:\Projects\my-workspace\Cargo.toml --package app-core --exclude-path src/scenariosOutput as JSON for CI pipelines:
cargo crap4rust --manifest-path C:\Projects\my-workspace\Cargo.toml --output-format jsonSet a custom warning threshold:
cargo crap4rust --manifest-path C:\Projects\my-workspace\Cargo.toml --warn-threshold 15Report without failing the exit code even when thresholds are exceeded:
cargo crap4rust --manifest-path C:\Projects\my-workspace\Cargo.toml --warn-onlyExample run against the etheram-raft workspace (all four workspace
members — node, node-infra, validation, system-tests — analysed
together, since --package is omitted):
cargo crap4rust --manifest-path C:\Projects\etheram\etheram-raft\Cargo.tomlReport excerpt:
crap4rust report for node, node-infra, validation, system-tests
| Package | Function | File | Line | Complexity | Coverage | CRAP | Verdict |
|---|---|---|---|---|---|---|---|
system-tests |
GrpcRaftTransportInner::send_with_retry_async |
grpc_raft_transport.rs |
67 | 8 | 0.0% | 72.0 | crappy |
system-tests |
SledRaftStorage::mutate |
sled_raft_storage.rs |
163 | 7 | 0.0% | 56.0 | crappy |
system-tests |
TimerSlots::check_slot |
desktop_raft_timer.rs |
92 | 6 | 0.0% | 42.0 | crappy |
Summary: total_functions=419, crappy_functions=3, crappy_percent=0.7%, threshold=30.0, project_threshold=5.0%, verdict=warn.
Production functions only — test code and generated code excluded by default.
The report above is abbreviated to the highest-scoring rows, with function names and file paths shortened for readability. When coverage is generated automatically, cargo llvm-cov also emits normal build and test output before the final crap4rust report.
Try-operator propagation with ? is treated as error forwarding rather than decision-making complexity, so CRAP scoring reflects branching and control-flow structure instead of penalising straightforward Result propagation.
See docs/IMPLEMENTED-FEATURES.md for the shipped feature set and docs/ROADMAP.md for the broader plan.