style: Support field_bound in #[derive(Parse)].

Differential Revision: https://phabricator.services.mozilla.com/D76268
This commit is contained in:
Emilio Cobos Álvarez 2020-05-21 13:48:36 +00:00
parent 35546aea54
commit 66185e81f6

View file

@ -15,7 +15,14 @@ pub struct ParseVariantAttrs {
pub condition: Option<Path>, pub condition: Option<Path>,
} }
#[darling(attributes(parse), default)]
#[derive(Default, FromField)]
pub struct ParseFieldAttrs {
field_bound: bool,
}
fn parse_non_keyword_variant( fn parse_non_keyword_variant(
where_clause: &mut Option<syn::WhereClause>,
name: &syn::Ident, name: &syn::Ident,
variant: &VariantInfo, variant: &VariantInfo,
variant_attrs: &CssVariantAttrs, variant_attrs: &CssVariantAttrs,
@ -32,7 +39,14 @@ fn parse_non_keyword_variant(
"We only support deriving parse for simple variants" "We only support deriving parse for simple variants"
); );
let variant_name = &variant.ast().ident; let variant_name = &variant.ast().ident;
let ty = &bindings[0].ast().ty; let binding_ast = &bindings[0].ast();
let ty = &binding_ast.ty;
let field_attrs = cg::parse_field_attrs::<ParseFieldAttrs>(binding_ast);
if field_attrs.field_bound {
cg::add_predicate(where_clause, parse_quote!(#ty: crate::parser::Parse));
}
let mut parse = if skip_try { let mut parse = if skip_try {
quote! { quote! {
let v = <#ty as crate::parser::Parse>::parse(context, input)?; let v = <#ty as crate::parser::Parse>::parse(context, input)?;
@ -67,7 +81,6 @@ fn parse_non_keyword_variant(
} }
pub fn derive(mut input: DeriveInput) -> TokenStream { pub fn derive(mut input: DeriveInput) -> TokenStream {
{
let mut where_clause = input.generics.where_clause.take(); let mut where_clause = input.generics.where_clause.take();
for param in input.generics.type_params() { for param in input.generics.type_params() {
cg::add_predicate( cg::add_predicate(
@ -75,8 +88,6 @@ pub fn derive(mut input: DeriveInput) -> TokenStream {
parse_quote!(#param: crate::parser::Parse), parse_quote!(#param: crate::parser::Parse),
); );
} }
input.generics.where_clause = where_clause;
}
let name = &input.ident; let name = &input.ident;
let s = Structure::new(&input); let s = Structure::new(&input);
@ -88,12 +99,13 @@ pub fn derive(mut input: DeriveInput) -> TokenStream {
let mut effective_variants = 0; let mut effective_variants = 0;
for variant in s.variants().iter() { for variant in s.variants().iter() {
let css_variant_attrs = cg::parse_variant_attrs_from_ast::<CssVariantAttrs>(&variant.ast()); let css_variant_attrs = cg::parse_variant_attrs_from_ast::<CssVariantAttrs>(&variant.ast());
let parse_attrs = cg::parse_variant_attrs_from_ast::<ParseVariantAttrs>(&variant.ast());
if css_variant_attrs.skip { if css_variant_attrs.skip {
continue; continue;
} }
effective_variants += 1; effective_variants += 1;
let parse_attrs = cg::parse_variant_attrs_from_ast::<ParseVariantAttrs>(&variant.ast());
saw_condition |= parse_attrs.condition.is_some(); saw_condition |= parse_attrs.condition.is_some();
if !variant.bindings().is_empty() { if !variant.bindings().is_empty() {
@ -143,7 +155,7 @@ pub fn derive(mut input: DeriveInput) -> TokenStream {
for (i, (variant, css_attrs, parse_attrs)) in non_keywords.iter().enumerate() { for (i, (variant, css_attrs, parse_attrs)) in non_keywords.iter().enumerate() {
let skip_try = !has_keywords && i == non_keywords.len() - 1; let skip_try = !has_keywords && i == non_keywords.len() - 1;
let parse_variant = let parse_variant =
parse_non_keyword_variant(name, variant, css_attrs, parse_attrs, skip_try); parse_non_keyword_variant(&mut where_clause, name, variant, css_attrs, parse_attrs, skip_try);
parse_non_keywords.extend(parse_variant); parse_non_keywords.extend(parse_variant);
} }
@ -171,6 +183,9 @@ pub fn derive(mut input: DeriveInput) -> TokenStream {
quote! { Self::parse(input) } quote! { Self::parse(input) }
}; };
let has_non_keywords = !non_keywords.is_empty();
input.generics.where_clause = where_clause;
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let parse_trait_impl = quote! { let parse_trait_impl = quote! {
@ -189,7 +204,7 @@ pub fn derive(mut input: DeriveInput) -> TokenStream {
return parse_trait_impl; return parse_trait_impl;
} }
assert!(non_keywords.is_empty()); assert!(!has_non_keywords);
// TODO(emilio): It'd be nice to get rid of these, but that makes the // TODO(emilio): It'd be nice to get rid of these, but that makes the
// conversion harder... // conversion harder...