This commit is contained in:
nora 2022-10-06 22:02:08 +02:00
parent e674120d26
commit 7fd4516494
No known key found for this signature in database
3 changed files with 56 additions and 7 deletions

1
Cargo.lock generated
View file

@ -153,6 +153,7 @@ dependencies = [
"cargo", "cargo",
"prettyplease", "prettyplease",
"proc-macro2", "proc-macro2",
"quote",
"syn", "syn",
] ]

View file

@ -13,4 +13,5 @@ anyhow = "1.0.65"
cargo = "0.65.0" cargo = "0.65.0"
prettyplease = "0.1.19" prettyplease = "0.1.19"
proc-macro2 = "1.0.46" proc-macro2 = "1.0.46"
syn = { version = "1.0.101", features = ["full"] } quote = "1.0.21"
syn = { version = "1.0.101", features = ["full", "visit", "visit-mut"] }

View file

@ -8,7 +8,8 @@ use cargo::{
ops::{self, CompileOptions}, ops::{self, CompileOptions},
util::{command_prelude::CompileMode, Config}, util::{command_prelude::CompileMode, Config},
}; };
use std::{ops::Not, path::Path, process::Command}; use std::{collections::HashMap, ops::Not, path::Path, process::Command};
use syn::{visit_mut::VisitMut, File, Item, ItemMod, 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
@ -37,6 +38,12 @@ fn cargo_expand(cargo_dir: &TargetSourcePath) -> Result<syn::File> {
Ok(root) Ok(root)
} }
struct Crate {
file: syn::File,
name: String,
deps: Vec<String>,
}
struct DepExpander<'ws, 'cfg> { struct DepExpander<'ws, 'cfg> {
bcx: BuildContext<'ws, 'cfg>, bcx: BuildContext<'ws, 'cfg>,
} }
@ -49,13 +56,17 @@ impl<'ws, 'cfg> DepExpander<'ws, 'cfg> {
.context("unit source path not found") .context("unit source path not found")
} }
fn expand(&self) -> Result<syn::File> { fn crates(&self) -> Vec<Crate> {
todo!()
}
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")?;
self.expand_recursively(unit) self.expand_recursively(unit)
.context(format!("expanding {} crate", unit.target.crate_name())) .context(format!("expanding {} crate", unit.target.crate_name()))
} }
fn expand_recursively(&self, unit: &Unit) -> Result<syn::File> { fn expand_recursively(&self, unit: &Unit) -> Result<File> {
let mut ast = cargo_expand(unit.target.src_path()).context("expanding unit")?; let mut ast = cargo_expand(unit.target.src_path()).context("expanding unit")?;
let deps = self let deps = self
@ -73,7 +84,7 @@ impl<'ws, 'cfg> DepExpander<'ws, 'cfg> {
let name = proc_macro2::Ident::new(&crate_name, proc_macro2::Span::call_site()); let name = proc_macro2::Ident::new(&crate_name, proc_macro2::Span::call_site());
let module = syn::ItemMod { let mut module = ItemMod {
attrs: file.attrs, attrs: file.attrs,
vis: syn::Visibility::Inherited, vis: syn::Visibility::Inherited,
mod_token: Default::default(), mod_token: Default::default(),
@ -82,6 +93,8 @@ impl<'ws, 'cfg> DepExpander<'ws, 'cfg> {
semi: None, semi: None,
}; };
clean_dep_mod(&mut module);
ast.items.push(syn::Item::Mod(module)); ast.items.push(syn::Item::Mod(module));
} }
@ -90,7 +103,7 @@ impl<'ws, 'cfg> DepExpander<'ws, 'cfg> {
} }
/// Expands the crate in `cargo_dir` into a single file without dependencies /// Expands the crate in `cargo_dir` into a single file without dependencies
pub fn expand(cargo_dir: &Path) -> Result<syn::File> { pub fn expand(cargo_dir: &Path) -> Result<File> {
let cargo_dir = cargo_dir.canonicalize().context("could not find path")?; let cargo_dir = cargo_dir.canonicalize().context("could not find path")?;
let manifest_path = cargo_dir.join("Cargo.toml"); let manifest_path = cargo_dir.join("Cargo.toml");
@ -102,7 +115,41 @@ pub fn expand(cargo_dir: &Path) -> Result<syn::File> {
let expander = DepExpander { bcx }; let expander = DepExpander { bcx };
let root = expander.expand()?; let mut root = expander.expand()?;
clean_final_code(&mut root);
Ok(root) Ok(root)
} }
fn clean_dep_mod(module: &mut ItemMod) {
module
.content
.as_mut()
.unwrap()
.1
.retain(|item| !matches!(item, Item::ExternCrate(_)));
module.attrs.retain(
|attr| match attr.path.segments[0].ident.to_string().as_ref() {
"no_std" | "feature" => false,
_ => true,
},
)
}
fn clean_final_code(file: &mut File) {
MakePubCrateVisitor.visit_file_mut(file)
}
struct MakePubCrateVisitor;
impl VisitMut for MakePubCrateVisitor {
fn visit_visibility_mut(&mut self, vis: &mut Visibility) {
if let Visibility::Public(_) = vis {
let pub_crate = syn::parse2(quote::quote! { pub(crate) }).unwrap();
*vis = pub_crate;
}
}
}