diff options
Diffstat (limited to 'subplotlib-derive/src/lib.rs')
-rw-r--r-- | subplotlib-derive/src/lib.rs | 54 |
1 files changed, 39 insertions, 15 deletions
diff --git a/subplotlib-derive/src/lib.rs b/subplotlib-derive/src/lib.rs index 7fd1810..8e18c98 100644 --- a/subplotlib-derive/src/lib.rs +++ b/subplotlib-derive/src/lib.rs @@ -1,5 +1,6 @@ use proc_macro::TokenStream; use proc_macro2::Span; +use std::fmt::Write; use syn::{ parse_macro_input, parse_quote, Error, FnArg, Ident, ItemFn, Pat, PathArguments, ReturnType, Type, @@ -7,7 +8,7 @@ use syn::{ use quote::quote; -use fehler::{throw, throws}; +use culpa::{throw, throws}; fn ty_is_borrow_str(ty: &Type) -> bool { if let Type::Reference(ty) = ty { @@ -28,6 +29,25 @@ fn ty_is_borrow_str(ty: &Type) -> bool { } } +fn ty_is_borrow_path(ty: &Type) -> bool { + if let Type::Reference(ty) = ty { + if ty.mutability.is_none() && ty.lifetime.is_none() { + if let Type::Path(pp) = &*ty.elem { + pp.path.is_ident("Path") + } else { + // not a path, so not &Path + false + } + } else { + // mutable, or a lifetime stated, so not &Path + false + } + } else { + // Not & so not &Path + false + } +} + fn ty_is_datafile(ty: &Type) -> bool { if let Type::Path(ty) = ty { ty.path.is_ident("SubplotDataFile") @@ -189,19 +209,19 @@ fn process_step(mut input: ItemFn) -> proc_macro2::TokenStream { let contexts: Vec<Type> = input .attrs .iter() - .filter(|attr| attr.path.is_ident("context")) + .filter(|attr| attr.path().is_ident("context")) .map(|attr| { let ty: Type = attr.parse_args()?; Ok(ty) }) .collect::<Result<_, Error>>()?; - input.attrs.retain(|f| !f.path.is_ident("context")); + input.attrs.retain(|f| !f.path().is_ident("context")); let docs: Vec<_> = input .attrs .iter() - .filter(|attr| attr.path.is_ident("doc")) + .filter(|attr| attr.path().is_ident("doc")) .collect(); let fields = input @@ -241,6 +261,8 @@ fn process_step(mut input: ItemFn) -> proc_macro2::TokenStream { .map(|(id, ty)| { let ty = if ty_is_borrow_str(ty) { parse_quote!(::std::string::String) + } else if ty_is_borrow_path(ty) { + parse_quote!(::std::path::PathBuf) } else { ty.clone() }; @@ -277,6 +299,13 @@ fn process_step(mut input: ItemFn) -> proc_macro2::TokenStream { self } } + } else if ty_is_borrow_path(ty) { + quote! { + pub fn #id<P: Into<std::path::PathBuf>>(mut self, value: P) -> Self { + self.#id = value.into(); + self + } + } } else { quote! { pub fn #id(mut self, value: #ty) -> Self { @@ -291,7 +320,7 @@ fn process_step(mut input: ItemFn) -> proc_macro2::TokenStream { let buildargs: Vec<_> = fields .iter() .map(|(id, ty)| { - if ty_is_borrow_str(ty) { + if ty_is_borrow_str(ty) || ty_is_borrow_path(ty) { quote! { &self.#id } @@ -321,10 +350,11 @@ fn process_step(mut input: ItemFn) -> proc_macro2::TokenStream { impl Builder { #(#fieldfns)* - pub fn build(self, step_text: String) -> ScenarioStep { + pub fn build(self, step_text: String, location: &'static str) -> ScenarioStep { ScenarioStep::new(step_text, move |ctx, _defuse_poison| #builder_body, - |scenario| register_contexts(scenario) + |scenario| register_contexts(scenario), + location, ) } } @@ -372,12 +402,9 @@ fn process_step(mut input: ItemFn) -> proc_macro2::TokenStream { Some(&contexttype) }; for context in outer_ctx.into_iter().chain(contexts.iter()) { - contextattrs.push_str(&format!("\n #[context({:?})]", ty_as_path(context)?)); + write!(contextattrs, "\n #[context({:?})]", ty_as_path(context)?).unwrap(); } - let func_args: Vec<_> = fields - .iter() - .map(|(ident, _)| format!("{}", ident)) - .collect(); + let func_args: Vec<_> = fields.iter().map(|(ident, _)| format!("{ident}")).collect(); let func_args = func_args.join(", "); format!( r#" @@ -395,9 +422,6 @@ fn process_step(mut input: ItemFn) -> proc_macro2::TokenStream { }} ``` "#, - stepname = stepname, - contextattrs = contextattrs, - func_args = func_args, ) }; let ret = quote! { |