diff options
| author | John Turner <jturner.usa@gmail.com> | 2023-04-19 02:57:03 -0400 |
|---|---|---|
| committer | John Turner <jturner.usa@gmail.com> | 2023-04-19 02:57:03 -0400 |
| commit | 4038d8be9593d556412ce9705a324785f7d9e125 (patch) | |
| tree | 63c8133cb1401f387976ec7d69bf790eb1a30298 | |
| parent | 0439506dcfb639bd494248450f7686b0a31580d3 (diff) | |
| download | get-4038d8be9593d556412ce9705a324785f7d9e125.tar.gz | |
refactored code with if_chain
Adding a separate error for the case of an empty attribute list allows the code to
be less complicated and gives better diagnostics. Otherwise another
nested block would be required.
| -rw-r--r-- | src/lib.rs | 66 | ||||
| -rw-r--r-- | tests/trybuild/invalid-attribute.stderr | 2 |
2 files changed, 34 insertions, 34 deletions
@@ -8,6 +8,7 @@ pub fn get(input: proc_macro::TokenStream) -> proc_macro::TokenStream { mod get { + use if_chain::if_chain; use proc_macro2::{Span, TokenStream}; use quote::{format_ident, quote, ToTokens}; use syn::{ @@ -133,47 +134,46 @@ mod get { impl TryFrom<Attribute> for GetAttribute { type Error = Box<dyn std::error::Error>; fn try_from(attr: Attribute) -> Result<Self, Self::Error> { - if attr.path().is_ident("get") { - if let Meta::List(meta_list) = &attr.meta { - if let Ok(meta_name_values) = - Punctuated::<MetaNameValue, Token![,]>::parse_terminated - .parse(meta_list.tokens.clone().into()) - { - let get_name_values = meta_name_values - .iter() - .map(|n| n.try_into()) - .collect::<Result<Vec<GetNameValue>, _>>()?; - if let 1..=3 = get_name_values.len() { - return Ok(get_name_values.into_iter().fold( - Self::default(), - |_, g| match g { - GetNameValue::Method(name) => Self { method: Some(name) }, - }, - )); - } - } + if_chain! { + if attr.path().is_ident("get"); + if let Meta::List(list) = &attr.meta; + then { + Ok(Punctuated::<MetaNameValue, Token![,]>::parse_terminated + .parse(list.tokens.clone().into())? + .into_iter() + .map(|n| n.try_into()) + .collect::<Result<Vec<GetNameValue>, _>>() + .map(|v| match v.len() { + 1..=3 => Ok(v), + _ => Err("expected at least 1 name value pair in attribute") + })?? + .into_iter() + .fold(Self::default(), |_, n| match n { + GetNameValue::Method(s) => Self { + method: Some(s), + }, + })) + } else { + Err("failed to parse attribute".into()) } } - Err("failed to parse attribute".into()) } } - // The same applies here. - - impl<'a> TryFrom<&'a MetaNameValue> for GetNameValue { + impl TryFrom<MetaNameValue> for GetNameValue { type Error = Box<dyn std::error::Error>; - fn try_from(meta: &'a MetaNameValue) -> Result<Self, Self::Error> { - if let Some(name) = meta.path.get_ident().map(|i| i.to_string()) { - if let Expr::Lit(expr_lit) = &meta.value { - if let Lit::Str(s) = &expr_lit.lit { - let value = s.value(); - if let "method" = name.as_str() { - return Ok(Self::Method(value)); - }; - } + fn try_from(meta: MetaNameValue) -> Result<Self, Self::Error> { + if_chain! { + if let Some(name) = meta.path.get_ident().map(|ident| ident.to_string()); + if let Expr::Lit(expr) = &meta.value; + if let Lit::Str(s) = &expr.lit; + if let "method" = name.as_str(); + then { + Ok(Self::Method(s.value())) + } else { + Err("invalid name value list in attribute".into()) } } - Err("invalid name value list in attribute".into()) } } } diff --git a/tests/trybuild/invalid-attribute.stderr b/tests/trybuild/invalid-attribute.stderr index 426cc06..e408bb0 100644 --- a/tests/trybuild/invalid-attribute.stderr +++ b/tests/trybuild/invalid-attribute.stderr @@ -4,7 +4,7 @@ error: proc-macro derive panicked 3 | #[derive(Get)] | ^^^ | - = help: message: called `Result::unwrap()` on an `Err` value: "failed to parse attribute" + = help: message: called `Result::unwrap()` on an `Err` value: "expected at least 1 name value pair in attribute" error: proc-macro derive panicked --> tests/trybuild/invalid-attribute.rs:9:10 |
