Skip to content

Commit

Permalink
Fix some missing syn invisible group handling in FromMeta implementat…
Browse files Browse the repository at this point in the history
…ions (#263)

As of syn 2.40, syn may generate an invisible token when the input to the darling proc macro (specifically, the attributes) are generated by a macro_rules!

This update looks "through" that invisible group so parsing works as-expected.
  • Loading branch information
Ten0 committed Feb 12, 2024
1 parent 9decd6a commit 3ee36d9
Showing 1 changed file with 40 additions and 25 deletions.
65 changes: 40 additions & 25 deletions core/src/from_meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,14 @@ pub trait FromMeta: Sized {
fn from_expr(expr: &Expr) -> Result<Self> {
match *expr {
Expr::Lit(ref lit) => Self::from_value(&lit.lit),
Expr::Group(ref group) => Self::from_expr(&group.expr),
Expr::Group(ref group) => {
// syn may generate this invisible group delimiter when the input to the darling
// proc macro (specifically, the attributes) are generated by a
// macro_rules! (e.g. propagating a macro_rules!'s expr)
// Since we want to basically ignore these invisible group delimiters,
// we just propagate the call to the inner expression.
Self::from_expr(&group.expr)
}
_ => Err(Error::unexpected_expr_type(expr)),
}
.map_err(|e| e.with_span(expr))
Expand Down Expand Up @@ -292,13 +299,14 @@ impl<T: syn::parse::Parse, P: syn::parse::Parse> FromMeta for syn::punctuated::P
/// alternate parsing modes for this type.
impl FromMeta for syn::Expr {
fn from_expr(expr: &Expr) -> Result<Self> {
if let syn::Expr::Lit(expr_lit) = expr {
if let syn::Lit::Str(_) = &expr_lit.lit {
return Self::from_value(&expr_lit.lit);
}
match expr {
Expr::Lit(syn::ExprLit {
lit: lit @ syn::Lit::Str(_),
..
}) => Self::from_value(lit),
Expr::Group(group) => Self::from_expr(&group.expr), // see FromMeta::from_expr
_ => Ok(expr.clone()),
}

Ok(expr.clone())
}

fn from_string(value: &str) -> Result<Self> {
Expand Down Expand Up @@ -333,6 +341,7 @@ impl FromMeta for syn::Path {
match expr {
Expr::Lit(lit) => Self::from_value(&lit.lit),
Expr::Path(path) => Ok(path.path.clone()),
Expr::Group(group) => Self::from_expr(&group.expr), // see FromMeta::from_expr
_ => Err(Error::unexpected_expr_type(expr)),
}
}
Expand Down Expand Up @@ -361,6 +370,7 @@ impl FromMeta for syn::Ident {
Some(ident) => Ok(ident.clone()),
None => Err(Error::unexpected_expr_type(expr)),
},
Expr::Group(group) => Self::from_expr(&group.expr), // see FromMeta::from_expr
_ => Err(Error::unexpected_expr_type(expr)),
}
}
Expand All @@ -380,12 +390,11 @@ macro_rules! from_syn_expr_type {
($ty:path, $variant:ident) => {
impl FromMeta for $ty {
fn from_expr(expr: &syn::Expr) -> Result<Self> {
if let syn::Expr::$variant(body) = expr {
Ok(body.clone())
} else if let syn::Expr::Lit(expr_lit) = expr {
Self::from_value(&expr_lit.lit)
} else {
Err(Error::unexpected_expr_type(expr))
match expr {
syn::Expr::$variant(body) => Ok(body.clone()),
syn::Expr::Lit(expr_lit) => Self::from_value(&expr_lit.lit),
syn::Expr::Group(group) => Self::from_expr(&group.expr), // see FromMeta::from_expr
_ => Err(Error::unexpected_expr_type(expr)),
}
}

Expand Down Expand Up @@ -452,21 +461,27 @@ macro_rules! from_numeric_array {
/// Parsing an unsigned integer array, i.e. `example = "[1, 2, 3, 4]"`.
impl FromMeta for Vec<$ty> {
fn from_expr(expr: &syn::Expr) -> Result<Self> {
if let syn::Expr::Array(expr_array) = expr {
let v = expr_array
match expr {
syn::Expr::Array(expr_array) => expr_array
.elems
.iter()
.map(|expr| match expr {
Expr::Lit(lit) => $ty::from_value(&lit.lit),
_ => Err(Error::custom("Expected array of unsigned integers")
.with_span(expr)),
.map(|expr| {
let unexpected = || {
Error::custom("Expected array of unsigned integers").with_span(expr)
};
match expr {
Expr::Lit(lit) => $ty::from_value(&lit.lit),
Expr::Group(group) => match &*group.expr {
Expr::Lit(lit) => $ty::from_value(&lit.lit),
_ => Err(unexpected()),
},
_ => Err(unexpected()),
}
})
.collect::<Result<Vec<$ty>>>();
v
} else if let syn::Expr::Lit(expr_lit) = expr {
Self::from_value(&expr_lit.lit)
} else {
Err(Error::unexpected_expr_type(expr))
.collect::<Result<Vec<$ty>>>(),
syn::Expr::Lit(expr_lit) => Self::from_value(&expr_lit.lit),
syn::Expr::Group(group) => Self::from_expr(&group.expr), // see FromMeta::from_expr
_ => Err(Error::unexpected_expr_type(expr)),
}
}

Expand Down

0 comments on commit 3ee36d9

Please sign in to comment.