parse generics for implement macro

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk 2024-07-26 21:31:31 +00:00
parent ca82b59c6f
commit 7a3cc3941e
2 changed files with 29 additions and 15 deletions

View file

@ -1,26 +1,32 @@
use proc_macro::TokenStream;
use proc_macro::{Span, TokenStream};
use quote::quote;
use syn::{ItemFn, Meta, MetaList};
use syn::{Error, ItemFn, Meta, Path};
use utils::get_named_generics;
use crate::Result;
use crate::{utils, Result};
pub(super) fn implement(item: ItemFn, args: &[Meta]) -> Result<TokenStream> {
let Meta::List(MetaList {
path,
..
}) = &args
.first()
.expect("missing path to trait or item to implement")
else {
panic!("invalid path to item for implement");
};
let generics = get_named_generics(args, "generics")?;
let receiver = get_receiver(args)?;
let params = get_named_generics(args, "params")?;
let input = item;
let out = quote! {
impl #path {
impl #generics #receiver #params {
#input
}
};
Ok(out.into())
}
fn get_receiver(args: &[Meta]) -> Result<Path> {
let receiver = &args
.first()
.ok_or_else(|| Error::new(Span::call_site().into(), "Missing required argument to receiver"))?;
let Meta::Path(receiver) = receiver else {
return Err(Error::new(Span::call_site().into(), "First argument is not path to receiver"));
};
Ok(receiver.clone())
}

View file

@ -1,4 +1,12 @@
use syn::{Expr, Lit, Meta};
use syn::{parse_str, Expr, Generics, Lit, Meta};
use crate::Result;
pub(crate) fn get_named_generics(args: &[Meta], name: &str) -> Result<Generics> {
const DEFAULT: &str = "<>";
parse_str::<Generics>(&get_named_string(args, name).unwrap_or_else(|| DEFAULT.to_owned()))
}
pub(crate) fn get_named_string(args: &[Meta], name: &str) -> Option<String> {
args.iter().find_map(|arg| {