syn
syn copied to clipboard
Should syn have convenience functions for (derive) macros?
There's a few things I often need while writing a derive macro, which I keep writing small helper functions for. I'm wondering if these should be part of syn
, or if they should go in a separate crate.
An example:
I often want to iterate over the Member
s of a list of Fields
, such that Unit
results in an empty iterator, Tuple
results in Unnamed(0)
, Unnamed(1)
, etc., and Struct
results in Named("field1")
, Named("field2")
etc. This makes it easy to use e.g. quote!{ #structname { #( #member: Trait::thing(), )* } }
and have it work for all three kinds of structs.
(Concrete use case example: It'd reduce this match
to just a single case.)
This doesn't seem to exactly fit with the rest of syn
, because the tuple indexes (0
, 1
, ..) don't occur in the source code, but are generated for the convenience of proc macros.
A second example:
An .expect_struct()
on Data
that would return a Result<DataStruct>
, containing a nice error in case of an enum or union (with the span set to the enum or union token). (Or a .expect_unit()
on Fields
, etc.)
I have a few more examples like this. But I first wanted to ask the general question: Would syn
be the right place for functions like this, or should syn
only focus on parsing and keep other functionality to a minimum?
One that I had to use recently was on Data
to get the span of the token, such as
pub trait ToSpan {
fn to_span(self) -> Span;
}
impl ToSpan for Data {
fn to_span(self) -> Span {
match self {
Data::Struct(d) => d.struct_token.span(),
Data::Enum(d) => d.enum_token.span(),
Data::Union(d) => d.union_token.span(),
}
}
}
Now I realize that implementing syn::spanned::Spanned
on Data is quite complex and should give the entire definition, a helper method Data.token_span()
or something like that would be really great.
I found myself reaching for a number of conveniences that were outside syn
's stated scope, which led me to create darling
. In this particular case, you may find darling::ast::Data
helpful.
They need to go in a separate crate. The suggestion of adding various conveniences would make this crate effectively unbounded in scope which is not appealing to me or the users who rely on it to compile fast.