aboutsummaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs94
1 files changed, 13 insertions, 81 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 1cf086c..ace708c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -3,13 +3,10 @@
use std::collections::HashMap;
use proc_macro::TokenStream;
-use proc_macro2::Group;
use quote::format_ident;
use quote::quote;
use quote::quote_spanned;
use quote::ToTokens;
-use syn::parenthesized;
-use syn::parse::Parse;
use syn::parse_macro_input;
use syn::spanned::Spanned;
use syn::token::Brace;
@@ -18,20 +15,16 @@ use syn::token::Lt;
use syn::token::Trait;
use syn::AngleBracketedGenericArguments;
use syn::Block;
-use syn::Error;
use syn::Expr;
use syn::GenericArgument;
use syn::GenericParam;
-use syn::Ident;
use syn::ImplItemMethod;
use syn::ItemTrait;
-use syn::LitInt;
use syn::Path;
use syn::PathArguments;
use syn::PathSegment;
use syn::Signature;
use syn::Stmt;
-use syn::Token;
use syn::TraitBound;
use syn::TraitItem;
use syn::TraitItemMethod;
@@ -44,6 +37,7 @@ use syn_utils::TypeOrPath;
use crate::parse_assoc_type::parse_assoc_type;
use crate::parse_assoc_type::AssocTypeError;
+use crate::parse_attrs::TraitAttrs;
use crate::syn_utils::iter_path;
use crate::syn_utils::trait_bounds;
use crate::trait_sig::convert_trait_signature;
@@ -54,6 +48,7 @@ use crate::transform::TransformError;
use crate::transform::TypeConverter;
mod parse_assoc_type;
+mod parse_attrs;
mod syn_utils;
mod trait_sig;
mod transform;
@@ -66,30 +61,6 @@ macro_rules! abort {
}};
}
-struct Collection {
- id: Ident,
- count: usize,
-}
-
-impl Parse for Collection {
- fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
- let inner;
- parenthesized!(inner in input);
-
- let id: Ident = inner.parse()?;
- let _: Token![,] = inner.parse()?;
- let count_lit: LitInt = inner.parse()?;
- let count: usize = count_lit.base10_parse()?;
- if count < 1 {
- return Err(Error::new(
- count_lit.span(),
- "number of type parameters must be >= 1",
- ));
- }
- Ok(Self { id, count })
- }
-}
-
#[proc_macro_attribute]
pub fn dynamize(_attr: TokenStream, input: TokenStream) -> TokenStream {
let mut original_trait = parse_macro_input!(input as ItemTrait);
@@ -108,57 +79,15 @@ pub fn dynamize(_attr: TokenStream, input: TokenStream) -> TokenStream {
}
}
- let mut type_converter = TypeConverter::default();
-
- let mut blanket_impl_attrs = Vec::new();
- let mut dyn_trait_attrs = Vec::new();
+ let method_attrs = match TraitAttrs::parse(&mut original_trait.attrs) {
+ Ok(attrs) => attrs,
+ Err(err) => return err.to_compile_error().into(),
+ };
- // FUTURE: use Vec::drain_filter once it's stable
- let mut i = 0;
- while i < original_trait.attrs.len() {
- if original_trait.attrs[i].path.is_ident("blanket_impl_attr") {
- let attr = original_trait.attrs.remove(i);
- let group: Group = match syn::parse2(attr.tokens) {
- Ok(g) => g,
- Err(err) => {
- return abort!(
- err.span(),
- "expected parenthesis: #[blanket_impl_attr(...)]"
- )
- }
- };
- let tokens = group.stream();
- blanket_impl_attrs.push(quote! {#[#tokens]});
- } else if original_trait.attrs[i].path.is_ident("dyn_trait_attr") {
- let attr = original_trait.attrs.remove(i);
- let group: Group = match syn::parse2(attr.tokens) {
- Ok(g) => g,
- Err(err) => {
- return abort!(err.span(), "expected parenthesis: #[dyn_trait_attr(...)]")
- }
- };
- let tokens = group.stream();
- dyn_trait_attrs.push(quote! {#[#tokens]});
- } else if original_trait.attrs[i].path.is_ident("collection") {
- let attr = original_trait.attrs.remove(i);
- let tokens = attr.tokens.into();
- let coll = parse_macro_input!(tokens as Collection);
-
- if type_converter
- .collections
- .insert(coll.id.clone(), coll.count)
- .is_some()
- {
- return abort!(
- coll.id.span(),
- "collection `{}` is defined multiple times for this trait",
- coll.id
- );
- }
- } else {
- i += 1;
- }
- }
+ let mut type_converter = TypeConverter {
+ collections: method_attrs.collections,
+ ..TypeConverter::default()
+ };
for item in &original_trait.items {
if let TraitItem::Type(assoc_type) = item {
@@ -393,6 +322,9 @@ pub fn dynamize(_attr: TokenStream, input: TokenStream) -> TokenStream {
let dyn_trait_name = &dyn_trait.ident;
let (impl_generics, ty_generics, where_clause) = dyn_trait.generics.split_for_impl();
+ let dyn_trait_attrs = method_attrs.dyn_trait_attrs;
+ let blanket_impl_attrs = method_attrs.blanket_impl_attrs;
+
let expanded = quote! {
#original_trait