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 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> { pub(super) fn implement(item: ItemFn, args: &[Meta]) -> Result<TokenStream> {
let Meta::List(MetaList { let generics = get_named_generics(args, "generics")?;
path, let receiver = get_receiver(args)?;
.. let params = get_named_generics(args, "params")?;
}) = &args
.first()
.expect("missing path to trait or item to implement")
else {
panic!("invalid path to item for implement");
};
let input = item; let input = item;
let out = quote! { let out = quote! {
impl #path { impl #generics #receiver #params {
#input #input
} }
}; };
Ok(out.into()) 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> { pub(crate) fn get_named_string(args: &[Meta], name: &str) -> Option<String> {
args.iter().find_map(|arg| { args.iter().find_map(|arg| {