Skip to content

Commit

Permalink
Add --no-owns CLI option for dependencies command
Browse files Browse the repository at this point in the history
  • Loading branch information
regexident committed Dec 10, 2024
1 parent 57e6b87 commit d81109d
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 0 deletions.
24 changes: 24 additions & 0 deletions src/command/dependencies/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,30 @@ impl<'a> Filter<'a> {

debug_assert!(graph.contains_node(root_idx), "{}", ROOT_DROP_ERR_MSG);

if self.options.selection.no_owns {
// drop all "owns" edges:
graph.retain_edges(|graph, edge_idx| !matches!(&graph[edge_idx], Relationship::Owns));

// By removing the structural "owns" edges from the graph, that make it connected,
// we are likely to end up with a graph consisting of mostly individual unconnected nodes,
// which now basically contain no "dependency" information and thus aren't interesting to us.
//
// We thus also drop all nodes that don't have any remaining edges connected to them
// (with the exception of the crate's node, for reasons):
graph.retain_nodes(|graph, node_idx| {
let out_degree = graph
.neighbors_directed(node_idx, Direction::Outgoing)
.count();
let in_degree = graph
.neighbors_directed(node_idx, Direction::Incoming)
.count();

node_idx == root_idx || (out_degree + in_degree) > 0
});
}

debug_assert!(graph.contains_node(root_idx), "{}", ROOT_DROP_ERR_MSG);

Ok(graph)
}

Expand Down
4 changes: 4 additions & 0 deletions src/command/dependencies/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ pub struct SelectionOptions {
#[clap(long = "no-modules")]
pub no_modules: bool,

/// Filter out structural "owns" edges from graph.
#[clap(long = "no-owns")]
pub no_owns: bool,

/// Filter out sysroot crates (`std`, `core` & friends) from graph.
#[arg(long = "no-sysroot")]
pub no_sysroot: bool,
Expand Down
10 changes: 10 additions & 0 deletions tests/dependencies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,16 @@ mod selection {
);
}

mod no_owns {
test_cmd!(
args: "dependencies \
--no-owns",
success: true,
color_mode: ColorMode::Plain,
project: smoke
);
}

mod no_traits {
test_cmd!(
args: "dependencies \
Expand Down
2 changes: 2 additions & 0 deletions tests/snapshots/dependencies__help__smoke.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
source: tests/dependencies.rs
assertion_line: 5
expression: output
snapshot_kind: text
---
Expand Down Expand Up @@ -27,6 +28,7 @@ Options:
--no-externs Filter out extern items from extern crates from graph
--no-fns Filter out functions (e.g. fns, async fns, const fns) from graph
--no-modules Filter out modules (e.g. `mod foo`, `mod foo {}`) from graph
--no-owns Filter out structural "owns" edges from graph
--no-sysroot Filter out sysroot crates (`std`, `core` & friends) from graph
--no-traits Filter out traits (e.g. trait, unsafe trait) from graph
--no-types Filter out types (e.g. structs, unions, enums) from graph
Expand Down
127 changes: 127 additions & 0 deletions tests/snapshots/dependencies__selection__no_owns__smoke.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
---
source: tests/dependencies.rs
expression: output
snapshot_kind: text
---
COMMAND:
dependencies
--no-owns

STDERR:

STDOUT:
digraph {

graph [
label="smoke",
labelloc=t,

pad=0.4,

// Consider rendering the graph using a different layout algorithm, such as:
// [dot, neato, twopi, circo, fdp, sfdp]
layout=neato,
overlap=false,
splines="line",
rankdir=LR,

fontname="Helvetica",
fontsize="36",
];

node [
fontname="monospace",
fontsize="10",
shape="record",
style="filled",
];

edge [
fontname="monospace",
fontsize="10",
];

"alloc::fmt" [label="external mod|alloc::fmt", fillcolor="#81c169"]; // "mod" node
"alloc::string::String" [label="external struct|alloc::string::String", fillcolor="#81c169"]; // "struct" node
"bool" [label="external builtin|bool", fillcolor="#81c169"]; // "builtin" node
"core::cmp" [label="external mod|core::cmp", fillcolor="#81c169"]; // "mod" node
"core::future::future::Future" [label="external trait|core::future::future::Future", fillcolor="#81c169"]; // "trait" node
"core::marker::Sized" [label="external trait|core::marker::Sized", fillcolor="#81c169"]; // "trait" node
"core::ops" [label="external mod|core::ops", fillcolor="#81c169"]; // "mod" node
"i32" [label="external builtin|i32", fillcolor="#81c169"]; // "builtin" node
"smoke" [label="crate|smoke", fillcolor="#5397c8"]; // "crate" node
"smoke::derives::Dummy" [label="pub(self) struct|smoke::derives::Dummy", fillcolor="#db5367"]; // "struct" node
"smoke::derives::Dummy::clone" [label="pub(self) fn|smoke::derives::Dummy::clone", fillcolor="#db5367"]; // "fn" node
"smoke::functions::Crate" [label="pub(self) type|smoke::functions::Crate", fillcolor="#db5367"]; // "type" node
"smoke::functions::Local" [label="pub(self) struct|smoke::functions::Local", fillcolor="#db5367"]; // "struct" node
"smoke::functions::Std" [label="pub(self) type|smoke::functions::Std", fillcolor="#db5367"]; // "type" node
"smoke::functions::body" [label="pub(self) fn|smoke::functions::body", fillcolor="#db5367"]; // "fn" node
"smoke::functions::inputs" [label="pub(self) fn|smoke::functions::inputs", fillcolor="#db5367"]; // "fn" node
"smoke::functions::outputs" [label="pub(self) fn|smoke::functions::outputs", fillcolor="#db5367"]; // "fn" node
"smoke::hierarchy" [label="pub(crate) mod|smoke::hierarchy", fillcolor="#f8c04c"]; // "mod" node
"smoke::methods::Crate" [label="pub(self) type|smoke::methods::Crate", fillcolor="#db5367"]; // "type" node
"smoke::methods::Dummy::body" [label="pub(self) fn|smoke::methods::Dummy::body", fillcolor="#db5367"]; // "fn" node
"smoke::methods::Dummy::inputs" [label="pub(self) fn|smoke::methods::Dummy::inputs", fillcolor="#db5367"]; // "fn" node
"smoke::methods::Dummy::outputs" [label="pub(self) fn|smoke::methods::Dummy::outputs", fillcolor="#db5367"]; // "fn" node
"smoke::methods::Local" [label="pub(self) struct|smoke::methods::Local", fillcolor="#db5367"]; // "struct" node
"smoke::methods::Std" [label="pub(self) type|smoke::methods::Std", fillcolor="#db5367"]; // "type" node
"smoke::target::Target" [label="pub struct|smoke::target::Target", fillcolor="#81c169"]; // "struct" node
"smoke::uses" [label="pub(crate) mod|smoke::uses", fillcolor="#f8c04c"]; // "mod" node
"smoke::uses::cycle::node_0" [label="pub(self) mod|smoke::uses::cycle::node_0", fillcolor="#db5367"]; // "mod" node
"smoke::uses::cycle::node_1" [label="pub(self) mod|smoke::uses::cycle::node_1", fillcolor="#db5367"]; // "mod" node
"smoke::uses::cycle::node_1::node_2" [label="pub(self) mod|smoke::uses::cycle::node_1::node_2", fillcolor="#db5367"]; // "mod" node
"smoke::visibility::dummy::kinds::AsyncFunction" [label="pub(self) async fn|smoke::visibility::dummy::kinds::AsyncFunction", fillcolor="#db5367"]; // "async fn" node
"smoke::visibility::dummy::kinds::Struct" [label="pub(self) struct|smoke::visibility::dummy::kinds::Struct", fillcolor="#db5367"]; // "struct" node
"smoke::visibility::dummy::kinds::Trait" [label="pub(self) trait|smoke::visibility::dummy::kinds::Trait", fillcolor="#db5367"]; // "trait" node
"smoke::visibility::dummy::kinds::TraitAlias" [label="pub(self) type|smoke::visibility::dummy::kinds::TraitAlias", fillcolor="#db5367"]; // "type" node
"smoke::visibility::dummy::kinds::TypeAlias" [label="pub(self) type|smoke::visibility::dummy::kinds::TypeAlias", fillcolor="#db5367"]; // "type" node
"str" [label="external builtin|str", fillcolor="#81c169"]; // "builtin" node

"smoke::derives::Dummy::clone" -> "bool" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::derives::Dummy::clone" -> "smoke::derives::Dummy" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::functions::Crate" -> "smoke::target::Target" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::functions::Std" -> "alloc::string::String" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::functions::body" -> "alloc::string::String" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::functions::body" -> "i32" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::functions::body" -> "smoke::functions::Local" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::functions::body" -> "smoke::target::Target" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::functions::body" -> "str" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::functions::inputs" -> "alloc::string::String" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::functions::inputs" -> "i32" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::functions::inputs" -> "smoke::functions::Local" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::functions::inputs" -> "smoke::target::Target" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::functions::inputs" -> "str" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::functions::outputs" -> "alloc::string::String" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::functions::outputs" -> "i32" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::functions::outputs" -> "smoke::functions::Local" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::functions::outputs" -> "smoke::target::Target" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::functions::outputs" -> "str" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::methods::Crate" -> "smoke::target::Target" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::methods::Dummy::body" -> "alloc::string::String" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::methods::Dummy::body" -> "i32" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::methods::Dummy::body" -> "smoke::methods::Local" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::methods::Dummy::body" -> "smoke::target::Target" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::methods::Dummy::body" -> "str" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::methods::Dummy::inputs" -> "alloc::string::String" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::methods::Dummy::inputs" -> "i32" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::methods::Dummy::inputs" -> "smoke::methods::Local" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::methods::Dummy::inputs" -> "smoke::target::Target" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::methods::Dummy::inputs" -> "str" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::methods::Dummy::outputs" -> "alloc::string::String" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::methods::Dummy::outputs" -> "i32" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::methods::Dummy::outputs" -> "smoke::methods::Local" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::methods::Dummy::outputs" -> "smoke::target::Target" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::methods::Dummy::outputs" -> "str" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::methods::Std" -> "alloc::string::String" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::uses" -> "alloc::fmt" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::uses" -> "core::cmp" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::uses" -> "core::ops" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::uses" -> "smoke::hierarchy" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::uses::cycle::node_0" -> "smoke::uses::cycle::node_1" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::uses::cycle::node_1::node_2" -> "smoke::uses::cycle::node_0" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::visibility::dummy::kinds::AsyncFunction" -> "core::future::future::Future" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::visibility::dummy::kinds::AsyncFunction" -> "core::marker::Sized" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::visibility::dummy::kinds::TraitAlias" -> "smoke::visibility::dummy::kinds::Trait" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
"smoke::visibility::dummy::kinds::TypeAlias" -> "smoke::visibility::dummy::kinds::Struct" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge

}

0 comments on commit d81109d

Please sign in to comment.