A cargo plugin for visualizing/analyzing a crate's internal structure.
With time, as your Rust projects grow bigger and bigger, it gets more and more important to properly structure your code. Fortunately Rust provides us with a quite sophisticated module system, allowing us to neatly split up our crates into arbitrarily small sub-modules of types and functions. While this helps to avoid monolithic and unstructured chunks of code, it can also make it hard at times to still mentally stay on top of the over-all high-level structure of the project at hand.
This is where cargo-modules
comes into play:
Install cargo-modules
via:
cargo install cargo-modules
The cargo-modules
tool comes with a couple of commands:
# Print a crate's hierarchical structure as a tree:
cargo modules structure <OPTIONS>
# Print a crate's internal dependencies as a graph:
cargo modules dependencies <OPTIONS>
# Detect unlinked source files within a crate's directory:
cargo modules orphans <OPTIONS>
Print a crate's hierarchical structure as a tree:
cargo modules structure <OPTIONS>
cd ./tests/projects/readme_tree_example
cargo-modules structure --cfg-test
Output:
crate readme_tree_example
├── trait Lorem: pub
├── mod amet: pub(crate)
│ └── mod consectetur: pub(self)
│ └── mod adipiscing: pub(self)
│ └── union Elit: pub(in crate::amet)
├── mod dolor: pub(crate)
│ └── enum Sit: pub(crate)
└── mod tests: pub(crate) #[cfg(test)]
└── fn it_works: pub(self) #[test]
(Project source code: readme_tree_example/src/lib.rs)
If you are running the command on a terminal with color support and don't have NO_COLOR
defined in your environment, then the output will be colored for easier visual parsing:
└── <visibility> <keyword> <name> [<test-attributes>]
The <visibility>
(more info) is further more highlighted by the following colors:
Color | Meaning |
---|---|
🟢 green | Items visible to all and everything (i.e. pub ) |
🟡 yellow | Items visible to the current crate (i.e. pub(crate) ) |
🟠 orange | Items visible to a certain parent module (i.e. pub(in path) ) |
🔴 red | Items visible to the current module (i.e. pub(self) , implied by lack of pub … ) |
The <keyword>
is highlighted in 🔵 blue to visually separate it from the name.
Test-guarded items (i.e. #[cfg(test)] …
) and test functions (i.e. #[test] fn …
) have their corresponding <test-attributes>
printed next to them in gray and cyan.
Print a crate's internal dependencies as a graph:
cargo modules dependencies <OPTIONS>
cargo modules dependencies --no-externs --no-fns --no-sysroot --no-traits --no-types --no-uses > mods.dot
(The command above is equivalent to cargo-modules generate graph
from v0.12.0 or earlier.)
cd ./tests/projects/smoke
cargo-modules dependencies --cfg-test | dot -Tsvg
See "./docs/dependencies_output.dot" for the corresponding raw dot file.
(Project source code: readme_graph_example/src/lib.rs)
The individual nodes are structured as follows:
┌────────────────────────┐
│ <visibility> <keyword> │
├────────────────────────┤
│ <path> │
└────────────────────────┘
The <visibility>
(more info) is further more highlighted by the following colors:
Color | Meaning |
---|---|
🔵 blue | Crates (i.e. their implicit root module) |
🟢 green | Items visible to all and everything (i.e. pub ) |
🟡 yellow | Items visible to the current crate (i.e. pub(crate) ) |
🟠 orange | Items visible to a certain parent module (i.e. pub(in path) ) |
🔴 red | Items visible to the current module (i.e. pub(self) , implied by lack of pub … ) |
cargo-modules's dependencies
command checks for the presence of a --acyclic
flag. If found it will search for cycles in the directed graph and return an error for any cycles it found.
Running cargo modules dependencies --lib --acyclic
on the source of the tool itself emits the following cycle error:
Error: Circular dependency between `cargo_modules::options::general` and `cargo_modules::options::generate`.
┌> cargo_modules::options::general
│ └─> cargo_modules::options::generate::graph
│ └─> cargo_modules::options::generate
└──────────┘
Detect unlinked source files within a crate's directory:
cargo modules orphans <OPTIONS>
cd ./tests/projects/readme_tree_example
cargo-modules structure --types --traits --fns --tests
Output:
2 orphans found:
warning: orphaned module `foo` at src/orphans/foo/mod.rs
--> src/orphans.rs
| ^^^^^^^^^^^^^^ orphan module not loaded from file
|
help: consider loading `foo` from module `orphans::orphans`
|
| mod foo;
| ++++++++
|
warning: orphaned module `bar` at src/orphans/bar.rs
--> src/orphans.rs
| ^^^^^^^^^^^^^^ orphan module not loaded from file
|
help: consider loading `bar` from module `orphans::orphans`
|
| mod bar;
| ++++++++
|
Error: Found 2 orphans in crate 'orphans'
(Project source code: readme_tree_example/src/lib.rs)
cargo-modules checks for the presence of a NO_COLOR
environment variable that, when present (regardless of its value), prevents the addition of color to the console output (and only the console output!).
Please read CONTRIBUTING.md for details on our code of conduct,
and the process for submitting pull requests to us.
We use SemVer for versioning. For the versions available, see the tags on this repository.
This project is licensed under the MPL-2.0 – see the LICENSE.md file for details.