mirror of
https://github.com/fanzeyi/cargo-play
synced 2024-11-10 05:04:13 +00:00
add --infer
that allows cargo-play to infer dependencies
This commit is contained in:
parent
7e424d95b3
commit
8aff17b192
9 changed files with 150 additions and 1 deletions
38
Cargo.lock
generated
38
Cargo.lock
generated
|
@ -80,10 +80,13 @@ dependencies = [
|
|||
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pathdiff 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"structopt 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -192,6 +195,14 @@ dependencies = [
|
|||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.6.12"
|
||||
|
@ -200,6 +211,14 @@ dependencies = [
|
|||
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.7.0"
|
||||
|
@ -318,6 +337,16 @@ dependencies = [
|
|||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.10.1"
|
||||
|
@ -371,6 +400,11 @@ name = "unicode-xid"
|
|||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.1"
|
||||
|
@ -419,7 +453,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum pathdiff 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a3bf70094d203e07844da868b634207e71bfab254fe713171fae9a6e751ccf31"
|
||||
"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b"
|
||||
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||
"checksum proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5c2380ae88876faae57698be9e9775e3544decad214599c3a6266cca6ac802"
|
||||
"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"
|
||||
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
|
||||
"checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c"
|
||||
"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853"
|
||||
"checksum rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "615e683324e75af5d43d8f7a39ffe3ee4a9dc42c5c701167a71dc59c3a493aca"
|
||||
|
@ -435,6 +471,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum structopt 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "3d0760c312538987d363c36c42339b55f5ee176ea8808bbe4543d484a291c8d1"
|
||||
"checksum structopt-derive 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "528aeb7351d042e6ffbc2a6fb76a86f9b622fdf7c25932798e7a82cb03bc94c6"
|
||||
"checksum syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)" = "a1393e4a97a19c01e900df2aec855a29f71cf02c402e2f443b8d2747c25c5dbe"
|
||||
"checksum syn 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "158521e6f544e7e3dcfc370ac180794aa38cb34a1b1e07609376d4adcf429b93"
|
||||
"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
|
||||
"checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea"
|
||||
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||
|
@ -442,6 +479,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1"
|
||||
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
|
||||
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
|
||||
"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770"
|
||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
|
|
@ -18,6 +18,9 @@ base64 = "0.10"
|
|||
log = "0.4"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
pathdiff = "0.1.0"
|
||||
proc-macro2 = "1.0.1"
|
||||
syn = { version = "*", features = ["full"] }
|
||||
quote = "1.0.2"
|
||||
|
||||
[dev-dependencies]
|
||||
rand = "0.7.0"
|
||||
|
|
19
fixtures/infer.rs
Normal file
19
fixtures/infer.rs
Normal file
|
@ -0,0 +1,19 @@
|
|||
use bitflags::bitflags;
|
||||
|
||||
bitflags! {
|
||||
struct Flags: u32 {
|
||||
const A = 0b00000001;
|
||||
const B = 0b00000010;
|
||||
const C = 0b00000100;
|
||||
const ABC = Self::A.bits | Self::B.bits | Self::C.bits;
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let e1 = Flags::A | Flags::C;
|
||||
let e2 = Flags::B | Flags::C;
|
||||
assert_eq!((e1 | e2), Flags::ABC); // union
|
||||
assert_eq!((e1 & e2), Flags::C); // intersection
|
||||
assert_eq!((e1 - e2), Flags::A); // set difference
|
||||
assert_eq!(!e2, Flags::A); // set complement
|
||||
}
|
|
@ -18,6 +18,9 @@ pub enum CargoPlayError {
|
|||
#[fail(display = "Path already exists at {:?}", _0)]
|
||||
PathExistError(std::path::PathBuf),
|
||||
|
||||
#[fail(display = "Failed to parse source code: {:?}", _0)]
|
||||
RustParseError(syn::Error),
|
||||
|
||||
/// Helper error kind only exists for development purpose.
|
||||
#[fail(display = "{:?}", _0)]
|
||||
_Message(String),
|
||||
|
@ -29,6 +32,12 @@ impl From<std::io::Error> for CargoPlayError {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<syn::Error> for CargoPlayError {
|
||||
fn from(value: syn::Error) -> Self {
|
||||
CargoPlayError::RustParseError(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl CargoPlayError {
|
||||
pub fn from_serde<T: Debug>(value: T) -> Self {
|
||||
CargoPlayError::ParseError(format!("{:?}", value))
|
||||
|
|
58
src/infer.rs
Normal file
58
src/infer.rs
Normal file
|
@ -0,0 +1,58 @@
|
|||
use std::collections::HashSet;
|
||||
use std::fs;
|
||||
use std::iter;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use proc_macro2::{Ident, TokenStream, TokenTree};
|
||||
use quote::ToTokens;
|
||||
|
||||
use crate::errors::CargoPlayError;
|
||||
|
||||
const USE_KEYWORDS: &'static [&'static str] = &["std", "core", "crate", "self", "alloc", "super"];
|
||||
|
||||
fn extra_use<'a, T: 'a + IntoIterator<Item = TokenTree> + Clone>(
|
||||
input: T,
|
||||
) -> Box<dyn Iterator<Item = Ident> + 'a> {
|
||||
use proc_macro2::Literal;
|
||||
use TokenTree as tt;
|
||||
|
||||
Box::new(
|
||||
input
|
||||
.clone()
|
||||
.into_iter()
|
||||
.zip(
|
||||
input
|
||||
.into_iter()
|
||||
.skip(1)
|
||||
.chain(iter::once(Literal::u8_suffixed(1u8).into())),
|
||||
)
|
||||
.flat_map(|(prev, current)| match (prev, current) {
|
||||
(tt::Ident(ref first), tt::Ident(ref second)) if first.to_string() == "use" => {
|
||||
Box::new(iter::once(second.clone()))
|
||||
}
|
||||
(tt::Group(ref group), _) => extra_use(group.stream()),
|
||||
_ => Box::new(iter::empty()),
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn analyze_sources(sources: &Vec<PathBuf>) -> Result<HashSet<String>, CargoPlayError> {
|
||||
let contents: Vec<_> = sources
|
||||
.into_iter()
|
||||
.map(fs::read_to_string)
|
||||
.collect::<Result<_, _>>()?;
|
||||
|
||||
let streams: Vec<TokenStream> = contents
|
||||
.into_iter()
|
||||
.map(|file| -> Result<_, CargoPlayError> {
|
||||
Ok(syn::parse_file(&file)?.into_token_stream())
|
||||
})
|
||||
.collect::<Result<_, CargoPlayError>>()?;
|
||||
|
||||
Ok(streams
|
||||
.into_iter()
|
||||
.flat_map(|token| extra_use(token.into_iter()))
|
||||
.map(|ident| ident.to_string())
|
||||
.filter(|ident| !USE_KEYWORDS.contains(&ident.as_ref()))
|
||||
.collect())
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
mod cargo;
|
||||
mod errors;
|
||||
mod infer;
|
||||
pub mod opt;
|
||||
pub mod steps;
|
||||
|
|
11
src/main.rs
11
src/main.rs
|
@ -1,5 +1,6 @@
|
|||
mod cargo;
|
||||
mod errors;
|
||||
mod infer;
|
||||
mod opt;
|
||||
mod steps;
|
||||
|
||||
|
@ -44,7 +45,15 @@ fn main() -> Result<(), CargoPlayError> {
|
|||
}
|
||||
|
||||
let files = parse_inputs(&opt.src)?;
|
||||
let dependencies = extract_headers(&files);
|
||||
let mut dependencies = extract_headers(&files);
|
||||
|
||||
if opt.infer {
|
||||
let mut infers = infer::analyze_sources(&opt.src)?
|
||||
.into_iter()
|
||||
.map(|crat| format!("{} = \"*\"", crat))
|
||||
.collect();
|
||||
dependencies.append(&mut infers);
|
||||
}
|
||||
|
||||
if opt.clean {
|
||||
rmtemp(&temp);
|
||||
|
|
|
@ -80,6 +80,9 @@ pub struct Opt {
|
|||
#[structopt(long = "save")]
|
||||
/// Generate a Cargo project based on inputs
|
||||
pub save: Option<PathBuf>,
|
||||
/// [experimental] Automatically infers dependency
|
||||
#[structopt(long = "infer", short = "i")]
|
||||
pub infer: bool,
|
||||
#[structopt(multiple = true, last = true)]
|
||||
/// Arguments passed to the underlying program
|
||||
pub args: Vec<String>,
|
||||
|
|
|
@ -209,3 +209,12 @@ fn external_crate() -> Result<()> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_infer() -> Result<()> {
|
||||
let rt = TestRuntime::new()?;
|
||||
let output = rt.run(&["--infer", "fixtures/infer.rs"])?;
|
||||
assert_eq!(output.status.code().unwrap(), 0);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue