Package: remove .base/defer, copy with macro
Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
This commit is contained in:
parent
96ac418e2f
commit
a5722bff5c
@ -15,6 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#![feature(proc_macro_span)]
|
||||||
use ::proc_macro::TokenStream;
|
use ::proc_macro::TokenStream;
|
||||||
|
|
||||||
mod pkgs;
|
mod pkgs;
|
||||||
@ -103,17 +104,19 @@ pub fn pkg_fn_to_code(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
/// #[::bok::package(::bok::PkgEmpty)]
|
/// #[::bok::package(::bok::PkgEmpty)]
|
||||||
/// pub struct MyPkg {}
|
/// pub struct MyPkg {}
|
||||||
/// ```
|
/// ```
|
||||||
|
#[::macro_magic::import_tokens_attr]
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn package(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
pub fn package(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
crate::pkgs::package(attrs, input)
|
crate::pkgs::package(attrs, input, __source_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Use as #[::bok::impl_package]
|
/// Use as #[::bok::package_impl]
|
||||||
/// Will include basic macros on functions and .base() method
|
/// will add `#[::bok::package_impl_base(..)]` with proper arguments
|
||||||
|
/// and export the resulting symbols
|
||||||
///
|
///
|
||||||
/// e.g.:
|
/// e.g.:
|
||||||
/// ```
|
/// ```
|
||||||
/// #[::bok::impl_package]
|
/// #[::bok::package_impl]
|
||||||
/// impl ::bok::Pkg for MyPackage {
|
/// impl ::bok::Pkg for MyPackage {
|
||||||
/// fn build(&self) -> Result<(),()> {
|
/// fn build(&self) -> Result<(),()> {
|
||||||
/// ...
|
/// ...
|
||||||
@ -121,8 +124,40 @@ pub fn package(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn impl_package(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
pub fn package_impl(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
crate::pkgs::impl_package(attrs, input)
|
crate::pkgs::package_impl(attrs, input)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Internal, **don't use unless you know what you are doing.**
|
||||||
|
/// Use as #[::bok::package_impl_base(::my::Package)]
|
||||||
|
/// implements common ::bok::Pkg methods and takes the package methods
|
||||||
|
/// not implemented by the user from the base package
|
||||||
|
///
|
||||||
|
/// does not export symbols.
|
||||||
|
///
|
||||||
|
/// should be called with the same path as the package that implements
|
||||||
|
/// ::bok::Pkg
|
||||||
|
///
|
||||||
|
/// will rewrite itself with the exported impl path of the base package
|
||||||
|
/// so that macro_magic can import the base impl
|
||||||
|
///
|
||||||
|
/// e.g.:
|
||||||
|
/// ```
|
||||||
|
/// #[::bok::package_impl_base(MyPackage)]
|
||||||
|
/// #[::macro_magic::export_tokens(bok_pkg_mypackage)]
|
||||||
|
/// impl ::bok::Pkg for MyPackage {
|
||||||
|
/// fn build(&self) -> Result<(),()> {
|
||||||
|
/// ...
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[::macro_magic::import_tokens_attr]
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn package_impl_base(
|
||||||
|
attrs: TokenStream,
|
||||||
|
input: TokenStream,
|
||||||
|
) -> TokenStream {
|
||||||
|
crate::pkgs::package_impl_base(attrs, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unless you know what you are doing, use `#[::bok::package(MyBasePackage)]`
|
/// Unless you know what you are doing, use `#[::bok::package(MyBasePackage)]`
|
||||||
|
@ -18,33 +18,20 @@
|
|||||||
use ::proc_macro::TokenStream;
|
use ::proc_macro::TokenStream;
|
||||||
use ::quote::quote;
|
use ::quote::quote;
|
||||||
use ::syn::{parse::Parser, parse_macro_input, DeriveInput};
|
use ::syn::{parse::Parser, parse_macro_input, DeriveInput};
|
||||||
|
use syn::{parse_quote, spanned::Spanned};
|
||||||
|
|
||||||
pub(crate) fn pkg_fn_to_code(
|
pub(crate) fn pkg_fn_to_code(
|
||||||
_attrs: TokenStream,
|
_attrs: TokenStream,
|
||||||
input: TokenStream,
|
input: TokenStream,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let mut ast_orig: ::syn::ItemFn =
|
let ast_orig: ::syn::ItemFn = parse_macro_input!(input as ::syn::ItemFn);
|
||||||
parse_macro_input!(input as ::syn::ItemFn);
|
|
||||||
|
|
||||||
let mut ast_new = ast_orig.clone();
|
let mut ast_new = ast_orig.clone();
|
||||||
ast_new.block = ast_orig.block.clone();
|
|
||||||
|
|
||||||
// Add a prefix and suffix statement
|
let new_fn_name = quote::format_ident!("{}_code", ast_orig.sig.ident);
|
||||||
// where we declare and return the result
|
ast_new.sig.ident = quote::format_ident!("{}_code", new_fn_name);
|
||||||
let prefix_ret: ::syn::Stmt = ::syn::parse_quote! {
|
|
||||||
let mut ret : ::core::result::Result<(),()> = ::core::result::Result::Err(());
|
|
||||||
};
|
|
||||||
let suffix_ret: ::syn::Stmt = ::syn::parse_quote! {
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
ast_orig.block.stmts.insert(0, prefix_ret);
|
|
||||||
ast_orig.block.stmts.push(suffix_ret);
|
|
||||||
|
|
||||||
let new_fn_name =
|
|
||||||
quote::format_ident!("{}", ast_orig.sig.ident.to_string() + "_code");
|
|
||||||
ast_new.sig.ident = quote::format_ident!("{}", new_fn_name);
|
|
||||||
use ::quote::ToTokens;
|
use ::quote::ToTokens;
|
||||||
let fn_block = ast_new.block.to_token_stream();
|
let fn_block = ast_orig.block.to_token_stream();
|
||||||
|
|
||||||
let asdf = quote! {
|
let asdf = quote! {
|
||||||
#ast_orig
|
#ast_orig
|
||||||
@ -56,50 +43,327 @@ pub(crate) fn pkg_fn_to_code(
|
|||||||
asdf.into()
|
asdf.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn package(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
pub(crate) fn package(
|
||||||
let mut ast = parse_macro_input!(input as DeriveInput);
|
attrs: TokenStream,
|
||||||
match &mut ast.data {
|
input: TokenStream,
|
||||||
syn::Data::Struct(ref mut struct_data) => {
|
__source_path: TokenStream,
|
||||||
match &mut struct_data.fields {
|
) -> TokenStream {
|
||||||
syn::Fields::Named(fields) => {
|
use ::syn::{spanned::Spanned, Fields, ItemStruct};
|
||||||
let base = proc_macro2::TokenStream::from(attrs);
|
let local = parse_macro_input!(input as ItemStruct);
|
||||||
fields.named.push(
|
let local_span = local.span();
|
||||||
syn::Field::parse_named
|
let Fields::Named(local_fields) = local.fields else {
|
||||||
.parse2(quote! { base: #base })
|
use ::syn::spanned::Spanned;
|
||||||
.unwrap(),
|
return ::syn::Error::new(
|
||||||
);
|
local.fields.span(),
|
||||||
fields.named.push(
|
"unnamed fields are not supported",
|
||||||
syn::Field::parse_named
|
)
|
||||||
.parse2(quote! { version: ::bok::Version })
|
.to_compile_error()
|
||||||
.unwrap(),
|
.into();
|
||||||
);
|
};
|
||||||
|
let local_attrs = local.attrs.iter();
|
||||||
|
let generics = local.generics;
|
||||||
|
let ident = local.ident;
|
||||||
|
let vis = local.vis;
|
||||||
|
|
||||||
|
let source_path = parse_macro_input!(__source_path as ::syn::Path);
|
||||||
|
|
||||||
|
let base = parse_macro_input!(attrs as ItemStruct);
|
||||||
|
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();
|
||||||
|
};
|
||||||
|
// make sure the 'version' field is the first after the user's fields
|
||||||
|
// we will use as a separator from the other imported fields
|
||||||
|
let mut base_fields_extra = Vec::with_capacity(base.fields.len());
|
||||||
|
match base_fields.named.iter().find(|&x| match &x.ident {
|
||||||
|
Some(id_local) => id_local == "version",
|
||||||
|
_ => false,
|
||||||
|
}) {
|
||||||
|
Some(_) => {
|
||||||
|
let pkg_version = ::syn::Field::parse_named
|
||||||
|
.parse2(quote! {
|
||||||
|
version: ::bok::Version
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
let base_marker = ::syn::Field::parse_named
|
||||||
|
.parse2(quote! {
|
||||||
|
_bok_base: ::std::marker::PhantomData<#source_path>
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
base_fields_extra.push(pkg_version);
|
||||||
|
base_fields_extra.push(base_marker);
|
||||||
}
|
}
|
||||||
_ => (),
|
None => {
|
||||||
|
return ::syn::Error::new(
|
||||||
|
local_span,
|
||||||
|
"pkg: \"".to_owned()
|
||||||
|
+ &ident.to_string()
|
||||||
|
+ "\" base package \""
|
||||||
|
+ &base.ident.to_string()
|
||||||
|
+ "\" does not have 'version' field",
|
||||||
|
)
|
||||||
|
.to_compile_error()
|
||||||
|
.into();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for f in base_fields.named.iter() {
|
||||||
|
let Some(id) = &f.ident else { continue };
|
||||||
|
// don't add 'version' again
|
||||||
|
if id.to_string() == "version" || id.to_string() == "_bok_base" {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// compiler error if you try to extend a package while
|
||||||
|
// reusing its fields names
|
||||||
|
if let Some(repeated) = local_fields.named.iter().find(|&x| {
|
||||||
|
let Some(id_local) = &x.ident else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
id_local.to_string() == id.to_string()
|
||||||
|
}) {
|
||||||
|
return ::syn::Error::new(
|
||||||
|
local_span,
|
||||||
|
"pkg: \"".to_owned()
|
||||||
|
+ &ident.to_string()
|
||||||
|
+ "\" field \""
|
||||||
|
+ &repeated.ident.as_ref().unwrap().to_string()
|
||||||
|
+ "\" is already in package "
|
||||||
|
+ &base.ident.to_string()
|
||||||
|
+ "\" or its base",
|
||||||
|
)
|
||||||
|
.to_compile_error()
|
||||||
|
.into();
|
||||||
|
}
|
||||||
|
base_fields_extra.push(f.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut all_fields = Vec::new();
|
||||||
|
all_fields.extend(local_fields.named.iter());
|
||||||
|
all_fields.extend(base_fields_extra.iter());
|
||||||
quote! {
|
quote! {
|
||||||
|
#(#local_attrs)
|
||||||
|
*
|
||||||
|
#[::macro_magic::export_tokens]
|
||||||
#[derive(::bok::Package, ::std::fmt::Debug, Clone)]
|
#[derive(::bok::Package, ::std::fmt::Debug, Clone)]
|
||||||
#ast
|
#vis struct #ident<#generics> {
|
||||||
|
#(#all_fields),
|
||||||
|
*
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
_ => panic!("`package` has to be used with a struct"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn impl_package(
|
// package_impl has 3 stages, and uses macro_magic import for the last two:
|
||||||
|
// * called without parameters => add default ::bok::Pkg functions, then add the
|
||||||
|
// same macro with the package type as argument
|
||||||
|
// * called with the package type as argument => get the base type, then add the
|
||||||
|
// same macro with the base type IMPL as argument
|
||||||
|
// * called with the a package impl as argument, copy the non-implemented
|
||||||
|
// functions from the base
|
||||||
|
pub(crate) fn package_impl(
|
||||||
_attrs: TokenStream,
|
_attrs: TokenStream,
|
||||||
input: TokenStream,
|
input: TokenStream,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let mut ast = parse_macro_input!(input as ::syn::ItemImpl);
|
let ast = parse_macro_input!(input as ::syn::ItemImpl);
|
||||||
|
|
||||||
let name_pkg = match &*ast.self_ty {
|
let name_pkg = match &*ast.self_ty {
|
||||||
::syn::Type::Path(tp) => match tp.path.get_ident() {
|
::syn::Type::Path(tp) => match tp.path.get_ident() {
|
||||||
Some(id) => id.clone(),
|
Some(id) => id.clone(),
|
||||||
_ => panic!("impl_package expected path ident"),
|
_ => {
|
||||||
|
return ::syn::Error::new(
|
||||||
|
ast.span(),
|
||||||
|
"package_impl: type::Path but no ident",
|
||||||
|
)
|
||||||
|
.to_compile_error()
|
||||||
|
.into()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
_ => panic!("impl_package expected path"),
|
_ => {
|
||||||
|
return ::syn::Error::new(
|
||||||
|
ast.span(),
|
||||||
|
"package_impl: not a type::Path",
|
||||||
|
)
|
||||||
|
.to_compile_error()
|
||||||
|
.into()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
let full_path_name = proc_macro2::Ident::new(
|
||||||
|
&("_bok_pkg_".to_owned() + &name_pkg.to_string()),
|
||||||
|
proc_macro2::Span::call_site(),
|
||||||
|
);
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
use ::bok_macro::package_impl_base;
|
||||||
|
#[::bok_macro::package_impl_base(#name_pkg)]
|
||||||
|
#[::macro_magic::export_tokens(#full_path_name)]
|
||||||
|
#ast
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the actual base type and re-call the macro with the impl symbols
|
||||||
|
pub(crate) fn package_impl_base(
|
||||||
|
attrs: TokenStream,
|
||||||
|
input: TokenStream,
|
||||||
|
) -> TokenStream {
|
||||||
|
// This is a two-phase macro
|
||||||
|
// * The first time this is called the argument will be the same path as the
|
||||||
|
// struct that implements ::bok::Pkg
|
||||||
|
// * The macro will be rewritten with the base package name that is extended
|
||||||
|
// by the package
|
||||||
|
// And now that we have the proper base name we can add the missing
|
||||||
|
// methods from the base
|
||||||
|
|
||||||
|
let mut ast = parse_macro_input!(input as ::syn::ItemImpl);
|
||||||
|
let name_pkg = match &*ast.self_ty {
|
||||||
|
::syn::Type::Path(tp) => match tp.path.get_ident() {
|
||||||
|
Some(id) => id.clone(),
|
||||||
|
_ => panic!("::bok::package_impl expected path ident"),
|
||||||
|
},
|
||||||
|
_ => panic!("::bok::package_impl expected path"),
|
||||||
|
};
|
||||||
|
let Ok(syntax_tree) = syn::parse::<::syn::ItemStruct>(attrs.clone()) else {
|
||||||
|
return package_impl_base_add(attrs, &mut ast);
|
||||||
|
};
|
||||||
|
// we were passed an exported struct. first phase.
|
||||||
|
if syntax_tree.ident.to_string() != name_pkg.to_string() {
|
||||||
|
return ::syn::Error::new(
|
||||||
|
ast.span(),
|
||||||
|
"package_impl: called on \"".to_owned()
|
||||||
|
+ &name_pkg.to_string()
|
||||||
|
+ "\" with wrong initial name"
|
||||||
|
+ &syntax_tree.ident.to_string()
|
||||||
|
+ "\" ",
|
||||||
|
)
|
||||||
|
.to_compile_error()
|
||||||
|
.into();
|
||||||
|
}
|
||||||
|
// go through the struct definition, extract the base type
|
||||||
|
// from the `_bok_base` phantom data marker
|
||||||
|
let base_path = match syntax_tree.fields.iter().find(|&x| {
|
||||||
|
let Some(id) = &x.ident else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
return id.to_string() == "_bok_base";
|
||||||
|
}) {
|
||||||
|
Some(field) => match &field.ty {
|
||||||
|
::syn::Type::Path(tp) => {
|
||||||
|
if tp.path.segments.len() != 3
|
||||||
|
|| tp.path.segments[0].ident.to_string() != "std"
|
||||||
|
|| tp.path.segments[1].ident.to_string() != "marker"
|
||||||
|
|| tp.path.segments[2].ident.to_string() != "PhantomData"
|
||||||
|
{
|
||||||
|
return ::syn::Error::new(
|
||||||
|
ast.span(),
|
||||||
|
"package_impl: called on \"".to_owned()
|
||||||
|
+ &name_pkg.to_string()
|
||||||
|
+ "\" base is not PhantomData, "
|
||||||
|
+ "what are you doing?",
|
||||||
|
)
|
||||||
|
.to_compile_error()
|
||||||
|
.into();
|
||||||
|
}
|
||||||
|
let ::syn::PathArguments::AngleBracketed(psa) =
|
||||||
|
&tp.path.segments[2].arguments
|
||||||
|
else {
|
||||||
|
return ::syn::Error::new(
|
||||||
|
ast.span(),
|
||||||
|
"package_impl: called on \"".to_owned()
|
||||||
|
+ &name_pkg.to_string()
|
||||||
|
+ "\" base PhantomData has no arguments "
|
||||||
|
+ "what are you doing?",
|
||||||
|
)
|
||||||
|
.to_compile_error()
|
||||||
|
.into();
|
||||||
|
};
|
||||||
|
if psa.args.len() != 1 {
|
||||||
|
return ::syn::Error::new(
|
||||||
|
ast.span(),
|
||||||
|
"package_impl: called on \"".to_owned()
|
||||||
|
+ &name_pkg.to_string()
|
||||||
|
+ "\" base PhantomData has too many arguments "
|
||||||
|
+ "what are you doing?",
|
||||||
|
)
|
||||||
|
.to_compile_error()
|
||||||
|
.into();
|
||||||
|
}
|
||||||
|
let ::syn::GenericArgument::Type(::syn::Type::Path(
|
||||||
|
base_pkg_path,
|
||||||
|
)) = &psa.args[0]
|
||||||
|
else {
|
||||||
|
return ::syn::Error::new(
|
||||||
|
ast.span(),
|
||||||
|
"package_impl: called on \"".to_owned()
|
||||||
|
+ &name_pkg.to_string()
|
||||||
|
+ "\" base PhantomData has wrong argument type "
|
||||||
|
+ "what are you doing?",
|
||||||
|
)
|
||||||
|
.to_compile_error()
|
||||||
|
.into();
|
||||||
|
};
|
||||||
|
base_pkg_path.path.clone()
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return ::syn::Error::new(
|
||||||
|
ast.span(),
|
||||||
|
"package_impl: called on \"".to_owned()
|
||||||
|
+ &name_pkg.to_string()
|
||||||
|
+ "\" base of unknown type",
|
||||||
|
)
|
||||||
|
.to_compile_error()
|
||||||
|
.into();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
return ::syn::Error::new(
|
||||||
|
ast.span(),
|
||||||
|
"package_impl: called on \"".to_owned()
|
||||||
|
+ &name_pkg.to_string()
|
||||||
|
+ "\" can't find base",
|
||||||
|
)
|
||||||
|
.to_compile_error()
|
||||||
|
.into();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// now, `base_path` is an absolute path.
|
||||||
|
// but it does not mean that it is in our crate
|
||||||
|
// we need to maintain the whole path and change only the last ident,
|
||||||
|
// to the one generated by us instead of by macro_magic
|
||||||
|
|
||||||
|
// now `base_type` is the base struct. but what we actually want is
|
||||||
|
// to import the `impl ::bok::Pkg` for `base_type`
|
||||||
|
let mut exported_impl_name = base_path.clone();
|
||||||
|
let last_segment_n = exported_impl_name.segments.len() - 1;
|
||||||
|
let last_segment = &mut exported_impl_name.segments[last_segment_n];
|
||||||
|
last_segment.ident =
|
||||||
|
::quote::format_ident!("_bok_pkg_{}", last_segment.ident);
|
||||||
|
|
||||||
|
return quote! {
|
||||||
|
#[::bok_macro::package_impl_base(#exported_impl_name)]
|
||||||
|
#ast
|
||||||
|
}
|
||||||
|
.into();
|
||||||
|
}
|
||||||
|
|
||||||
|
// implements ::bok::Pkg:
|
||||||
|
// * add base methods
|
||||||
|
// * copy the non-implemented methods from the base
|
||||||
|
pub(crate) fn package_impl_base_add(
|
||||||
|
attrs: TokenStream,
|
||||||
|
ast: &mut ::syn::ItemImpl,
|
||||||
|
) -> TokenStream {
|
||||||
|
let name_pkg = match &*ast.self_ty {
|
||||||
|
::syn::Type::Path(tp) => match tp.path.get_ident() {
|
||||||
|
Some(id) => id.clone(),
|
||||||
|
_ => panic!("::bok::package_impl expected path ident"),
|
||||||
|
},
|
||||||
|
_ => panic!("::bok::package_impl expected path"),
|
||||||
|
};
|
||||||
|
let base_ast = parse_macro_input!(attrs as ::syn::ItemImpl);
|
||||||
let name: ::syn::ImplItem = ::syn::parse_quote! {
|
let name: ::syn::ImplItem = ::syn::parse_quote! {
|
||||||
fn name(&self) -> ::bok::PkgName {
|
fn name(&self) -> ::bok::PkgName {
|
||||||
(module_path!().to_owned() + "::" + ::std::stringify!(#name_pkg)).as_str().into()
|
(module_path!().to_owned() + "::" + ::std::stringify!(#name_pkg)).as_str().into()
|
||||||
@ -115,16 +379,6 @@ pub(crate) fn impl_package(
|
|||||||
self.version.clone()
|
self.version.clone()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let base: ::syn::ImplItem = ::syn::parse_quote! {
|
|
||||||
fn base(&self) -> ::core::option::Option<&dyn ::bok::Pkg> {
|
|
||||||
Some(&self.base)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let base_mut: ::syn::ImplItem = ::syn::parse_quote! {
|
|
||||||
fn base_mut(&mut self) -> ::core::option::Option<&mut dyn ::bok::Pkg> {
|
|
||||||
Some(&mut self.base)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let any: ::syn::ImplItem = ::syn::parse_quote! {
|
let any: ::syn::ImplItem = ::syn::parse_quote! {
|
||||||
fn as_any(&self) -> &dyn ::std::any::Any {
|
fn as_any(&self) -> &dyn ::std::any::Any {
|
||||||
self
|
self
|
||||||
@ -163,7 +417,11 @@ pub(crate) fn impl_package(
|
|||||||
|
|
||||||
for mut impl_item in ast.items.iter_mut() {
|
for mut impl_item in ast.items.iter_mut() {
|
||||||
if let ::syn::ImplItem::Fn(ref mut fn_impl) = &mut impl_item {
|
if let ::syn::ImplItem::Fn(ref mut fn_impl) = &mut impl_item {
|
||||||
if fn_impl.sig.ident.to_string() == "dependencies_set" {
|
if ["prepare", "configure", "build", "check", "install"]
|
||||||
|
.iter()
|
||||||
|
.find(|&f| *f == fn_impl.sig.ident.to_string().as_str())
|
||||||
|
.is_none()
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let fn_with_code: ::syn::ImplItemFn = ::syn::parse_quote! {
|
let fn_with_code: ::syn::ImplItemFn = ::syn::parse_quote! {
|
||||||
@ -179,13 +437,85 @@ pub(crate) fn impl_package(
|
|||||||
ast.items.push(name);
|
ast.items.push(name);
|
||||||
ast.items.push(path);
|
ast.items.push(path);
|
||||||
ast.items.push(version);
|
ast.items.push(version);
|
||||||
ast.items.push(base);
|
|
||||||
ast.items.push(base_mut);
|
|
||||||
ast.items.push(any);
|
ast.items.push(any);
|
||||||
ast.items.push(any_mut);
|
ast.items.push(any_mut);
|
||||||
ast.items.push(hash);
|
ast.items.push(hash);
|
||||||
ast.items.push(hash_code);
|
ast.items.push(hash_code);
|
||||||
|
|
||||||
|
fn maybe_add_fn(
|
||||||
|
name_pkg: &str,
|
||||||
|
ast: &mut ::syn::ItemImpl,
|
||||||
|
base_ast: &::syn::ItemImpl,
|
||||||
|
name: &str,
|
||||||
|
) -> Result<(), TokenStream> {
|
||||||
|
let Some(base_fn) = base_ast.items.iter().find(|&f| {
|
||||||
|
let ::syn::ImplItem::Fn(func) = f else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
return func.sig.ident.to_string() == name;
|
||||||
|
}) else {
|
||||||
|
return Err(::syn::Error::new(
|
||||||
|
ast.span(),
|
||||||
|
"package_impl: called on \"".to_owned()
|
||||||
|
+ name_pkg
|
||||||
|
+ "\" maybe_add_fn can't find "
|
||||||
|
+ name
|
||||||
|
+ " on base",
|
||||||
|
)
|
||||||
|
.to_compile_error()
|
||||||
|
.into());
|
||||||
|
};
|
||||||
|
let ::syn::ImplItem::Fn(mut base_fn_no_code) = base_fn.clone() else {
|
||||||
|
return Err(::syn::Error::new(
|
||||||
|
ast.span(),
|
||||||
|
"package_impl: called on \"".to_owned()
|
||||||
|
+ name_pkg
|
||||||
|
+ "\" what was Fn is not anymore",
|
||||||
|
)
|
||||||
|
.to_compile_error()
|
||||||
|
.into());
|
||||||
|
};
|
||||||
|
base_fn_no_code.attrs.retain_mut(|a| {
|
||||||
|
let ::syn::Meta::Path(mp) = &a.meta else {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
if mp.segments.len() == 2
|
||||||
|
&& mp.segments[0].ident.to_string() == "bok"
|
||||||
|
&& mp.segments[1].ident.to_string() == "pkg_fn_to_code"
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
if ast
|
||||||
|
.items
|
||||||
|
.iter()
|
||||||
|
.find(|&f| {
|
||||||
|
let ::syn::ImplItem::Fn(func) = f else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
return func.sig.ident.to_string() == name;
|
||||||
|
})
|
||||||
|
.is_none()
|
||||||
|
{
|
||||||
|
let new_fn: ::syn::ImplItem = parse_quote!(
|
||||||
|
#[::bok::pkg_fn_to_code]
|
||||||
|
#base_fn_no_code
|
||||||
|
);
|
||||||
|
ast.items.push(new_fn);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
for name in
|
||||||
|
["prepare", "configure", "build", "check", "install"].into_iter()
|
||||||
|
{
|
||||||
|
let Err(e) = maybe_add_fn(&name_pkg.to_string(), ast, &base_ast, name)
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
return e;
|
||||||
|
}
|
||||||
quote! {
|
quote! {
|
||||||
#ast
|
#ast
|
||||||
}
|
}
|
||||||
@ -193,23 +523,22 @@ pub(crate) fn impl_package(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn derive_package(input: TokenStream) -> TokenStream {
|
pub(crate) fn derive_package(input: TokenStream) -> TokenStream {
|
||||||
let input = parse_macro_input!(input as DeriveInput);
|
let mut input = parse_macro_input!(input as DeriveInput);
|
||||||
let mut input_nobase = input.clone();
|
|
||||||
|
|
||||||
let name = input.ident.clone();
|
let name = input.ident.clone();
|
||||||
let name_builder = quote::format_ident!("{name}Builder");
|
let name_builder = quote::format_ident!("{name}Builder");
|
||||||
let name_builder2 = name_builder.clone();
|
let name_builder2 = name_builder.clone();
|
||||||
let name_builder3 = name_builder.clone();
|
let name_builder3 = name_builder.clone();
|
||||||
let elements = match input.data {
|
let elements = match &input.data {
|
||||||
::syn::Data::Struct(s) => match s.fields {
|
::syn::Data::Struct(s) => match &s.fields {
|
||||||
syn::Fields::Named(n) => n.named,
|
syn::Fields::Named(n) => n.named.clone(),
|
||||||
_ => panic!("only named supported"),
|
_ => panic!("only named supported"),
|
||||||
},
|
},
|
||||||
_ => panic!("only struct allowed"),
|
_ => panic!("only struct allowed"),
|
||||||
};
|
};
|
||||||
let all_fields = elements.iter().filter_map(|field| {
|
let all_fields = elements.iter().filter_map(|field| {
|
||||||
if let Some(id) = field.ident.clone() {
|
if let Some(id) = field.ident.clone() {
|
||||||
if id.to_string() != "base" && id.to_string() != "version" {
|
if id.to_string() != "version" && id.to_string() != "_bok_base" {
|
||||||
return Some(&field.ident);
|
return Some(&field.ident);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -219,26 +548,15 @@ pub(crate) fn derive_package(input: TokenStream) -> TokenStream {
|
|||||||
let all_fields3 = all_fields.clone();
|
let all_fields3 = all_fields.clone();
|
||||||
let all_fields_mut = elements.iter().filter_map(|field| {
|
let all_fields_mut = elements.iter().filter_map(|field| {
|
||||||
if let Some(id) = field.ident.clone() {
|
if let Some(id) = field.ident.clone() {
|
||||||
if id.to_string() != "base" && id.to_string() != "version" {
|
if id.to_string() != "version" && id.to_string() != "_bok_base" {
|
||||||
return Some(quote::format_ident!("{}_mut", id.to_string()));
|
return Some(quote::format_ident!("{}_mut", id.to_string()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
});
|
});
|
||||||
let base_type = elements
|
|
||||||
.iter()
|
|
||||||
.find_map(|field| {
|
|
||||||
if let Some(id) = field.ident.clone() {
|
|
||||||
if id.to_string() == "base" {
|
|
||||||
return Some(&field.ty);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
})
|
|
||||||
.expect("expected a base type");
|
|
||||||
let all_types = elements.iter().filter_map(|field| {
|
let all_types = elements.iter().filter_map(|field| {
|
||||||
if let Some(id) = field.ident.clone() {
|
if let Some(id) = field.ident.clone() {
|
||||||
if id.to_string() != "base" && id.to_string() != "version" {
|
if id.to_string() != "version" && id.to_string() != "_bok_base" {
|
||||||
return Some(&field.ty);
|
return Some(&field.ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -247,7 +565,7 @@ pub(crate) fn derive_package(input: TokenStream) -> TokenStream {
|
|||||||
let all_types2 = all_types.clone();
|
let all_types2 = all_types.clone();
|
||||||
let non_opt_fields = elements.iter().filter_map(|field| {
|
let non_opt_fields = elements.iter().filter_map(|field| {
|
||||||
if let Some(id) = field.ident.clone() {
|
if let Some(id) = field.ident.clone() {
|
||||||
if id.to_string() == "base" || id.to_string() == "version" {
|
if id.to_string() == "version" || id.to_string() == "_bok_base" {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -266,7 +584,7 @@ pub(crate) fn derive_package(input: TokenStream) -> TokenStream {
|
|||||||
});
|
});
|
||||||
let opt_fields = elements.iter().filter_map(|field| {
|
let opt_fields = elements.iter().filter_map(|field| {
|
||||||
if let Some(id) = field.ident.clone() {
|
if let Some(id) = field.ident.clone() {
|
||||||
if id.to_string() == "base" || id.to_string() == "version" {
|
if id.to_string() == "version" || id.to_string() == "_bok_base" {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -285,7 +603,7 @@ pub(crate) fn derive_package(input: TokenStream) -> TokenStream {
|
|||||||
});
|
});
|
||||||
let non_opt_types = elements.iter().filter_map(|field| {
|
let non_opt_types = elements.iter().filter_map(|field| {
|
||||||
if let Some(id) = field.ident.clone() {
|
if let Some(id) = field.ident.clone() {
|
||||||
if id.to_string() == "base" || id.to_string() == "version" {
|
if id.to_string() == "version" || id.to_string() == "_bok_base" {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -304,7 +622,7 @@ pub(crate) fn derive_package(input: TokenStream) -> TokenStream {
|
|||||||
});
|
});
|
||||||
let opt_types = elements.iter().filter_map(|field| {
|
let opt_types = elements.iter().filter_map(|field| {
|
||||||
if let Some(id) = field.ident.clone() {
|
if let Some(id) = field.ident.clone() {
|
||||||
if id.to_string() == "base" || id.to_string() == "version" {
|
if id.to_string() == "version" || id.to_string() == "_bok_base" {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -337,29 +655,15 @@ pub(crate) fn derive_package(input: TokenStream) -> TokenStream {
|
|||||||
let non_opt_types2 = non_opt_types.clone();
|
let non_opt_types2 = non_opt_types.clone();
|
||||||
|
|
||||||
{
|
{
|
||||||
// remove the `base` field from the struct
|
let ::syn::Data::Struct(ref mut ds) = input.data else {
|
||||||
let ::syn::Data::Struct(ref mut ds) = input_nobase.data else {
|
|
||||||
panic!("::bok::package expected a struct");
|
panic!("::bok::package expected a struct");
|
||||||
};
|
};
|
||||||
let ::syn::Fields::Named(ref mut old_nf) = ds.fields else {
|
let ::syn::Fields::Named(ref mut _old_nf) = ds.fields else {
|
||||||
panic!("::bok::package expected a named field");
|
panic!("::bok::package expected a named field");
|
||||||
};
|
};
|
||||||
let mut new_nf = ::syn::punctuated::Punctuated::<
|
|
||||||
::syn::Field,
|
|
||||||
::syn::token::Comma,
|
|
||||||
>::new();
|
|
||||||
for f in old_nf.named.iter() {
|
|
||||||
if let Some(ref id) = f.ident {
|
|
||||||
if id.to_string() == "base" {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
new_nf.push(f.clone());
|
|
||||||
}
|
|
||||||
old_nf.named = new_nf;
|
|
||||||
}
|
}
|
||||||
let pkg_struct = quote! {
|
let pkg_struct = quote! {
|
||||||
#input_nobase
|
#input
|
||||||
};
|
};
|
||||||
let mut pkg_struct_str = String::new();
|
let mut pkg_struct_str = String::new();
|
||||||
{
|
{
|
||||||
@ -391,6 +695,7 @@ pub(crate) fn derive_package(input: TokenStream) -> TokenStream {
|
|||||||
// don't add a method if it is just the base Trait implementation
|
// don't add a method if it is just the base Trait implementation
|
||||||
fn maybe_add_fn(out: &mut String, name: &str, fn_str: &str) -> ::core::fmt::Result {
|
fn maybe_add_fn(out: &mut String, name: &str, fn_str: &str) -> ::core::fmt::Result {
|
||||||
|
|
||||||
|
//FIXME: check with the code exported from macro_magic base
|
||||||
let str_base = "self . base () . unwrap () . ".to_owned() + name + " ()";
|
let str_base = "self . base () . unwrap () . ".to_owned() + name + " ()";
|
||||||
|
|
||||||
if fn_str.trim() != str_base {
|
if fn_str.trim() != str_base {
|
||||||
@ -414,13 +719,13 @@ pub(crate) fn derive_package(input: TokenStream) -> TokenStream {
|
|||||||
|
|
||||||
let pkg_empty = ::bok::PkgEmpty::default();
|
let pkg_empty = ::bok::PkgEmpty::default();
|
||||||
let mut pkg_string = String::new();
|
let mut pkg_string = String::new();
|
||||||
|
// FIXME: filter out the things added from base pkg
|
||||||
write!(&mut pkg_string,
|
write!(&mut pkg_string,
|
||||||
"#[::bok::package({})]\n\
|
"#[::bok::package(::bok::PkgEmpty)]\n\
|
||||||
{}",
|
{}",
|
||||||
::std::stringify!(#base_type),
|
|
||||||
#pkg_struct_str)?;
|
#pkg_struct_str)?;
|
||||||
write!(&mut pkg_string,
|
write!(&mut pkg_string,
|
||||||
"#[::bok::impl_package]\n\
|
"#[::bok::package_impl]\n\
|
||||||
impl ::bok::Pkg for {} {{\n",
|
impl ::bok::Pkg for {} {{\n",
|
||||||
::std::stringify!(#name)
|
::std::stringify!(#name)
|
||||||
)?;
|
)?;
|
||||||
@ -457,14 +762,6 @@ pub(crate) fn derive_package(input: TokenStream) -> TokenStream {
|
|||||||
#(#non_opt_fields: ::std::option::Option<#non_opt_types>,)*
|
#(#non_opt_fields: ::std::option::Option<#non_opt_types>,)*
|
||||||
#(#opt_fields: ::std::option::Option<#opt_types>,)*
|
#(#opt_fields: ::std::option::Option<#opt_types>,)*
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
impl ::std::ops::Deref for #name_builder {
|
|
||||||
type Target = #base_type;
|
|
||||||
fn deref(&self) -> &#base_type {
|
|
||||||
&self.base
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
impl ::bok::PkgBuilder for #name_builder2 {
|
impl ::bok::PkgBuilder for #name_builder2 {
|
||||||
fn name(&self) -> ::bok::PkgName {
|
fn name(&self) -> ::bok::PkgName {
|
||||||
use ::bok::Pkg;
|
use ::bok::Pkg;
|
||||||
@ -492,8 +789,7 @@ pub(crate) fn derive_package(input: TokenStream) -> TokenStream {
|
|||||||
})*
|
})*
|
||||||
Ok(
|
Ok(
|
||||||
Box::new(#name {
|
Box::new(#name {
|
||||||
// FIXME: user must be able to override. Trait?
|
_bok_base: ::std::marker::PhantomData::default(),
|
||||||
base: #base_type::default(),
|
|
||||||
version: #name::default().version,
|
version: #name::default().version,
|
||||||
#(#non_opt_fields3 : self.#non_opt_fields3.clone().unwrap(),)*
|
#(#non_opt_fields3 : self.#non_opt_fields3.clone().unwrap(),)*
|
||||||
#(#opt_fields2 : self.#opt_fields2.clone(),)*
|
#(#opt_fields2 : self.#opt_fields2.clone(),)*
|
||||||
|
@ -37,12 +37,15 @@ impl TP for P {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
let one = pkgs::one::One::default();
|
||||||
|
|
||||||
let pkgs1 = pkgs::Pkgs1::default();
|
let pkgs1 = pkgs::Pkgs1::default();
|
||||||
let pkgs2 = pkgs::Pkgs2::default();
|
let pkgs2 = pkgs::Pkgs2::default();
|
||||||
use ::bok::Repository;
|
use ::bok::Repository;
|
||||||
println!("pkgs1: {}", pkgs1.name());
|
println!("pkgs1: {}", pkgs1.name());
|
||||||
println!("pkgs2: {}", pkgs2.name());
|
println!("pkgs2: {}", pkgs2.name());
|
||||||
|
|
||||||
|
/*
|
||||||
let mut pb: pkgs::one::OneBuilder = pkgs1.one();
|
let mut pb: pkgs::one::OneBuilder = pkgs1.one();
|
||||||
|
|
||||||
let b = pb.as_builder();
|
let b = pb.as_builder();
|
||||||
@ -57,6 +60,7 @@ fn main() {
|
|||||||
println!("hash one: {}", pkg.hash());
|
println!("hash one: {}", pkg.hash());
|
||||||
println!("hash one code: {}", pkg.hash_code());
|
println!("hash one code: {}", pkg.hash_code());
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
println!("pkgs1 - 1:{}", pkgs1.one().default_unused().build().my_attr);
|
println!("pkgs1 - 1:{}", pkgs1.one().default_unused().build().my_attr);
|
||||||
|
@ -40,10 +40,8 @@ pub struct Pkgs1 {
|
|||||||
bok::repo_packages! {
|
bok::repo_packages! {
|
||||||
Pkgs1 {
|
Pkgs1 {
|
||||||
One,
|
One,
|
||||||
Two,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// This repository extends and changes Pkgs1
|
/// This repository extends and changes Pkgs1
|
||||||
#[::bok::repository(Pkgs1)]
|
#[::bok::repository(Pkgs1)]
|
||||||
@ -59,6 +57,7 @@ bok::repo_packages! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
impl Pkgs2 {
|
impl Pkgs2 {
|
||||||
/// override the package `two` options from the base repostiory (Pkgs1)
|
/// override the package `two` options from the base repostiory (Pkgs1)
|
||||||
pub fn two(&self) -> Two {
|
pub fn two(&self) -> Two {
|
||||||
@ -72,8 +71,10 @@ impl Pkgs2 {
|
|||||||
two.clone()
|
two.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This repository extends both Pkgs1 and Pkgs2
|
/// This repository extends both Pkgs1 and Pkgs2
|
||||||
#[::bok::repository(Pkgs2)]
|
#[::bok::repository(Pkgs2)]
|
||||||
#[::bok::repository(Pkgs1)]
|
#[::bok::repository(Pkgs1)]
|
||||||
#[derive(::std::default::Default)]
|
#[derive(::std::default::Default)]
|
||||||
pub struct Pkgs3 {}
|
pub struct Pkgs3 {}
|
||||||
|
*/
|
||||||
|
@ -15,9 +15,13 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use ::bok::package;
|
||||||
|
//use ::bok::{package, PkgEmpty};
|
||||||
|
//use ::bok::*;
|
||||||
|
|
||||||
/// Example package
|
/// Example package
|
||||||
/// Automatically implements `.builder().my_attr(42).build()` pattern
|
/// Automatically implements `.builder().my_attr(42).build()` pattern
|
||||||
#[::bok_macro::package(::bok::PkgEmpty)]
|
#[::bok::package(::bok::PkgEmpty)]
|
||||||
pub struct One {
|
pub struct One {
|
||||||
pub my_attr: u32,
|
pub my_attr: u32,
|
||||||
}
|
}
|
||||||
@ -25,7 +29,7 @@ pub struct One {
|
|||||||
impl ::std::default::Default for One {
|
impl ::std::default::Default for One {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
One {
|
One {
|
||||||
base: ::bok::PkgEmpty::default(),
|
_bok_base: ::std::marker::PhantomData::default(),
|
||||||
my_attr: 1,
|
my_attr: 1,
|
||||||
version: ::bok::Version {
|
version: ::bok::Version {
|
||||||
major: 0,
|
major: 0,
|
||||||
@ -38,10 +42,10 @@ impl ::std::default::Default for One {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[::bok::impl_package]
|
#[::bok::package_impl]
|
||||||
impl ::bok::Pkg for One {
|
impl ::bok::Pkg for One {
|
||||||
fn build(&self) -> ::core::result::Result<(), ()> {
|
fn build(&self) -> ::core::result::Result<(), ()> {
|
||||||
ret = ::core::result::Result::Ok(());
|
::core::result::Result::Ok(())
|
||||||
}
|
}
|
||||||
fn dependencies_set(
|
fn dependencies_set(
|
||||||
&self,
|
&self,
|
||||||
|
@ -15,9 +15,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use ::bok::package;
|
||||||
|
|
||||||
/// Example package
|
/// Example package
|
||||||
/// Automatically implements `.builder().my_attr(42).build()` pattern
|
#[::bok::package(::bok::PkgEmpty)]
|
||||||
#[::bok_macro::package(::bok::PkgEmpty)]
|
|
||||||
pub struct Three {
|
pub struct Three {
|
||||||
pub my_attr: u32,
|
pub my_attr: u32,
|
||||||
}
|
}
|
||||||
@ -25,7 +26,7 @@ pub struct Three {
|
|||||||
impl ::std::default::Default for Three {
|
impl ::std::default::Default for Three {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Three {
|
Three {
|
||||||
base: bok::PkgEmpty::default(),
|
_bok_base: ::std::marker::PhantomData::default(),
|
||||||
version: ::bok::Version {
|
version: ::bok::Version {
|
||||||
major: 0,
|
major: 0,
|
||||||
minor: 0,
|
minor: 0,
|
||||||
@ -37,10 +38,11 @@ impl ::std::default::Default for Three {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[::bok::impl_package]
|
|
||||||
|
#[::bok::package_impl]
|
||||||
impl ::bok::Pkg for Three {
|
impl ::bok::Pkg for Three {
|
||||||
fn build(&self) -> ::core::result::Result<(), ()> {
|
fn build(&self) -> ::core::result::Result<(), ()> {
|
||||||
ret = ::core::result::Result::Ok(());
|
::core::result::Result::Ok(())
|
||||||
}
|
}
|
||||||
fn dependencies_set(
|
fn dependencies_set(
|
||||||
&self,
|
&self,
|
||||||
|
@ -15,18 +15,20 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use ::bok::package;
|
||||||
|
|
||||||
/// Example package
|
/// Example package
|
||||||
/// Automatically implements `.builder().my_attr(42).build()` pattern
|
#[::bok::package(crate::pkgs::One)]
|
||||||
#[::bok_macro::package(::bok::PkgEmpty)]
|
|
||||||
pub struct Two {
|
pub struct Two {
|
||||||
pub my_attr: u32,
|
pub my_attr2: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::std::default::Default for Two {
|
impl ::std::default::Default for Two {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Two {
|
Two {
|
||||||
base: ::bok::PkgEmpty::default(),
|
_bok_base: ::std::marker::PhantomData::default(),
|
||||||
my_attr: 2,
|
my_attr: 2,
|
||||||
|
my_attr2: 2,
|
||||||
version: ::bok::Version {
|
version: ::bok::Version {
|
||||||
major: 0,
|
major: 0,
|
||||||
minor: 0,
|
minor: 0,
|
||||||
@ -37,7 +39,8 @@ impl ::std::default::Default for Two {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[::bok::impl_package]
|
|
||||||
|
#[::bok::package_impl]
|
||||||
impl ::bok::Pkg for Two {
|
impl ::bok::Pkg for Two {
|
||||||
fn dependencies_set(
|
fn dependencies_set(
|
||||||
&self,
|
&self,
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
|
|
||||||
* Copyright 2024 Luca Fulchir <luca.fulchir@runesauth.com>
|
* Copyright 2024 Luca Fulchir <luca.fulchir@runesauth.com>
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 with LLVM exception (the
|
* Licensed under the Apache License, Version 2.0 with LLVM exception (the
|
||||||
@ -28,7 +27,7 @@ pub mod deps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub use ::bok_macro::{
|
pub use ::bok_macro::{
|
||||||
impl_package, package, pkg_fn_to_code, repository, Package, Repository,
|
package, package_impl, pkg_fn_to_code, repository, Package, Repository,
|
||||||
};
|
};
|
||||||
pub use ::semver::{BuildMetadata, Prerelease, Version};
|
pub use ::semver::{BuildMetadata, Prerelease, Version};
|
||||||
|
|
||||||
@ -121,8 +120,6 @@ pub trait Pkg:
|
|||||||
fn name(&self) -> PkgName;
|
fn name(&self) -> PkgName;
|
||||||
fn path(&self) -> Path<PkgName>;
|
fn path(&self) -> Path<PkgName>;
|
||||||
fn version(&self) -> Version;
|
fn version(&self) -> Version;
|
||||||
fn base(&self) -> ::core::option::Option<&dyn Pkg>;
|
|
||||||
fn base_mut(&mut self) -> ::core::option::Option<&mut dyn Pkg>;
|
|
||||||
fn as_any(&self) -> &dyn ::std::any::Any;
|
fn as_any(&self) -> &dyn ::std::any::Any;
|
||||||
fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any;
|
fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any;
|
||||||
fn dependencies_set(
|
fn dependencies_set(
|
||||||
@ -131,46 +128,16 @@ pub trait Pkg:
|
|||||||
build: &deps::Build,
|
build: &deps::Build,
|
||||||
runtime: &deps::Runtime,
|
runtime: &deps::Runtime,
|
||||||
) -> Result<(), ()>;
|
) -> Result<(), ()>;
|
||||||
fn prepare(&self) -> ::core::result::Result<(), ()> {
|
fn prepare(&self) -> ::core::result::Result<(), ()>;
|
||||||
self.base().unwrap().prepare()
|
fn prepare_code(&self) -> ::proc_macro2::TokenStream;
|
||||||
}
|
fn configure(&self) -> ::core::result::Result<(), ()>;
|
||||||
fn prepare_code(&self) -> ::proc_macro2::TokenStream {
|
fn configure_code(&self) -> ::proc_macro2::TokenStream;
|
||||||
::quote::quote! {
|
fn build(&self) -> ::core::result::Result<(), ()>;
|
||||||
self.base().unwrap().prepare()
|
fn build_code(&self) -> ::proc_macro2::TokenStream;
|
||||||
}
|
fn check(&self) -> ::core::result::Result<(), ()>;
|
||||||
}
|
fn check_code(&self) -> ::proc_macro2::TokenStream;
|
||||||
fn configure(&self) -> ::core::result::Result<(), ()> {
|
fn install(&self) -> ::core::result::Result<(), ()>;
|
||||||
self.base().unwrap().configure()
|
fn install_code(&self) -> ::proc_macro2::TokenStream;
|
||||||
}
|
|
||||||
fn configure_code(&self) -> ::proc_macro2::TokenStream {
|
|
||||||
::quote::quote! {
|
|
||||||
self.base().unwrap().configure()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn build(&self) -> ::core::result::Result<(), ()> {
|
|
||||||
self.base().unwrap().build()
|
|
||||||
}
|
|
||||||
fn build_code(&self) -> ::proc_macro2::TokenStream {
|
|
||||||
::quote::quote! {
|
|
||||||
self.base().unwrap().build()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn check(&self) -> ::core::result::Result<(), ()> {
|
|
||||||
self.base().unwrap().check()
|
|
||||||
}
|
|
||||||
fn check_code(&self) -> ::proc_macro2::TokenStream {
|
|
||||||
::quote::quote! {
|
|
||||||
self.base().unwrap().check()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn install(&self) -> ::core::result::Result<(), ()> {
|
|
||||||
self.base().unwrap().install()
|
|
||||||
}
|
|
||||||
fn install_code(&self) -> ::proc_macro2::TokenStream {
|
|
||||||
::quote::quote! {
|
|
||||||
self.base().unwrap().install()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn package(&self) -> ::core::result::Result<(), ()> {
|
fn package(&self) -> ::core::result::Result<(), ()> {
|
||||||
self.prepare()?;
|
self.prepare()?;
|
||||||
self.configure()?;
|
self.configure()?;
|
||||||
@ -192,6 +159,7 @@ pub trait PkgBuilder: ::core::fmt::Debug + ::std::any::Any {
|
|||||||
) -> Result<Box<dyn Pkg>, ::std::boxed::Box<dyn ::std::error::Error>>;
|
) -> Result<Box<dyn Pkg>, ::std::boxed::Box<dyn ::std::error::Error>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[::macro_magic::export_tokens]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct PkgEmpty {
|
pub struct PkgEmpty {
|
||||||
version: Version,
|
version: Version,
|
||||||
@ -223,6 +191,7 @@ impl PkgCode for PkgEmpty {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[::macro_magic::export_tokens(_bok_pkg_PkgEmpty)]
|
||||||
impl Pkg for PkgEmpty {
|
impl Pkg for PkgEmpty {
|
||||||
fn name(&self) -> PkgName {
|
fn name(&self) -> PkgName {
|
||||||
"PkgEmpty".into()
|
"PkgEmpty".into()
|
||||||
@ -233,12 +202,6 @@ impl Pkg for PkgEmpty {
|
|||||||
fn version(&self) -> Version {
|
fn version(&self) -> Version {
|
||||||
self.version.clone()
|
self.version.clone()
|
||||||
}
|
}
|
||||||
fn base(&self) -> Option<&dyn Pkg> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
fn base_mut(&mut self) -> Option<&mut dyn Pkg> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
fn as_any(&self) -> &dyn ::std::any::Any {
|
fn as_any(&self) -> &dyn ::std::any::Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -258,7 +221,7 @@ impl Pkg for PkgEmpty {
|
|||||||
}
|
}
|
||||||
fn prepare_code(&self) -> ::proc_macro2::TokenStream {
|
fn prepare_code(&self) -> ::proc_macro2::TokenStream {
|
||||||
::quote::quote! {
|
::quote::quote! {
|
||||||
ret = ::core::result::Result::Ok(());
|
::core::result::Result::Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn configure(&self) -> ::core::result::Result<(), ()> {
|
fn configure(&self) -> ::core::result::Result<(), ()> {
|
||||||
@ -266,7 +229,7 @@ impl Pkg for PkgEmpty {
|
|||||||
}
|
}
|
||||||
fn configure_code(&self) -> ::proc_macro2::TokenStream {
|
fn configure_code(&self) -> ::proc_macro2::TokenStream {
|
||||||
::quote::quote! {
|
::quote::quote! {
|
||||||
ret = ::core::result::Result::Ok(());
|
::core::result::Result::Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn build(&self) -> ::core::result::Result<(), ()> {
|
fn build(&self) -> ::core::result::Result<(), ()> {
|
||||||
@ -274,7 +237,7 @@ impl Pkg for PkgEmpty {
|
|||||||
}
|
}
|
||||||
fn build_code(&self) -> ::proc_macro2::TokenStream {
|
fn build_code(&self) -> ::proc_macro2::TokenStream {
|
||||||
::quote::quote! {
|
::quote::quote! {
|
||||||
ret = ::core::result::Result::Ok(());
|
::core::result::Result::Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn check(&self) -> ::core::result::Result<(), ()> {
|
fn check(&self) -> ::core::result::Result<(), ()> {
|
||||||
@ -282,7 +245,7 @@ impl Pkg for PkgEmpty {
|
|||||||
}
|
}
|
||||||
fn check_code(&self) -> ::proc_macro2::TokenStream {
|
fn check_code(&self) -> ::proc_macro2::TokenStream {
|
||||||
::quote::quote! {
|
::quote::quote! {
|
||||||
ret = ::core::result::Result::Ok(());
|
::core::result::Result::Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn install(&self) -> ::core::result::Result<(), ()> {
|
fn install(&self) -> ::core::result::Result<(), ()> {
|
||||||
@ -290,7 +253,7 @@ impl Pkg for PkgEmpty {
|
|||||||
}
|
}
|
||||||
fn install_code(&self) -> ::proc_macro2::TokenStream {
|
fn install_code(&self) -> ::proc_macro2::TokenStream {
|
||||||
::quote::quote! {
|
::quote::quote! {
|
||||||
ret = ::core::result::Result::Ok(());
|
::core::result::Result::Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn hash(&self) -> Hash {
|
fn hash(&self) -> Hash {
|
||||||
|
@ -53,6 +53,8 @@
|
|||||||
#mold
|
#mold
|
||||||
# fenrir deps
|
# fenrir deps
|
||||||
hwloc
|
hwloc
|
||||||
|
# development
|
||||||
|
nixd
|
||||||
];
|
];
|
||||||
# if you want to try the mold linker, add 'clang_16', 'mold', and append this to ~/.cargo/config.toml:
|
# if you want to try the mold linker, add 'clang_16', 'mold', and append this to ~/.cargo/config.toml:
|
||||||
# [target.x86_64-unknown-linux-gnu]
|
# [target.x86_64-unknown-linux-gnu]
|
||||||
|
Loading…
Reference in New Issue
Block a user