better ergonomics: hide generics in packages
Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
This commit is contained in:
parent
34a1771695
commit
ae44556dd7
@ -150,10 +150,26 @@ 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, __source_path)
|
crate::pkgs::package(attrs, input)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// **Internal**. try not to use
|
||||||
|
/// Use as #[::bok::package(MyBasePackage<R>)]
|
||||||
|
/// Will setup a `base` field that is the given base package
|
||||||
|
/// and add `#[derive(::bok::Package)]`
|
||||||
|
/// needs generics
|
||||||
|
///
|
||||||
|
/// e.g.:
|
||||||
|
/// ```
|
||||||
|
/// #[::bok::package_path(::base::pkg<R>)]
|
||||||
|
/// pub struct MyPkg {}
|
||||||
|
/// ```
|
||||||
|
#[::macro_magic::import_tokens_attr]
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn package_path(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
|
crate::pkgs::package_path(attrs, input, __source_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specify one or more build-time dependencies
|
/// Specify one or more build-time dependencies
|
||||||
@ -170,12 +186,17 @@ pub fn deps_build(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Use as #[::bok::package_impl]
|
/// Use as #[::bok::package_impl]
|
||||||
/// will add `#[::bok::package_impl_base(..)]` with proper arguments
|
/// adds the right generics to the package.
|
||||||
/// and export the resulting symbols
|
///
|
||||||
|
/// extra calls and changes are added to `::bok::Pkg` and ::std::Default traits
|
||||||
///
|
///
|
||||||
/// e.g.:
|
/// e.g.:
|
||||||
/// ```
|
/// ```
|
||||||
/// #[::bok::package_impl]
|
/// #[::bok::package_impl]
|
||||||
|
/// impl Default for Mypackage {
|
||||||
|
/// fn default() -> Self { ... }
|
||||||
|
/// }
|
||||||
|
/// #[::bok::package_impl]
|
||||||
/// impl ::bok::Pkg for MyPackage {
|
/// impl ::bok::Pkg for MyPackage {
|
||||||
/// fn build(&self) -> Result<(),()> {
|
/// fn build(&self) -> Result<(),()> {
|
||||||
/// ...
|
/// ...
|
||||||
|
@ -43,7 +43,37 @@ pub(crate) fn pkg_fn_to_code(
|
|||||||
asdf.into()
|
asdf.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn package(
|
pub(crate) fn package(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
|
let local = parse_macro_input!(input as ::syn::ItemStruct);
|
||||||
|
let mut path = parse_macro_input!(attrs as ::syn::Path);
|
||||||
|
|
||||||
|
let last = path.segments.last().unwrap();
|
||||||
|
if last.arguments.is_empty() {
|
||||||
|
// make sure all the packages have generics, and if not add the
|
||||||
|
// repo as generic aka: rewrite
|
||||||
|
// "#[package(my::pkg)]" -->> "#[package(my::pkg<R>)])"
|
||||||
|
// unless it's '::bok::PkgEmpty'
|
||||||
|
if path.segments.len() != 2
|
||||||
|
|| path.segments[0].ident.to_string() != "bok"
|
||||||
|
|| path.segments[1].ident.to_string() != "PkgEmpty"
|
||||||
|
{
|
||||||
|
let repo_argument = {
|
||||||
|
let generic_id: ::syn::Path = ::syn::parse_quote!(id<R>);
|
||||||
|
generic_id.segments.last().unwrap().arguments.clone()
|
||||||
|
};
|
||||||
|
path.segments.last_mut().unwrap().arguments = repo_argument;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return quote! {
|
||||||
|
use ::bok_macro::package_path;
|
||||||
|
#[::bok_macro::package_path(#path)]
|
||||||
|
#local
|
||||||
|
}
|
||||||
|
.into();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn package_path(
|
||||||
attrs: TokenStream,
|
attrs: TokenStream,
|
||||||
input: TokenStream,
|
input: TokenStream,
|
||||||
__source_path: TokenStream,
|
__source_path: TokenStream,
|
||||||
@ -183,9 +213,34 @@ pub(crate) fn deps_build(
|
|||||||
attrs: TokenStream,
|
attrs: TokenStream,
|
||||||
input: TokenStream,
|
input: TokenStream,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let packages = parse_macro_input!(attrs as crate::PathList);
|
let mut packages = parse_macro_input!(attrs as crate::PathList);
|
||||||
|
|
||||||
let local = parse_macro_input!(input as ::syn::ItemStruct);
|
let local = parse_macro_input!(input as ::syn::ItemStruct);
|
||||||
|
|
||||||
|
// make sure all the packages have generics, and if not add the repo as
|
||||||
|
// generic aka: rewrite
|
||||||
|
// "#[deps_build(my::pkg)]" -->> "#[deps_build(my::pkg<R>)])"
|
||||||
|
let mut rewrite = false;
|
||||||
|
let repo_argument = {
|
||||||
|
let generic_id: ::syn::Path = ::syn::parse_quote!(id<R>);
|
||||||
|
generic_id.segments.last().unwrap().arguments.clone()
|
||||||
|
};
|
||||||
|
for p in packages.0.iter_mut() {
|
||||||
|
let last = p.segments.last_mut().unwrap();
|
||||||
|
if last.arguments.is_empty() {
|
||||||
|
rewrite = true;
|
||||||
|
last.arguments = repo_argument.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if rewrite {
|
||||||
|
let p_list = packages.0.into_iter();
|
||||||
|
return quote! {
|
||||||
|
#[::bok::deps_build(#(#p_list,)*)]
|
||||||
|
#local
|
||||||
|
}
|
||||||
|
.into();
|
||||||
|
}
|
||||||
|
let packages = packages; // remove mut;
|
||||||
|
|
||||||
let ::syn::Fields::Named(local_fields) = local.fields else {
|
let ::syn::Fields::Named(local_fields) = local.fields else {
|
||||||
use ::syn::spanned::Spanned;
|
use ::syn::spanned::Spanned;
|
||||||
return ::syn::Error::new(
|
return ::syn::Error::new(
|
||||||
@ -240,7 +295,32 @@ pub(crate) fn package_impl(
|
|||||||
_attrs: TokenStream,
|
_attrs: TokenStream,
|
||||||
input: TokenStream,
|
input: TokenStream,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let ast = parse_macro_input!(input as ::syn::ItemImpl);
|
let mut ast = parse_macro_input!(input as ::syn::ItemImpl);
|
||||||
|
|
||||||
|
if let Some((_, trait_name, _)) = &ast.trait_ {
|
||||||
|
let s = &trait_name.segments;
|
||||||
|
if s.len() != 2
|
||||||
|
|| s[0].ident.to_string() != "bok"
|
||||||
|
|| s[1].ident.to_string() != "Pkg"
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// only add the generic parameter and nothing else
|
||||||
|
//
|
||||||
|
let t_id = &ast.self_ty;
|
||||||
|
let g: ::syn::ItemImpl = ::syn::parse_quote! {
|
||||||
|
impl<R> trait_name for #t_id<R> where R: ::bok::Repository {}
|
||||||
|
};
|
||||||
|
ast.generics = g.generics;
|
||||||
|
ast.self_ty = g.self_ty;
|
||||||
|
// TODO: if the trait is `::std::default::Default`
|
||||||
|
// then add the `_bok_base` and `_bok_repo` defaults automatically
|
||||||
|
return quote! {
|
||||||
|
#ast
|
||||||
|
}
|
||||||
|
.into();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let ast = ast; // remove mut
|
||||||
|
|
||||||
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() {
|
||||||
|
@ -236,6 +236,33 @@ pub(crate) fn repo_packages(
|
|||||||
input: TokenStream,
|
input: TokenStream,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let local = parse_macro_input!(input as ItemStruct);
|
let local = parse_macro_input!(input as ItemStruct);
|
||||||
|
let mut packages = parse_macro_input!(attrs as crate::PathList);
|
||||||
|
|
||||||
|
// make sure all the packages have generics, and if not add the repo as
|
||||||
|
// generic aka: rewrite
|
||||||
|
// "#[repo_packages(my::pkg)]" -->> "#[repo_packages(my::pkg<Self>)])"
|
||||||
|
let mut rewrite = false;
|
||||||
|
let repo_argument = {
|
||||||
|
let generic_id: ::syn::Path = ::syn::parse_quote!(id<Self>);
|
||||||
|
generic_id.segments.last().unwrap().arguments.clone()
|
||||||
|
};
|
||||||
|
for p in packages.0.iter_mut() {
|
||||||
|
let last = p.segments.last_mut().unwrap();
|
||||||
|
if last.arguments.is_empty() {
|
||||||
|
rewrite = true;
|
||||||
|
last.arguments = repo_argument.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if rewrite {
|
||||||
|
let p_list = packages.0.into_iter();
|
||||||
|
return quote! {
|
||||||
|
#[::bok::repo_packages(#(#p_list,)*)]
|
||||||
|
#local
|
||||||
|
}
|
||||||
|
.into();
|
||||||
|
}
|
||||||
|
let packages = packages; // remove mut
|
||||||
|
|
||||||
let local_attrs = local.attrs.iter();
|
let local_attrs = local.attrs.iter();
|
||||||
let (_, generics, where_clause) = local.generics.split_for_impl();
|
let (_, generics, where_clause) = local.generics.split_for_impl();
|
||||||
let ident = local.ident;
|
let ident = local.ident;
|
||||||
@ -292,8 +319,6 @@ pub(crate) fn repo_packages(
|
|||||||
})
|
})
|
||||||
.collect::<Vec<&::syn::Field>>();
|
.collect::<Vec<&::syn::Field>>();
|
||||||
|
|
||||||
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
|
||||||
// extending the repository
|
// extending the repository
|
||||||
|
@ -30,7 +30,7 @@ use ::bok::repository;
|
|||||||
///
|
///
|
||||||
/// Base repository with some packages
|
/// Base repository with some packages
|
||||||
#[::bok::repository(::bok::RepositoryEmpty)]
|
#[::bok::repository(::bok::RepositoryEmpty)]
|
||||||
#[::bok::repo_packages(pkgs::one::One<Self>)]
|
#[::bok::repo_packages(pkgs::one::One)]
|
||||||
#[derive(::std::default::Default)]
|
#[derive(::std::default::Default)]
|
||||||
pub struct Pkgs1 {
|
pub struct Pkgs1 {
|
||||||
r1: i32,
|
r1: i32,
|
||||||
@ -42,7 +42,7 @@ impl Pkgs1 {}
|
|||||||
///
|
///
|
||||||
/// This repository extends and changes Pkgs1
|
/// This repository extends and changes Pkgs1
|
||||||
#[::bok::repository(Pkgs1)]
|
#[::bok::repository(Pkgs1)]
|
||||||
#[::bok::repo_packages(pkgs::two::Two<Self>)]
|
#[::bok::repo_packages(pkgs::two::Two)]
|
||||||
#[derive(::std::default::Default)]
|
#[derive(::std::default::Default)]
|
||||||
pub struct Pkgs2 {
|
pub struct Pkgs2 {
|
||||||
r2: i32,
|
r2: i32,
|
||||||
|
@ -15,8 +15,6 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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)]
|
||||||
@ -25,10 +23,8 @@ pub struct One {
|
|||||||
pub my_attr: u32,
|
pub my_attr: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R> ::std::default::Default for One<R>
|
#[::bok::package_impl]
|
||||||
where
|
impl ::std::default::Default for One {
|
||||||
R: ::bok::Repository,
|
|
||||||
{
|
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
One {
|
One {
|
||||||
_bok_base: ::std::marker::PhantomData::default(),
|
_bok_base: ::std::marker::PhantomData::default(),
|
||||||
|
@ -15,11 +15,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use ::bok::package;
|
|
||||||
|
|
||||||
/// Example package
|
/// Example package
|
||||||
#[::bok::package(::bok::PkgEmpty)]
|
#[::bok::package(::bok::PkgEmpty)]
|
||||||
#[::bok::deps_build(super::One<R>)]
|
#[::bok::deps_build(super::One)]
|
||||||
pub struct Three {
|
pub struct Three {
|
||||||
pub my_attr: u32,
|
pub my_attr: u32,
|
||||||
}
|
}
|
||||||
|
@ -15,11 +15,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use ::bok::package;
|
|
||||||
|
|
||||||
/// Example package
|
/// Example package
|
||||||
#[::bok::package(super::one::One<R>)]
|
#[::bok::package(super::one::One)]
|
||||||
#[::bok::deps_build(super::one::One<R>)]
|
#[::bok::deps_build(super::one::One)]
|
||||||
pub struct Two {
|
pub struct Two {
|
||||||
pub my_attr2: u32,
|
pub my_attr2: u32,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user