From c78f9757bd8dbbcc83b06da1e2adf215f7feec7c Mon Sep 17 00:00:00 2001 From: Stuart Harris Date: Sun, 10 Mar 2024 09:18:17 +0000 Subject: [PATCH] use guppy to slurp workspace structure --- Cargo.lock | 193 ++++++++++++++++++++++++++++++++++++++++ crux_cli/Cargo.toml | 3 + crux_cli/src/args.rs | 4 +- crux_cli/src/codegen.rs | 53 +++++++++-- crux_cli/src/graph.rs | 8 ++ crux_cli/src/main.rs | 1 + 6 files changed, 255 insertions(+), 7 deletions(-) create mode 100644 crux_cli/src/graph.rs diff --git a/Cargo.lock b/Cargo.lock index 7822640fe..951203e4e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,19 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom 0.2.12", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.3" @@ -246,12 +259,54 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +[[package]] +name = "camino" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "cc" version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +[[package]] +name = "cfg-expr" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa50868b64a9a6fda9d593ce778849ea8715cd2a3d2cc17ffdb4a2f2f2f1961d" +dependencies = [ + "smallvec", + "target-lexicon", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -394,10 +449,13 @@ dependencies = [ "anyhow", "clap", "console", + "guppy", "ignore", "libc", "ramhorns", + "rustdoc-types", "serde", + "serde_json", "similar", "tokio", "tokio-fd", @@ -532,6 +590,12 @@ dependencies = [ "syn 2.0.55", ] +[[package]] +name = "debug-ignore" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe7ed1d93f4553003e20b629abe9085e1e81b1429520f897f8f8860bc6dfc21" + [[package]] name = "derive_builder" version = "0.20.0" @@ -596,6 +660,12 @@ dependencies = [ "serde", ] +[[package]] +name = "either" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" + [[package]] name = "encode_unicode" version = "0.3.6" @@ -669,6 +739,12 @@ version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + [[package]] name = "fnv" version = "1.0.7" @@ -865,6 +941,39 @@ dependencies = [ "walkdir", ] +[[package]] +name = "guppy" +version = "0.17.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34e99a7734579b834a076ef11789783c153c6eb5fb3520ed15bc41f483f0f317" +dependencies = [ + "ahash", + "camino", + "cargo_metadata", + "cfg-if", + "debug-ignore", + "fixedbitset", + "guppy-workspace-hack", + "indexmap", + "itertools", + "nested", + "once_cell", + "pathdiff", + "petgraph", + "semver", + "serde", + "serde_json", + "smallvec", + "static_assertions", + "target-spec", +] + +[[package]] +name = "guppy-workspace-hack" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92620684d99f750bae383ecb3be3748142d6095760afd5cbcf2261e9a279d780" + [[package]] name = "hashbrown" version = "0.14.3" @@ -1028,6 +1137,15 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -1132,6 +1250,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "nested" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b420f638f07fe83056b55ea190bb815f609ec5a35e7017884a10f78839c9e" + [[package]] name = "num-traits" version = "0.2.18" @@ -1195,12 +1319,31 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" +dependencies = [ + "camino", +] + [[package]] name = "percent-encoding" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "petgraph" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +dependencies = [ + "fixedbitset", + "indexmap", +] + [[package]] name = "phf" version = "0.10.1" @@ -1524,6 +1667,15 @@ dependencies = [ "semver", ] +[[package]] +name = "rustdoc-types" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0904b9147011800e63763fb9e49bbeaf76c1b6ab8982824c659dce5433712559" +dependencies = [ + "serde", +] + [[package]] name = "rustix" version = "0.38.32" @@ -1563,6 +1715,9 @@ name = "semver" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +dependencies = [ + "serde", +] [[package]] name = "serde" @@ -1744,6 +1899,24 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "target-lexicon" +version = "0.12.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" + +[[package]] +name = "target-spec" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36a8e795b1824524d13cdf04f73cf8b4f244ce86c96b4d2a83a6ca1a753d2752" +dependencies = [ + "cfg-expr", + "guppy-workspace-hack", + "target-lexicon", + "unicode-ident", +] + [[package]] name = "tempfile" version = "3.10.1" @@ -2220,3 +2393,23 @@ checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" dependencies = [ "memchr", ] + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] diff --git a/crux_cli/Cargo.toml b/crux_cli/Cargo.toml index be9103ad1..9955b3a80 100644 --- a/crux_cli/Cargo.toml +++ b/crux_cli/Cargo.toml @@ -17,10 +17,13 @@ path = "src/main.rs" anyhow.workspace = true clap = { version = "4.3.24", features = ["derive"] } console = "0.15.8" +guppy = "0.17.5" ignore = "0.4.22" libc = "0.2.153" ramhorns = "0.14.0" +rustdoc-types = "0.24.0" serde = { workspace = true, features = ["derive"] } +serde_json = "1.0.114" similar = { version = "2.4.0", features = ["inline"] } tokio = { version = "1.36.0", features = ["full"] } tokio-fd = "0.3.0" diff --git a/crux_cli/src/args.rs b/crux_cli/src/args.rs index f94e283ad..70aabd562 100644 --- a/crux_cli/src/args.rs +++ b/crux_cli/src/args.rs @@ -48,9 +48,9 @@ pub(crate) struct DoctorArgs { #[derive(Args)] pub(crate) struct CodegenArgs { - /// path to the directory containing the Cargo.toml manifest + /// name of the library containing your Crux App #[arg(long, short)] - pub path: PathBuf, + pub lib: String, } #[cfg(test)] diff --git a/crux_cli/src/codegen.rs b/crux_cli/src/codegen.rs index efc89a60d..3b9316e13 100644 --- a/crux_cli/src/codegen.rs +++ b/crux_cli/src/codegen.rs @@ -1,10 +1,20 @@ -use anyhow::Result; -use std::io::{stdout, IsTerminal}; -use tokio::process::Command; +use anyhow::{bail, Result}; +use rustdoc_types::{Crate, Impl, ItemEnum, Path}; +use std::{ + fs::File, + io::{stdout, IsTerminal}, +}; +use tokio::{process::Command, task::spawn_blocking}; -use crate::{args::CodegenArgs, command_runner}; +use crate::{args::CodegenArgs, command_runner, graph}; pub async fn codegen(args: &CodegenArgs) -> Result<()> { + let graph = graph::compute_package_graph()?; + + let Ok(lib) = graph.workspace().member_by_path(&args.lib) else { + bail!("Could not find workspace package with path {}", args.lib) + }; + let mut cmd = Command::new("cargo"); cmd.env("RUSTC_BOOTSTRAP", "1") .env( @@ -12,8 +22,9 @@ pub async fn codegen(args: &CodegenArgs) -> Result<()> { "-Z unstable-options --output-format=json --cap-lints=allow", ) .arg("doc") + .arg("--no-deps") .arg("--manifest-path") - .arg(&args.path) + .arg(lib.manifest_path()) .arg("--lib"); if stdout().is_terminal() { cmd.arg("--color=always"); @@ -21,5 +32,37 @@ pub async fn codegen(args: &CodegenArgs) -> Result<()> { command_runner::run(&mut cmd).await?; + let target_directory = graph.workspace().target_directory().as_std_path(); + let json_path = target_directory + .join("doc") + .join(format!("{}.json", lib.name().replace("-", "_"))); + + let rustdoc: Crate = spawn_blocking(move || { + let file = File::open(&json_path)?; + let crate_: Crate = serde_json::from_reader(file)?; + Ok::(crate_) + }) + .await??; + + if let Some(name) = rustdoc.index.iter().find_map(|(_k, v)| { + if let ItemEnum::Impl(Impl { + trait_: Some(rustdoc_types::Path { + name: trait_name, .. + }), + for_: rustdoc_types::Type::ResolvedPath(Path { name, .. }), + .. + }) = &v.inner + { + (trait_name == &"App".to_string()).then(|| name) + } else { + None + } + }) { + println!( + "The struct that implements crux_core::App is called {:?}", + name + ); + } + Ok(()) } diff --git a/crux_cli/src/graph.rs b/crux_cli/src/graph.rs new file mode 100644 index 000000000..90cc84ec0 --- /dev/null +++ b/crux_cli/src/graph.rs @@ -0,0 +1,8 @@ +use anyhow::{anyhow, Result}; +use guppy::{graph::PackageGraph, MetadataCommand}; + +pub(crate) fn compute_package_graph() -> Result { + let mut cmd = MetadataCommand::new(); + let package_graph = PackageGraph::from_command(&mut cmd); + package_graph.map_err(|e| anyhow!(e)) +} diff --git a/crux_cli/src/main.rs b/crux_cli/src/main.rs index 2443c6ab0..453962559 100644 --- a/crux_cli/src/main.rs +++ b/crux_cli/src/main.rs @@ -10,6 +10,7 @@ mod command_runner; mod config; mod diff; mod doctor; +mod graph; mod template; mod workspace;