Package dependencies
Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
This commit is contained in:
parent
631c3a19e5
commit
00e93ce612
@ -84,7 +84,7 @@ pub fn repo_impl(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
/// Create the methods that will return the builders and packages
|
/// Create the methods that will return the builders and packages
|
||||||
/// Usage:
|
/// Usage:
|
||||||
/// ```
|
/// ```
|
||||||
/// #[::bok_macro::repo_impl(MyRepo)]
|
/// #[::bok_macro::repo_impl_methods(MyRepo)]
|
||||||
/// impl MyRepo{}
|
/// impl MyRepo{}
|
||||||
/// ```
|
/// ```
|
||||||
#[::macro_magic::import_tokens_attr]
|
#[::macro_magic::import_tokens_attr]
|
||||||
@ -96,6 +96,24 @@ pub fn repo_impl_methods(
|
|||||||
crate::repos::repo_impl_methods(attrs, input, __source_path)
|
crate::repos::repo_impl_methods(attrs, input, __source_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Internal. **Do not use unless you know what you are doing**
|
||||||
|
/// given a Repository and a trait "BokDeps...",
|
||||||
|
/// implement all the fn returning the dependencies needed by the package
|
||||||
|
///
|
||||||
|
/// Usage:
|
||||||
|
/// ```
|
||||||
|
/// #[::bok_macro::repo_impl_(MyRepo)]
|
||||||
|
/// impl MyRepo{}
|
||||||
|
/// ```
|
||||||
|
#[::macro_magic::import_tokens_attr]
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn repo_impl_pkg_deps(
|
||||||
|
attrs: TokenStream,
|
||||||
|
input: TokenStream,
|
||||||
|
) -> TokenStream {
|
||||||
|
crate::repos::repo_impl_pkg_deps(attrs, input)
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// ####### Package stuff ##########
|
// ####### Package stuff ##########
|
||||||
//
|
//
|
||||||
@ -138,6 +156,19 @@ pub fn package(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
crate::pkgs::package(attrs, input, __source_path)
|
crate::pkgs::package(attrs, input, __source_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Specify one or more build-time dependencies
|
||||||
|
///
|
||||||
|
/// e.g:
|
||||||
|
/// ```
|
||||||
|
/// #[::bok::package(::bok::PkgEmpty)]
|
||||||
|
/// #[::bok::deps_build(some::Package, other::Package)]
|
||||||
|
/// pub struct MyPkg {}
|
||||||
|
/// ```
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn deps_build(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
|
crate::pkgs::deps_build(attrs, input)
|
||||||
|
}
|
||||||
|
|
||||||
/// Use as #[::bok::package_impl]
|
/// Use as #[::bok::package_impl]
|
||||||
/// will add `#[::bok::package_impl_base(..)]` with proper arguments
|
/// will add `#[::bok::package_impl_base(..)]` with proper arguments
|
||||||
/// and export the resulting symbols
|
/// and export the resulting symbols
|
||||||
@ -205,3 +236,34 @@ pub fn package_impl_base(
|
|||||||
pub fn derive_package(input: TokenStream) -> TokenStream {
|
pub fn derive_package(input: TokenStream) -> TokenStream {
|
||||||
crate::pkgs::derive_package(input)
|
crate::pkgs::derive_package(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ==== Common package stuff ====
|
||||||
|
|
||||||
|
pub(crate) struct PathList(Vec<::syn::Path>);
|
||||||
|
|
||||||
|
impl ::syn::parse::Parse for PathList {
|
||||||
|
fn parse(input: ::syn::parse::ParseStream) -> syn::Result<Self> {
|
||||||
|
use ::syn::punctuated::Punctuated;
|
||||||
|
let raw =
|
||||||
|
Punctuated::<::syn::Path, ::syn::Token![,]>::parse_terminated(
|
||||||
|
input,
|
||||||
|
)?;
|
||||||
|
let mut result = Vec::with_capacity(raw.len());
|
||||||
|
for r in raw.into_iter() {
|
||||||
|
result.push(r)
|
||||||
|
}
|
||||||
|
Ok(PathList(result))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn path_to_magic_export(p: &::syn::Path) -> ::syn::Path {
|
||||||
|
let mut tmp = p.clone();
|
||||||
|
let new_id = {
|
||||||
|
macro_magic::mm_core::export_tokens_macro_ident(
|
||||||
|
&tmp.segments.last().unwrap().ident,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
tmp.segments.last_mut().unwrap().ident = new_id;
|
||||||
|
|
||||||
|
tmp
|
||||||
|
}
|
||||||
|
@ -157,6 +157,52 @@ pub(crate) fn package(
|
|||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn deps_build(
|
||||||
|
attrs: TokenStream,
|
||||||
|
input: TokenStream,
|
||||||
|
) -> TokenStream {
|
||||||
|
let packages = parse_macro_input!(attrs as crate::PathList);
|
||||||
|
|
||||||
|
let local = parse_macro_input!(input as ::syn::ItemStruct);
|
||||||
|
let ::syn::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 local_attrs = local.attrs.iter();
|
||||||
|
let local_fields = local_fields.named.iter();
|
||||||
|
let generics = local.generics;
|
||||||
|
let ident = local.ident;
|
||||||
|
let vis = local.vis;
|
||||||
|
|
||||||
|
let pkg_trait = quote::format_ident!("BokDeps{}", ident);
|
||||||
|
|
||||||
|
let deps = packages
|
||||||
|
.0
|
||||||
|
.iter()
|
||||||
|
.map(|x| x.segments.last().unwrap().ident.clone())
|
||||||
|
.collect::<Vec<::syn::Ident>>();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#(#local_attrs)
|
||||||
|
*
|
||||||
|
#vis struct #ident<#generics> {
|
||||||
|
#(#local_fields),
|
||||||
|
*
|
||||||
|
}
|
||||||
|
#[::macro_magic::export_tokens(#pkg_trait)]
|
||||||
|
pub trait #pkg_trait {
|
||||||
|
#(fn #deps(&self) -> ::std::boxed::Box<dyn ::bok::Pkg>;)
|
||||||
|
*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
// package_impl has 3 stages, and uses macro_magic import for the last two:
|
// 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
|
// * called without parameters => add default ::bok::Pkg functions, then add the
|
||||||
// same macro with the package type as argument
|
// same macro with the package type as argument
|
||||||
|
@ -19,122 +19,6 @@ use ::proc_macro::TokenStream;
|
|||||||
use ::quote::quote;
|
use ::quote::quote;
|
||||||
use ::syn::{parse_macro_input, DeriveInput, Fields, ItemImpl, ItemStruct};
|
use ::syn::{parse_macro_input, DeriveInput, Fields, ItemImpl, ItemStruct};
|
||||||
|
|
||||||
pub(crate) fn repo_impl(
|
|
||||||
_attrs: TokenStream,
|
|
||||||
input: TokenStream,
|
|
||||||
) -> TokenStream {
|
|
||||||
let local = parse_macro_input!(input as ItemImpl);
|
|
||||||
|
|
||||||
let reponame = &local.self_ty;
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
#[::bok_macro::repo_impl_methods(#reponame)]
|
|
||||||
#local
|
|
||||||
}
|
|
||||||
.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn repo_impl_methods(
|
|
||||||
attrs: TokenStream,
|
|
||||||
input: TokenStream,
|
|
||||||
__source_name: TokenStream,
|
|
||||||
) -> TokenStream {
|
|
||||||
let base = parse_macro_input!(attrs as ItemStruct);
|
|
||||||
let local = parse_macro_input!(input as ItemImpl);
|
|
||||||
let source_name = parse_macro_input!(__source_name as ::syn::Path);
|
|
||||||
|
|
||||||
if let ::syn::Type::Path(self_type_path) = local.self_ty.as_ref() {
|
|
||||||
if self_type_path.path != source_name {
|
|
||||||
return ::syn::Error::new(
|
|
||||||
proc_macro2::Span::call_site(),
|
|
||||||
"#[::bok_macro::repo_impl_methods(..)]: argument and impl \
|
|
||||||
type differ",
|
|
||||||
)
|
|
||||||
.to_compile_error()
|
|
||||||
.into();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return ::syn::Error::new(
|
|
||||||
proc_macro2::Span::call_site(),
|
|
||||||
"#[::bok_macro::repo_impl_methods(..)]: argument and impl type \
|
|
||||||
differ",
|
|
||||||
)
|
|
||||||
.to_compile_error()
|
|
||||||
.into();
|
|
||||||
}
|
|
||||||
|
|
||||||
let local_attrs = local.attrs.iter();
|
|
||||||
let generics = local.generics;
|
|
||||||
let ident = &local.self_ty;
|
|
||||||
let items = local.items.iter();
|
|
||||||
|
|
||||||
let ::syn::Fields::Named(base_fields) = base.fields else {
|
|
||||||
return ::syn::Error::new(
|
|
||||||
proc_macro2::Span::call_site(),
|
|
||||||
"#[::bok_macro::repo_impl_methods(..)]: type has unsupported \
|
|
||||||
unnamed fields",
|
|
||||||
)
|
|
||||||
.to_compile_error()
|
|
||||||
.into();
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut fn_to_add = Vec::new();
|
|
||||||
for f in base_fields.named.iter() {
|
|
||||||
if !f
|
|
||||||
.ident
|
|
||||||
.as_ref()
|
|
||||||
.is_some_and(|id| id.to_string().starts_with("_p_"))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
let ::syn::Type::Path(f_type) = &f.ty else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
let t_phantom = &f_type.path;
|
|
||||||
let t_id = {
|
|
||||||
let args = &t_phantom
|
|
||||||
.segments
|
|
||||||
.last()
|
|
||||||
.expect("t_phantom no last?")
|
|
||||||
.arguments;
|
|
||||||
let ::syn::PathArguments::AngleBracketed(bracketed) = &args else {
|
|
||||||
panic!("phantom without anglebracket?");
|
|
||||||
};
|
|
||||||
let ::syn::GenericArgument::Type(::syn::Type::Path(t)) =
|
|
||||||
bracketed.args.first().expect("phantom bracketed, no args")
|
|
||||||
else {
|
|
||||||
panic!("phantom bracketed, generic not a type path");
|
|
||||||
};
|
|
||||||
t.path.clone()
|
|
||||||
};
|
|
||||||
let pkg_name = {
|
|
||||||
let segment = t_id.segments.iter().last().unwrap();
|
|
||||||
|
|
||||||
&segment.ident
|
|
||||||
};
|
|
||||||
let pkg_fn: ::syn::ImplItemFn = ::syn::parse_quote! {
|
|
||||||
pub fn #pkg_name(&self) -> #t_id {
|
|
||||||
#t_id::default()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
fn_to_add.push(pkg_fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
let new_fn = fn_to_add.iter();
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
#(#local_attrs)
|
|
||||||
*
|
|
||||||
impl #ident<#generics> {
|
|
||||||
#(#items)
|
|
||||||
*
|
|
||||||
#(#new_fn)
|
|
||||||
*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn repository(
|
pub(crate) fn repository(
|
||||||
attrs: TokenStream,
|
attrs: TokenStream,
|
||||||
input: TokenStream,
|
input: TokenStream,
|
||||||
@ -368,22 +252,6 @@ pub(crate) fn derive_repository(input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}.into()
|
}.into()
|
||||||
}
|
}
|
||||||
struct PathList(Vec<::syn::Path>);
|
|
||||||
|
|
||||||
impl ::syn::parse::Parse for PathList {
|
|
||||||
fn parse(input: ::syn::parse::ParseStream) -> syn::Result<Self> {
|
|
||||||
use ::syn::punctuated::Punctuated;
|
|
||||||
let raw =
|
|
||||||
Punctuated::<::syn::Path, ::syn::Token![,]>::parse_terminated(
|
|
||||||
input,
|
|
||||||
)?;
|
|
||||||
let mut result = Vec::with_capacity(raw.len());
|
|
||||||
for r in raw.into_iter() {
|
|
||||||
result.push(r)
|
|
||||||
}
|
|
||||||
Ok(PathList(result))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn repo_packages(
|
pub(crate) fn repo_packages(
|
||||||
attrs: TokenStream,
|
attrs: TokenStream,
|
||||||
@ -446,7 +314,7 @@ pub(crate) fn repo_packages(
|
|||||||
})
|
})
|
||||||
.collect::<Vec<&::syn::Field>>();
|
.collect::<Vec<&::syn::Field>>();
|
||||||
|
|
||||||
let packages = parse_macro_input!(attrs as PathList);
|
let packages = parse_macro_input!(attrs as crate::PathList);
|
||||||
|
|
||||||
// the packages added manually must not be repeated manually.
|
// the packages added manually must not be repeated manually.
|
||||||
// but they will override any other package added by
|
// but they will override any other package added by
|
||||||
@ -530,20 +398,213 @@ pub(crate) fn repo_packages(
|
|||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path_to_snake_case(path: &::syn::Path) -> String {
|
pub(crate) fn repo_impl(
|
||||||
let mut s = String::new();
|
_attrs: TokenStream,
|
||||||
|
input: TokenStream,
|
||||||
|
) -> TokenStream {
|
||||||
|
let local = parse_macro_input!(input as ItemImpl);
|
||||||
|
|
||||||
let mut is_first = true;
|
let reponame = &local.self_ty;
|
||||||
for segment in path.segments.iter() {
|
|
||||||
if !is_first {
|
quote! {
|
||||||
s += "_";
|
#[::bok_macro::repo_impl_methods(#reponame)]
|
||||||
|
#local
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn repo_impl_methods(
|
||||||
|
attrs: TokenStream,
|
||||||
|
input: TokenStream,
|
||||||
|
__source_name: TokenStream,
|
||||||
|
) -> TokenStream {
|
||||||
|
let base = parse_macro_input!(attrs as ItemStruct);
|
||||||
|
let local = parse_macro_input!(input as ItemImpl);
|
||||||
|
let source_name = parse_macro_input!(__source_name as ::syn::Path);
|
||||||
|
|
||||||
|
if let ::syn::Type::Path(self_type_path) = local.self_ty.as_ref() {
|
||||||
|
if self_type_path.path != source_name {
|
||||||
|
return ::syn::Error::new(
|
||||||
|
proc_macro2::Span::call_site(),
|
||||||
|
"#[::bok_macro::repo_impl_methods(..)]: argument and impl \
|
||||||
|
type differ",
|
||||||
|
)
|
||||||
|
.to_compile_error()
|
||||||
|
.into();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
is_first = false
|
return ::syn::Error::new(
|
||||||
}
|
proc_macro2::Span::call_site(),
|
||||||
s += segment.ident.to_string().as_str();
|
"#[::bok_macro::repo_impl_methods(..)]: argument and impl type \
|
||||||
|
differ",
|
||||||
|
)
|
||||||
|
.to_compile_error()
|
||||||
|
.into();
|
||||||
}
|
}
|
||||||
|
|
||||||
use ::convert_case::{Case, Casing};
|
let local_attrs = local.attrs.iter();
|
||||||
|
let generics = local.generics;
|
||||||
|
let ::syn::Type::Path(local_tp) = local.self_ty.as_ref() else {
|
||||||
|
return ::syn::Error::new(
|
||||||
|
proc_macro2::Span::call_site(),
|
||||||
|
"#[::bok_macro::repo_impl_methods(..)]: no ident?",
|
||||||
|
)
|
||||||
|
.to_compile_error()
|
||||||
|
.into();
|
||||||
|
};
|
||||||
|
let local_ident = local_tp.path.get_ident().expect("NOT AN IDENT");
|
||||||
|
let items = local.items.iter();
|
||||||
|
// FIXME: make sure `items` does not have methods that are not packages in
|
||||||
|
// the impl
|
||||||
|
|
||||||
s.to_case(Case::Snake)
|
let ::syn::Fields::Named(base_fields) = base.fields else {
|
||||||
|
return ::syn::Error::new(
|
||||||
|
proc_macro2::Span::call_site(),
|
||||||
|
"#[::bok_macro::repo_impl_methods(..)]: type has unsupported \
|
||||||
|
unnamed fields",
|
||||||
|
)
|
||||||
|
.to_compile_error()
|
||||||
|
.into();
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut all_pkgs_types = Vec::with_capacity(base_fields.named.len());
|
||||||
|
|
||||||
|
let mut fn_to_add = Vec::new();
|
||||||
|
for f in base_fields.named.iter() {
|
||||||
|
if !f
|
||||||
|
.ident
|
||||||
|
.as_ref()
|
||||||
|
.is_some_and(|id| id.to_string().starts_with("_p_"))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let ::syn::Type::Path(f_type) = &f.ty else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let t_phantom = &f_type.path;
|
||||||
|
let t_id = {
|
||||||
|
let args = &t_phantom
|
||||||
|
.segments
|
||||||
|
.last()
|
||||||
|
.expect("t_phantom no last?")
|
||||||
|
.arguments;
|
||||||
|
let ::syn::PathArguments::AngleBracketed(bracketed) = &args else {
|
||||||
|
panic!("phantom without anglebracket?");
|
||||||
|
};
|
||||||
|
let ::syn::GenericArgument::Type(::syn::Type::Path(t)) =
|
||||||
|
bracketed.args.first().expect("phantom bracketed, no args")
|
||||||
|
else {
|
||||||
|
panic!("phantom bracketed, generic not a type path");
|
||||||
|
};
|
||||||
|
t.path.clone()
|
||||||
|
};
|
||||||
|
let pkg_name = {
|
||||||
|
let segment = t_id.segments.iter().last().unwrap();
|
||||||
|
|
||||||
|
&segment.ident
|
||||||
|
};
|
||||||
|
all_pkgs_types.push(t_id.clone());
|
||||||
|
if local
|
||||||
|
.items
|
||||||
|
.iter()
|
||||||
|
.find(|&func_it| {
|
||||||
|
let ::syn::ImplItem::Fn(func) = &func_it else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
func.sig.ident.to_string() == pkg_name.to_string()
|
||||||
|
})
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
// the user overrode the `::default()` package build
|
||||||
|
// don't try to add it again
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let pkg_fn: ::syn::ImplItemFn = ::syn::parse_quote! {
|
||||||
|
pub fn #pkg_name(&self) -> #t_id {
|
||||||
|
#t_id::default()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fn_to_add.push(pkg_fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_fn = fn_to_add.iter();
|
||||||
|
|
||||||
|
let mut all_impl_deps = Vec::with_capacity(all_pkgs_types.len());
|
||||||
|
|
||||||
|
for p_type in all_pkgs_types.into_iter() {
|
||||||
|
let bok_dep_trait = {
|
||||||
|
let mut tmp = p_type.clone();
|
||||||
|
tmp.segments.last_mut().unwrap().ident = quote::format_ident!(
|
||||||
|
"BokDeps{}",
|
||||||
|
tmp.segments.last().unwrap().ident
|
||||||
|
);
|
||||||
|
tmp
|
||||||
|
};
|
||||||
|
let pkg_trait_impl = &bok_dep_trait;
|
||||||
|
let dep_view = quote! {
|
||||||
|
#[::bok_macro::repo_impl_pkg_deps(#pkg_trait_impl)]
|
||||||
|
impl #bok_dep_trait for #local_ident {}
|
||||||
|
};
|
||||||
|
all_impl_deps.push(dep_view);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#(#local_attrs)
|
||||||
|
*
|
||||||
|
impl #local_ident<#generics> {
|
||||||
|
#(#items)
|
||||||
|
*
|
||||||
|
#(#new_fn)
|
||||||
|
*
|
||||||
|
}
|
||||||
|
#(#all_impl_deps)
|
||||||
|
*
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn repo_impl_pkg_deps(
|
||||||
|
attrs: TokenStream,
|
||||||
|
input: TokenStream,
|
||||||
|
) -> TokenStream {
|
||||||
|
let trait_deps = parse_macro_input!(attrs as ::syn::ItemTrait);
|
||||||
|
let local = parse_macro_input!(input as ItemImpl);
|
||||||
|
|
||||||
|
let impl_trait = local
|
||||||
|
.trait_
|
||||||
|
.expect("#[::bok_macro::repo_impl_pkg_deps()]: no trait found")
|
||||||
|
.1;
|
||||||
|
let local_attrs = local.attrs.iter();
|
||||||
|
let generics = local.generics;
|
||||||
|
let ident = &local.self_ty;
|
||||||
|
|
||||||
|
//let deps = Vec::<::syn::TraitItemFn>::new();
|
||||||
|
let deps = trait_deps
|
||||||
|
.items
|
||||||
|
.iter()
|
||||||
|
.filter_map(|x| {
|
||||||
|
if let ::syn::TraitItem::Fn(func) = &x {
|
||||||
|
let name = &func.sig.ident;
|
||||||
|
let dep_impl: ::syn::TraitItemFn = ::syn::parse_quote! {
|
||||||
|
fn #name(&self) -> ::std::boxed::Box<dyn ::bok::Pkg> {
|
||||||
|
::std::boxed::Box::new(self.#name())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Some(dep_impl)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<::syn::TraitItemFn>>();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#(#local_attrs)
|
||||||
|
*
|
||||||
|
impl #impl_trait for #ident<#generics> {
|
||||||
|
#(#deps)
|
||||||
|
*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ pub mod pkgs;
|
|||||||
|
|
||||||
// FIXME: why?
|
// FIXME: why?
|
||||||
use ::bok_macro::repo_impl_methods;
|
use ::bok_macro::repo_impl_methods;
|
||||||
|
use ::bok_macro::repo_impl_pkg_deps;
|
||||||
// Export multiple packages in this module
|
// Export multiple packages in this module
|
||||||
use ::bok::repository;
|
use ::bok::repository;
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ use ::bok::package;
|
|||||||
/// Example package
|
/// Example package
|
||||||
/// Automatically implements `.builder().my_attr(42).build()` pattern
|
/// Automatically implements `.builder().my_attr(42).build()` pattern
|
||||||
#[::bok::package(::bok::PkgEmpty)]
|
#[::bok::package(::bok::PkgEmpty)]
|
||||||
|
#[::bok::deps_build()]
|
||||||
pub struct One {
|
pub struct One {
|
||||||
pub my_attr: u32,
|
pub my_attr: u32,
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ use ::bok::package;
|
|||||||
|
|
||||||
/// Example package
|
/// Example package
|
||||||
#[::bok::package(::bok::PkgEmpty)]
|
#[::bok::package(::bok::PkgEmpty)]
|
||||||
|
#[::bok::deps_build(super::One)]
|
||||||
pub struct Three {
|
pub struct Three {
|
||||||
pub my_attr: u32,
|
pub my_attr: u32,
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ use ::bok::package;
|
|||||||
|
|
||||||
/// Example package
|
/// Example package
|
||||||
#[::bok::package(super::one::One)]
|
#[::bok::package(super::one::One)]
|
||||||
|
#[::bok::deps_build(super::one::One)]
|
||||||
pub struct Two {
|
pub struct Two {
|
||||||
pub my_attr2: u32,
|
pub my_attr2: u32,
|
||||||
}
|
}
|
||||||
|
@ -27,8 +27,8 @@ pub mod deps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub use ::bok_macro::{
|
pub use ::bok_macro::{
|
||||||
package, package_impl, pkg_fn_to_code, repo_impl, repo_packages,
|
deps_build, package, package_impl, pkg_fn_to_code, repo_impl,
|
||||||
repository, Package, Repository,
|
repo_packages, repository, Package, Repository,
|
||||||
};
|
};
|
||||||
pub use ::semver::{BuildMetadata, Prerelease, Version};
|
pub use ::semver::{BuildMetadata, Prerelease, Version};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user