Skip to content

Commit e19aa02

Browse files
committed
Take 2
1 parent aadae83 commit e19aa02

File tree

2 files changed

+31
-25
lines changed

2 files changed

+31
-25
lines changed

derive/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ edition = "2021"
1818
proc-macro = true
1919

2020
[dependencies]
21-
syn = { version = "2.0", features = ["full", "visit", "visit-mut"] }
21+
syn = { version = "2.0", features = ["parsing"] }
2222
proc-macro2 = "1.0"
2323
quote = "1.0"

derive/src/lib.rs

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ use proc_macro2::TokenStream;
22
use quote::{format_ident, quote, quote_spanned, ToTokens};
33
use syn::spanned::Spanned;
44
use syn::{
5-
parse_macro_input, parse_quote, Attribute, Data, DeriveInput, Expr, ExprLit, ExprPath,
6-
Fields, GenericParam, Generics, Ident, Index, Lit, Meta, MetaNameValue,
5+
parse::{Parse, ParseStream},
6+
parse_macro_input, parse_quote, Attribute, Data, DeriveInput,
7+
Fields, GenericParam, Generics, Ident, Index, LitStr, Meta, Token
78
};
89

910

@@ -78,36 +79,41 @@ struct Attributes {
7879
with: Option<Ident>,
7980
}
8081

82+
struct WithIdent {
83+
with: Option<Ident>,
84+
}
85+
impl Parse for WithIdent {
86+
fn parse(input: ParseStream) -> Result<Self, syn::Error> {
87+
let mut result = WithIdent { with: None };
88+
let ident = input.parse::<Ident>()?;
89+
if ident != "with" {
90+
return Err(syn::Error::new(ident.span(), "Expected identifier to be `with`"));
91+
}
92+
input.parse::<Token!(=)>()?;
93+
let s = input.parse::<LitStr>()?;
94+
result.with = Some(format_ident!("{}", s.value(), span = s.span()));
95+
Ok(result)
96+
}
97+
}
98+
8199
impl Attributes {
82100
fn parse(attrs: &[Attribute]) -> Self {
83101
let mut out = Self::default();
84102
for attr in attrs {
85-
if let Meta::NameValue(ref namevalue) = attr.meta {
86-
if namevalue.path.is_ident("visit") {
87-
out.parse_name_value(namevalue);
88-
}
89-
}
90-
}
91-
if out.with.is_none() {
92-
panic!("Expected #[visit(...)]");
93-
}
94-
out
95-
}
96-
97-
/// Updates self with a name value attribute
98-
fn parse_name_value(&mut self, v: &MetaNameValue) {
99-
if let Expr::Assign(ref assign) = v.value {
100-
if let Expr::Path(ExprPath { ref path, .. }) = *assign.left {
101-
if path.is_ident("with") {
102-
match *assign.right {
103-
Expr::Lit(ExprLit { lit: Lit::Str(ref s), .. }) => self.with = Some(format_ident!("{}", s.value(), span = s.span())),
104-
_ => panic!("Expected a string value, got {}", v.value.to_token_stream()),
103+
if let Meta::List(ref metalist) = attr.meta {
104+
if metalist.path.is_ident("visit") {
105+
match syn::parse2::<WithIdent>(metalist.tokens.clone()) {
106+
Ok(with_ident) => {
107+
out.with = with_ident.with;
108+
}
109+
Err(e) => {
110+
panic!("{}", e);
111+
}
105112
}
106-
return;
107113
}
108114
}
109115
}
110-
panic!("Unrecognised kv attribute {}", v.to_token_stream())
116+
out
111117
}
112118

113119
/// Returns the pre and post visit token streams

0 commit comments

Comments
 (0)