mirror of
https://github.com/Noratrieb/cargo-minimize.git
synced 2026-01-14 16:35:01 +01:00
better expansion
This commit is contained in:
parent
f5e8a3d51e
commit
958383f991
3 changed files with 84 additions and 58 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -1,2 +1,5 @@
|
||||||
target
|
target
|
||||||
expanded.rs
|
/expanded.rs
|
||||||
|
/expanded
|
||||||
|
/invalid.rs
|
||||||
|
/invalid
|
||||||
135
src/expand.rs
135
src/expand.rs
|
|
@ -9,7 +9,7 @@ use cargo::{
|
||||||
util::{command_prelude::CompileMode, Config},
|
util::{command_prelude::CompileMode, Config},
|
||||||
};
|
};
|
||||||
use std::{collections::BTreeSet, fmt::Debug, ops::Not, path::Path, process::Command};
|
use std::{collections::BTreeSet, fmt::Debug, ops::Not, path::Path, process::Command};
|
||||||
use syn::{visit_mut::VisitMut, File, Item, ItemMod, Visibility};
|
use syn::{visit_mut::VisitMut, File, Item, ItemExternCrate, ItemMod, ItemUse, Visibility};
|
||||||
|
|
||||||
fn cargo_expand(cargo_dir: &TargetSourcePath) -> Result<syn::File> {
|
fn cargo_expand(cargo_dir: &TargetSourcePath) -> Result<syn::File> {
|
||||||
let cargo_dir = cargo_dir
|
let cargo_dir = cargo_dir
|
||||||
|
|
@ -22,6 +22,12 @@ fn cargo_expand(cargo_dir: &TargetSourcePath) -> Result<syn::File> {
|
||||||
|
|
||||||
cmd.current_dir(cargo_dir).arg("expand");
|
cmd.current_dir(cargo_dir).arg("expand");
|
||||||
|
|
||||||
|
if let Some(lib) = std::env::args().nth(2) {
|
||||||
|
if lib == "lib" {
|
||||||
|
cmd.arg("--lib");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let output = cmd.output().context(format!(
|
let output = cmd.output().context(format!(
|
||||||
"spawning cargo with target path {}",
|
"spawning cargo with target path {}",
|
||||||
cargo_dir.display()
|
cargo_dir.display()
|
||||||
|
|
@ -33,14 +39,25 @@ fn cargo_expand(cargo_dir: &TargetSourcePath) -> Result<syn::File> {
|
||||||
|
|
||||||
let src = String::from_utf8(output.stdout).context("stdout utf8")?;
|
let src = String::from_utf8(output.stdout).context("stdout utf8")?;
|
||||||
|
|
||||||
let root = syn::parse_str(&src).context("parsing crate")?;
|
let root = match syn::parse_str(&src) {
|
||||||
|
Ok(root) => root,
|
||||||
|
Err(err) => {
|
||||||
|
let name = "invalid.rs";
|
||||||
|
|
||||||
|
std::fs::write(name, src).context("write debug file")?;
|
||||||
|
Err(err).context(format!(
|
||||||
|
"failed to parse, debug file with the contents at `{name}`"
|
||||||
|
))?;
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Ok(root)
|
Ok(root)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Crate {
|
struct Crate {
|
||||||
name: String,
|
name: String,
|
||||||
file: syn::File,
|
ast: syn::File,
|
||||||
deps: Vec<String>,
|
deps: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,8 +102,19 @@ impl<'ws, 'cfg> DepExpander<'ws, 'cfg> {
|
||||||
.context("unit source path not found")
|
.context("unit source path not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn crates(&self, unit: &Unit, set: &mut BTreeSet<Crate>) -> Result<()> {
|
fn dep_crates(&self, unit: &Unit, set: &mut BTreeSet<Crate>) -> Result<()> {
|
||||||
let ast = cargo_expand(unit.target.src_path()).context("expanding unit")?;
|
let krate = self.crates(unit, set)?;
|
||||||
|
set.insert(krate);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds all dependencies to `set` and returns itself
|
||||||
|
fn crates(&self, unit: &Unit, set: &mut BTreeSet<Crate>) -> Result<Crate> {
|
||||||
|
let name = unit.target.crate_name();
|
||||||
|
|
||||||
|
let ast =
|
||||||
|
cargo_expand(unit.target.src_path()).context(format!("expanding crate `{}`", name))?;
|
||||||
|
|
||||||
let deps = self
|
let deps = self
|
||||||
.bcx
|
.bcx
|
||||||
|
|
@ -100,64 +128,48 @@ impl<'ws, 'cfg> DepExpander<'ws, 'cfg> {
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let krate = Crate {
|
let krate = Crate {
|
||||||
file: ast,
|
ast,
|
||||||
name: unit.target.crate_name(),
|
name,
|
||||||
deps: dep_names,
|
deps: dep_names,
|
||||||
};
|
};
|
||||||
|
|
||||||
set.insert(krate);
|
|
||||||
|
|
||||||
for dep in deps {
|
for dep in deps {
|
||||||
self.crates(&dep.unit, set)?;
|
self.dep_crates(&dep.unit, set)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(krate)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand(&self) -> Result<File> {
|
fn expand(&self) -> Result<File> {
|
||||||
let unit = self.bcx.roots.get(0).context("root unit not found")?;
|
let unit = self.bcx.roots.get(0).context("root unit not found")?;
|
||||||
|
|
||||||
let mut crates = BTreeSet::new();
|
let mut crates = BTreeSet::new();
|
||||||
self.crates(unit, &mut crates).context("get crate list")?;
|
let mut root = self.crates(unit, &mut crates).context("get crate list")?;
|
||||||
println!("{crates:?}");
|
|
||||||
|
|
||||||
self.expand_recursively(unit)
|
for krate in crates {
|
||||||
.context(format!("expanding {} crate", unit.target.crate_name()))
|
self.expand_crate(krate, &mut root.ast);
|
||||||
}
|
|
||||||
|
|
||||||
fn expand_recursively(&self, unit: &Unit) -> Result<File> {
|
|
||||||
let mut ast = cargo_expand(unit.target.src_path()).context("expanding unit")?;
|
|
||||||
|
|
||||||
let deps = self
|
|
||||||
.bcx
|
|
||||||
.unit_graph
|
|
||||||
.get(unit)
|
|
||||||
.context("dependencies not found for crate")?;
|
|
||||||
|
|
||||||
for dep in deps {
|
|
||||||
let crate_name = dep.unit.target.crate_name();
|
|
||||||
|
|
||||||
let file = self
|
|
||||||
.expand_recursively(&dep.unit)
|
|
||||||
.context(format!("expanding {crate_name} crate"))?;
|
|
||||||
|
|
||||||
let name = proc_macro2::Ident::new(&crate_name, proc_macro2::Span::call_site());
|
|
||||||
|
|
||||||
let mut module = ItemMod {
|
|
||||||
attrs: file.attrs,
|
|
||||||
vis: syn::Visibility::Inherited,
|
|
||||||
mod_token: Default::default(),
|
|
||||||
ident: name,
|
|
||||||
content: Some((Default::default(), file.items)),
|
|
||||||
semi: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
clean_dep_mod(&mut module);
|
|
||||||
|
|
||||||
ast.items.push(syn::Item::Mod(module));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ast)
|
Ok(root.ast)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expand_crate(&self, krate: Crate, root: &mut syn::File) {
|
||||||
|
let crate_name = krate.name;
|
||||||
|
let file = krate.ast;
|
||||||
|
let name = proc_macro2::Ident::new(&crate_name, proc_macro2::Span::call_site());
|
||||||
|
|
||||||
|
let mut module = ItemMod {
|
||||||
|
attrs: file.attrs,
|
||||||
|
vis: syn::Visibility::Inherited,
|
||||||
|
mod_token: Default::default(),
|
||||||
|
ident: name,
|
||||||
|
content: Some((Default::default(), file.items)),
|
||||||
|
semi: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
clean_dep_mod(&mut module);
|
||||||
|
|
||||||
|
root.items.push(syn::Item::Mod(module));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -182,23 +194,23 @@ pub fn expand(cargo_dir: &Path) -> Result<File> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clean_dep_mod(module: &mut ItemMod) {
|
fn clean_dep_mod(module: &mut ItemMod) {
|
||||||
module
|
let items = &mut module.content.as_mut().unwrap().1;
|
||||||
.content
|
|
||||||
.as_mut()
|
items.retain(|item| !matches!(item, Item::ExternCrate(_)));
|
||||||
.unwrap()
|
clean_items_general(items);
|
||||||
.1
|
|
||||||
.retain(|item| !matches!(item, Item::ExternCrate(_)));
|
|
||||||
|
|
||||||
module.attrs.retain(
|
module.attrs.retain(
|
||||||
|attr| match attr.path.segments[0].ident.to_string().as_ref() {
|
|attr| match attr.path.segments[0].ident.to_string().as_ref() {
|
||||||
"no_std" | "feature" => false,
|
"no_std" | "feature" => false,
|
||||||
_ => true,
|
_ => true,
|
||||||
},
|
},
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clean_final_code(file: &mut File) {
|
fn clean_final_code(file: &mut File) {
|
||||||
MakePubCrateVisitor.visit_file_mut(file)
|
clean_items_general(&mut file.items);
|
||||||
|
|
||||||
|
MakePubCrateVisitor.visit_file_mut(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MakePubCrateVisitor;
|
struct MakePubCrateVisitor;
|
||||||
|
|
@ -212,3 +224,14 @@ impl VisitMut for MakePubCrateVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn clean_items_general(items: &mut Vec<Item>) {
|
||||||
|
items.retain(|item| match item {
|
||||||
|
Item::ExternCrate(ItemExternCrate { ident, .. }) if ident.to_string() == "std" => false,
|
||||||
|
Item::Use(ItemUse { attrs, .. }) => attrs
|
||||||
|
.get(0)
|
||||||
|
.map(|attr| attr.path.segments[0].ident.to_string() != "prelude_import")
|
||||||
|
.unwrap_or(true),
|
||||||
|
_ => true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use is_even::IsEven;
|
use is_even::IsEven;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("{}", 4.is_even());
|
4.is_even();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue