diff --git a/Cargo.lock b/Cargo.lock index 92d1ee3..70a4e44 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -72,6 +72,7 @@ version = "0.1.0" dependencies = [ "bitflags", "bok-macro", + "macro_magic", "paste", "proc-macro2", "quote", @@ -84,6 +85,7 @@ dependencies = [ name = "bok-macro" version = "0.1.0" dependencies = [ + "macro_magic", "proc-macro2", "quote", "syn", @@ -96,6 +98,7 @@ dependencies = [ "bok", "bok-macro", "clap", + "macro_magic", "prettyplease", "proc-macro2", "quote", @@ -103,6 +106,12 @@ dependencies = [ "syn", ] +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "clap" version = "4.5.20" @@ -151,6 +160,26 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom", + "once_cell", + "tiny-keccak", +] + [[package]] name = "cpufeatures" version = "0.2.14" @@ -160,6 +189,12 @@ dependencies = [ "libc", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-common" version = "0.1.6" @@ -170,6 +205,17 @@ dependencies = [ "typenum", ] +[[package]] +name = "derive-syn-parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "digest" version = "0.10.7" @@ -190,6 +236,17 @@ dependencies = [ "version_check", ] +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "heck" version = "0.5.0" @@ -217,6 +274,60 @@ version = "0.2.162" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" +[[package]] +name = "macro_magic" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc33f9f0351468d26fbc53d9ce00a096c8522ecb42f19b50f34f2c422f76d21d" +dependencies = [ + "macro_magic_core", + "macro_magic_macros", + "quote", + "syn", +] + +[[package]] +name = "macro_magic_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1687dc887e42f352865a393acae7cf79d98fab6351cde1f58e9e057da89bf150" +dependencies = [ + "const-random", + "derive-syn-parse", + "macro_magic_core_macros", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "macro_magic_core_macros" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b02abfe41815b5bd98dbd4260173db2c116dda171dc0fe7838cb206333b83308" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "macro_magic_macros" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ea28ee64b88876bf45277ed9a5817c1817df061a74f2b988971a12570e5869" +dependencies = [ + "macro_magic_core", + "quote", + "syn", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + [[package]] name = "paste" version = "1.0.15" @@ -304,6 +415,15 @@ dependencies = [ "syn", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "typenum" version = "1.17.0" @@ -340,6 +460,12 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "windows-sys" version = "0.59.0" diff --git a/bok-macro/Cargo.toml b/bok-macro/Cargo.toml index 6f9c2d1..a7d7dbb 100644 --- a/bok-macro/Cargo.toml +++ b/bok-macro/Cargo.toml @@ -16,3 +16,4 @@ proc-macro = true syn = { version = "2.0", features = [ "full" ] } quote = { version = "1.0" } proc-macro2 = "1.0" +macro_magic = { version = "0.5", features = [ "proc_support" ] } diff --git a/bok-macro/src/lib.rs b/bok-macro/src/lib.rs index e135deb..5c90283 100644 --- a/bok-macro/src/lib.rs +++ b/bok-macro/src/lib.rs @@ -17,38 +17,59 @@ use ::proc_macro::TokenStream; use ::quote::quote; -use ::syn::{parse::Parser, parse_macro_input, DeriveInput}; +use ::syn::{ + parse::Parser, parse_macro_input, DeriveInput, Fields, ItemStruct, +}; /// Use as #[::bok::repository(MyBaseRepo)] /// Will setup a `base` field that is the given base repo /// and add `#[derive(::bok::Repository)]` /// /// e.g.: `#[::bok::repository(::bok::RepositoryEmpty)]` +#[::macro_magic::import_tokens_attr] #[proc_macro_attribute] pub fn repository(attrs: TokenStream, input: TokenStream) -> TokenStream { - let mut ast = parse_macro_input!(input as DeriveInput); - match &mut ast.data { - syn::Data::Struct(ref mut struct_data) => { - match &mut struct_data.fields { - syn::Fields::Named(fields) => { - let base = proc_macro2::TokenStream::from(attrs); - fields.named.push( - syn::Field::parse_named - .parse2(quote! { base: #base }) - .unwrap(), - ); - } - _ => (), - } + let base = parse_macro_input!(attrs as ItemStruct); + let local = parse_macro_input!(input as ItemStruct); - quote! { - #[derive(::bok::Repository, Debug)] - #ast - } - .into() + let Fields::Named(local_fields) = local.fields else { + use ::syn::spanned::Spanned; + return ::syn::Error::new( + local.fields.span(), + "unnamed fields are not supported", + ) + .to_compile_error() + .into(); + }; + + let Fields::Named(base_fields) = base.fields else { + use ::syn::spanned::Spanned; + return ::syn::Error::new( + base.fields.span(), + "unnamed fields are not supported", + ) + .to_compile_error() + .into(); + }; + let local_fields_it = local_fields.named.iter(); + let base_fields_extra = base_fields.named.iter(); + let attrs = local.attrs; + let generics = local.generics; + let ident = local.ident; + let vis = local.vis; + quote! { + #(#attrs) + * + #[::macro_magic::export_tokens] + #[derive(::bok::Repository, Debug)] + #vis struct #ident<#generics> { + #(#base_fields_extra), + * + #(#local_fields_it), + * } - _ => panic!("`repository` has to be used with a struct"), } + .into() } /// Unless you know what you are doing, use `#[::bok::repository(MyBaseRepo)]` @@ -67,28 +88,6 @@ pub fn derive_repository(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); let name = input.ident.clone(); - let elements = match input.data { - ::syn::Data::Struct(s) => match s.fields { - syn::Fields::Named(n) => n.named, - _ => panic!("only named supported"), - }, - _ => panic!("`Repository` has to be used on a struct"), - }; - let base_type = elements - .iter() - .find_map(|field| { - if let Some(field_name) = &field.ident { - if field_name != "base" { - None - } else { - let t = &field.ty; - Some(quote! {#t}) - } - } else { - None - } - }) - .expect("can't find base value. Add #[repository] to your struct"); let expanded = quote! { impl ::bok::Repository for #name { @@ -99,12 +98,6 @@ pub fn derive_repository(input: TokenStream) -> TokenStream { (module_path!().to_owned() + "::" + ::std::stringify!(#name)).as_str().into() } } - impl ::std::ops::Deref for #name { - type Target = #base_type; - fn deref(&self) -> &#base_type { - &self.base - } - } }; TokenStream::from(expanded) diff --git a/bok-utils/Cargo.toml b/bok-utils/Cargo.toml index 20bc2fb..bad462d 100644 --- a/bok-utils/Cargo.toml +++ b/bok-utils/Cargo.toml @@ -13,8 +13,9 @@ categories = [ "config" ] clap = { version = "4.5", features = [ "derive", "unicode" ]} bok = { path = "../bok" } bok-macro = { path = "../bok-macro" } +macro_magic = { version = "0.5" } +prettyplease = "0.2" proc-macro2 = "1.0" quote = "1.0" -prettyplease = "0.2" syn = { version = "2", features = [ "full", "parsing" ] } sha3 = { version = "0.10" } diff --git a/bok-utils/src/main.rs b/bok-utils/src/main.rs index 244fd74..770858b 100644 --- a/bok-utils/src/main.rs +++ b/bok-utils/src/main.rs @@ -43,7 +43,7 @@ fn main() { println!("pkgs1: {}", pkgs1.name()); println!("pkgs2: {}", pkgs2.name()); - let mut pb: pkgs::one::OneBuilder = pkgs1.one_builder(); + let mut pb: pkgs::one::OneBuilder = pkgs1.one(); let b = pb.as_builder(); let a = pb.as_any_mut(); @@ -58,7 +58,8 @@ fn main() { println!("hash one code: {}", pkg.hash_code()); } - println!("pkgs1 - 1:{}", pkgs1.one().my_attr); + /* + println!("pkgs1 - 1:{}", pkgs1.one().default_unused().build().my_attr); println!("pkgs1 - 2:{}", pkgs1.two().my_attr); println!("pkgs2 - 1:{}", pkgs2.one().my_attr); println!("pkgs2 - 2:{}", pkgs2.two().my_attr); @@ -67,4 +68,5 @@ fn main() { println!("pkgs2-1:\n{}", pkgs2.one()); println!("pkgs2-2:\n{}", pkgs2.two()); println!("pkgs2-3:\n{}", pkgs2.three()); + */ } diff --git a/bok-utils/src/pkgs/mod.rs b/bok-utils/src/pkgs/mod.rs index 2bf432b..f98efda 100644 --- a/bok-utils/src/pkgs/mod.rs +++ b/bok-utils/src/pkgs/mod.rs @@ -20,7 +20,8 @@ //! extends ancd changes another // Export multiple packages in this module -bok::moduse! { +use ::bok::repository; +::bok::moduse! { one, two, three, @@ -28,7 +29,7 @@ bok::moduse! { /// /// Base repository with some packages -#[::bok_macro::repository(::bok::RepositoryEmpty)] +#[::bok::repository(::bok::RepositoryEmpty)] #[derive(::std::default::Default)] pub struct Pkgs1 {} @@ -43,7 +44,7 @@ bok::repo_packages! { /// /// This repository extends and changes Pkgs1 -#[::bok_macro::repository(Pkgs1)] +#[::bok::repository(Pkgs1)] #[derive(::std::default::Default)] pub struct Pkgs2 {} diff --git a/bok/Cargo.toml b/bok/Cargo.toml index 9f46424..11b3280 100644 --- a/bok/Cargo.toml +++ b/bok/Cargo.toml @@ -16,6 +16,7 @@ publish = false [dependencies] bitflags = "2.4" bok-macro = { path="../bok-macro" } +macro_magic = { version = "0.5" } paste = "1.0" proc-macro2 = "1.0" quote = "1.0" diff --git a/bok/src/lib.rs b/bok/src/lib.rs index 1a7bd06..f0f84e7 100644 --- a/bok/src/lib.rs +++ b/bok/src/lib.rs @@ -80,10 +80,7 @@ macro_rules! packages { ($($name:ident,)*) => { $crate::paste::paste! { $( - pub fn [<$name:snake>] (&self) -> $name { - $name::default() - } - pub fn [<$name:snake _builder>] (&self) -> [<$name Builder>] { + pub fn [<$name:snake>] (&self) -> [<$name Builder>] { $name::builder() } )* @@ -98,8 +95,11 @@ pub trait Repository: ::core::fmt::Debug { } /// This is an empty Package List. +#[::macro_magic::export_tokens] #[derive(::std::default::Default, Debug)] -pub struct RepositoryEmpty {} +pub struct RepositoryEmpty { + test: i32, +} impl Repository for RepositoryEmpty { fn name(&self) -> RepoName { "RepositoryEmpty".into()