diff options
author | Bastien Orivel <eijebong@bananium.fr> | 2018-02-12 16:49:28 +0100 |
---|---|---|
committer | Bastien Orivel <eijebong@bananium.fr> | 2018-02-12 17:08:55 +0100 |
commit | 9faa579c892ed4e45faf40a161e42da95a11f14c (patch) | |
tree | ee731f096a36c8e631374648345cff6e79562a69 /components/style_derive | |
parent | cf6330b6c169273d5c0de7b6e39dbd9d48c36111 (diff) | |
download | servo-9faa579c892ed4e45faf40a161e42da95a11f14c.tar.gz servo-9faa579c892ed4e45faf40a161e42da95a11f14c.zip |
Bump syn/quote in style_derive
Diffstat (limited to 'components/style_derive')
-rw-r--r-- | components/style_derive/Cargo.toml | 8 | ||||
-rw-r--r-- | components/style_derive/animate.rs | 53 | ||||
-rw-r--r-- | components/style_derive/cg.rs | 353 | ||||
-rw-r--r-- | components/style_derive/compute_squared_distance.rs | 38 | ||||
-rw-r--r-- | components/style_derive/lib.rs | 30 | ||||
-rw-r--r-- | components/style_derive/parse.rs | 24 | ||||
-rw-r--r-- | components/style_derive/to_animated_value.rs | 8 | ||||
-rw-r--r-- | components/style_derive/to_animated_zero.rs | 31 | ||||
-rw-r--r-- | components/style_derive/to_computed_value.rs | 20 | ||||
-rw-r--r-- | components/style_derive/to_css.rs | 29 |
10 files changed, 285 insertions, 309 deletions
diff --git a/components/style_derive/Cargo.toml b/components/style_derive/Cargo.toml index 69a62535aaa..c3435d3a92a 100644 --- a/components/style_derive/Cargo.toml +++ b/components/style_derive/Cargo.toml @@ -10,7 +10,7 @@ path = "lib.rs" proc-macro = true [dependencies] -darling = "0.2" -quote = "0.3.15" -syn = { version = "0.11", features = ["visit"] } -synstructure = "0.5.2" +darling = "0.3" +quote = "0.4.2" +syn = { version = "0.12.12", features = ["visit"] } +synstructure = "0.7" diff --git a/components/style_derive/animate.rs b/components/style_derive/animate.rs index d4fe5c94a53..ddf3cf1ec91 100644 --- a/components/style_derive/animate.rs +++ b/components/style_derive/animate.rs @@ -5,41 +5,41 @@ use cg; use quote::Tokens; use syn::{DeriveInput, Path}; +use synstructure; pub fn derive(input: DeriveInput) -> Tokens { let name = &input.ident; - let trait_path = &["values", "animated", "Animate"]; + let trait_path = parse_quote!(values::animated::Animate); let (impl_generics, ty_generics, mut where_clause) = - cg::trait_parts(&input, trait_path); + cg::trait_parts(&input, &trait_path); let input_attrs = cg::parse_input_attrs::<AnimateInputAttrs>(&input); - let variants = cg::variants(&input); - let mut match_body = quote!(); - let mut append_error_clause = variants.len() > 1; - match_body.append_all(variants.iter().flat_map(|variant| { - let variant_attrs = cg::parse_variant_attrs::<AnimationVariantAttrs>(variant); + let s = synstructure::Structure::new(&input); + let mut append_error_clause = s.variants().len() > 1; + + let mut match_body = s.variants().iter().fold(quote!(), |body, variant| { + let variant_attrs = cg::parse_variant_attrs::<AnimationVariantAttrs>(&variant.ast()); if variant_attrs.error { append_error_clause = true; - return None; + return body; } - let name = cg::variant_ctor(&input, variant); - let (this_pattern, this_info) = cg::ref_pattern(&name, variant, "this"); - let (other_pattern, other_info) = cg::ref_pattern(&name, variant, "other"); - let (result_value, result_info) = cg::value(&name, variant, "result"); + let (this_pattern, this_info) = cg::ref_pattern(&variant, "this"); + let (other_pattern, other_info) = cg::ref_pattern(&variant, "other"); + let (result_value, result_info) = cg::value(&variant, "result"); let mut computations = quote!(); let iter = result_info.iter().zip(this_info.iter().zip(&other_info)); computations.append_all(iter.map(|(result, (this, other))| { - let field_attrs = cg::parse_field_attrs::<AnimationFieldAttrs>(&result.field); + let field_attrs = cg::parse_field_attrs::<AnimationFieldAttrs>(&result.ast()); if field_attrs.constant { - if cg::is_parameterized(&result.field.ty, where_clause.params, None) { - where_clause.inner.predicates.push(cg::where_predicate( - result.field.ty.clone(), - &["std", "cmp", "PartialEq"], + if cg::is_parameterized(&result.ast().ty, &where_clause.params, None) { + where_clause.add_predicate(cg::where_predicate( + result.ast().ty.clone(), + &parse_quote!(std::cmp::PartialEq), None, )); - where_clause.inner.predicates.push(cg::where_predicate( - result.field.ty.clone(), - &["std", "clone", "Clone"], + where_clause.add_predicate(cg::where_predicate( + result.ast().ty.clone(), + &parse_quote!(std::clone::Clone), None, )); } @@ -50,28 +50,29 @@ pub fn derive(input: DeriveInput) -> Tokens { let #result = ::std::clone::Clone::clone(#this); } } else { - where_clause.add_trait_bound(&result.field.ty); + where_clause.add_trait_bound(&result.ast().ty); quote! { let #result = ::values::animated::Animate::animate(#this, #other, procedure)?; } } })); - Some(quote! { + quote! { + #body (&#this_pattern, &#other_pattern) => { #computations Ok(#result_value) } - }) - })); + } + }); if append_error_clause { if let Some(fallback) = input_attrs.fallback { - match_body.append(quote! { + match_body.append_all(quote! { (this, other) => #fallback(this, other, procedure) }); } else { - match_body.append(quote! { _ => Err(()) }); + match_body.append_all(quote! { _ => Err(()) }); } } diff --git a/components/style_derive/cg.rs b/components/style_derive/cg.rs index aa18fc45d10..3ed23226588 100644 --- a/components/style_derive/cg.rs +++ b/components/style_derive/cg.rs @@ -4,22 +4,21 @@ use darling::{FromDeriveInput, FromField, FromVariant}; use quote::{ToTokens, Tokens}; -use std::borrow::Cow; use std::collections::HashSet; -use std::iter; -use syn::{self, AngleBracketedParameterData, Body, DeriveInput, Field, Ident}; -use syn::{ImplGenerics, Path, PathParameters, PathSegment, PolyTraitRef}; -use syn::{QSelf, TraitBoundModifier, Ty, TyGenerics, TyParam, TyParamBound}; -use syn::{TypeBinding, Variant, WhereBoundPredicate, WherePredicate}; -use syn::visit::{self, Visitor}; -use synstructure::{self, BindOpts, BindStyle, BindingInfo}; +use syn::{self, DeriveInput, Field, Ident}; +use syn::{ImplGenerics, Path, PathArguments, PathSegment, AngleBracketedGenericArguments, GenericParam}; +use syn::{QSelf, Type, TypeGenerics, TypeParam}; +use syn::{TypeSlice, TypeArray, TypeTuple, TypePath, TypeParen}; +use syn::{Variant, WherePredicate, GenericArgument, Binding}; +use syn::visit::{self, Visit}; +use synstructure::{self, BindingInfo, BindStyle, VariantAst, VariantInfo}; pub struct WhereClause<'input, 'path> { - pub inner: syn::WhereClause, - pub params: &'input [TyParam], - trait_path: &'path [&'path str], - trait_output: Option<&'path str>, - bounded_types: HashSet<Ty>, + pub inner: Option<syn::WhereClause>, + pub params: Vec<&'input TypeParam>, + trait_path: &'path Path, + trait_output: Option<Ident>, + bounded_types: HashSet<Type>, } impl<'input, 'path> ToTokens for WhereClause<'input, 'path> { @@ -29,14 +28,13 @@ impl<'input, 'path> ToTokens for WhereClause<'input, 'path> { } impl<'input, 'path> WhereClause<'input, 'path> { - pub fn add_trait_bound(&mut self, ty: &Ty) { + pub fn add_trait_bound(&mut self, ty: &Type) { let trait_path = self.trait_path; - let params = self.params; let mut found = self.trait_output.map(|_| HashSet::new()); if self.bounded_types.contains(&ty) { return; } - if !is_parameterized(&ty, params, found.as_mut()) { + if !is_parameterized(&ty, &self.params, found.as_mut()) { return; } self.bounded_types.insert(ty.clone()); @@ -44,19 +42,19 @@ impl<'input, 'path> WhereClause<'input, 'path> { let output = if let Some(output) = self.trait_output { output } else { - self.inner.predicates.push(where_predicate(ty.clone(), trait_path, None)); + self.add_predicate(where_predicate(ty.clone(), trait_path, None)); return; }; - if let Ty::Path(None, ref path) = *ty { + if let Type::Path(syn::TypePath { ref path, .. }) = *ty { if path_to_ident(path).is_some() { - self.inner.predicates.push(where_predicate(ty.clone(), trait_path, None)); + self.add_predicate(where_predicate(ty.clone(), trait_path, None)); return; } } - let output_type = map_type_params(ty, params, &mut |ident| { - let ty = Ty::Path(None, ident.clone().into()); + let output_type = map_type_params(ty, &self.params, &mut |ident| { + let ty = Type::Path(syn::TypePath { qself: None, path: ident.clone().into() }); fmap_output_type(ty, trait_path, output) }); @@ -66,20 +64,29 @@ impl<'input, 'path> WhereClause<'input, 'path> { Some((output, output_type)), ); - self.inner.predicates.push(pred); + self.add_predicate(pred); if let Some(found) = found { for ident in found { - let ty = Ty::Path(None, ident.into()); + let ty = Type::Path(syn::TypePath { qself: None, path: ident.into() }); if !self.bounded_types.contains(&ty) { self.bounded_types.insert(ty.clone()); - self.inner.predicates.push( + self.add_predicate( where_predicate(ty, trait_path, None), ); }; } } } + + pub fn add_predicate(&mut self, pred: WherePredicate) { + if let Some(ref mut inner) = self.inner { + inner.predicates.push(pred); + } else { + self.inner = Some(parse_quote!(where)); + self.add_predicate(pred); + } + } } pub fn fmap_match<F>( @@ -90,71 +97,77 @@ pub fn fmap_match<F>( where F: FnMut(BindingInfo) -> Tokens, { - synstructure::each_variant(input, &bind_style.into(), |fields, variant| { - let name = variant_ctor(input, variant); - let (mapped, mapped_fields) = value(&name, variant, "mapped"); - let fields_pairs = fields.into_iter().zip(mapped_fields); + let mut s = synstructure::Structure::new(input); + s.variants_mut().iter_mut().for_each(|v| { v.bind_with(|_| bind_style); }); + s.each_variant(|variant| { + let (mapped, mapped_fields) = value(variant, "mapped"); + let fields_pairs = variant.bindings().into_iter().zip(mapped_fields); let mut computations = quote!(); computations.append_all(fields_pairs.map(|(field, mapped_field)| { - let expr = f(field); + let expr = f(field.clone()); quote! { let #mapped_field = #expr; } })); - computations.append(mapped); + computations.append_all(mapped); Some(computations) }) } fn fmap_output_type( - ty: Ty, - trait_path: &[&str], - trait_output: &str, -) -> Ty { - Ty::Path( - Some(QSelf { - ty: Box::new(ty), - position: trait_path.len(), - }), - path(trait_path.iter().chain(iter::once(&trait_output))), - ) + ty: Type, + trait_path: &Path, + trait_output: Ident, +) -> Type { + parse_quote!(<#ty as ::#trait_path>::#trait_output) } pub fn fmap_trait_parts<'input, 'path>( input: &'input DeriveInput, - trait_path: &'path [&'path str], - trait_output: &'path str, -) -> (ImplGenerics<'input>, TyGenerics<'input>, WhereClause<'input, 'path>, Path) { + trait_path: &'path Path, + trait_output: Ident, +) -> (ImplGenerics<'input>, TypeGenerics<'input>, WhereClause<'input, 'path>, Path) { let (impl_generics, ty_generics, mut where_clause) = trait_parts(input, trait_path); where_clause.trait_output = Some(trait_output); let output_ty = PathSegment { ident: input.ident.clone(), - parameters: PathParameters::AngleBracketed(AngleBracketedParameterData { - lifetimes: input.generics.lifetimes.iter().map(|l| l.lifetime.clone()).collect(), - types: input.generics.ty_params.iter().map(|ty| { - fmap_output_type( - Ty::Path(None, ty.ident.clone().into()), - trait_path, - trait_output, - ) + arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments { + args: input.generics.params.iter().map(|arg| { + match arg { + &GenericParam::Lifetime(ref data) => GenericArgument::Lifetime(data.lifetime.clone()), + &GenericParam::Type(ref data) => { + let ident = data.ident; + GenericArgument::Type( + fmap_output_type( + parse_quote!(#ident), + trait_path, + trait_output + ) + ) + }, + ref arg => panic!("arguments {:?} cannot be mapped yet", arg) + } }).collect(), - .. Default::default() - }), - }.into(); - (impl_generics, ty_generics, where_clause, output_ty) + colon2_token: Default::default(), + gt_token: Default::default(), + lt_token: Default::default(), + + }) + }; + (impl_generics, ty_generics, where_clause, output_ty.into()) } pub fn is_parameterized( - ty: &Ty, - params: &[TyParam], + ty: &Type, + params: &[&TypeParam], found: Option<&mut HashSet<Ident>>, ) -> bool { struct IsParameterized<'a, 'b> { - params: &'a [TyParam], + params: &'a [&'a TypeParam], has_free: bool, found: Option<&'b mut HashSet<Ident>>, } - impl<'a, 'b> Visitor for IsParameterized<'a, 'b> { - fn visit_path(&mut self, path: &Path) { + impl<'a, 'b, 'ast> Visit<'ast> for IsParameterized<'a, 'b> { + fn visit_path(&mut self, path: &'ast Path) { if let Some(ident) = path_to_ident(path) { if self.params.iter().any(|param| param.ident == ident) { self.has_free = true; @@ -163,100 +176,104 @@ pub fn is_parameterized( } } } - visit::walk_path(self, path); + visit::visit_path(self, path); } } let mut visitor = IsParameterized { params, has_free: false, found }; - visitor.visit_ty(ty); + visitor.visit_type(ty); visitor.has_free } -pub fn map_type_params<F>(ty: &Ty, params: &[TyParam], f: &mut F) -> Ty +pub fn map_type_params<F>(ty: &Type, params: &[&TypeParam], f: &mut F) -> Type where - F: FnMut(&Ident) -> Ty, + F: FnMut(&Ident) -> Type, { match *ty { - Ty::Slice(ref ty) => Ty::Slice(Box::new(map_type_params(ty, params, f))), - Ty::Array(ref ty, ref expr) => { - Ty::Array(Box::new(map_type_params(ty, params, f)), expr.clone()) + Type::Slice(ref inner) => { + Type::from(TypeSlice { elem: Box::new(map_type_params(&inner.elem, params, f)), ..inner.clone() }) }, - Ty::Never => Ty::Never, - Ty::Tup(ref items) => { - Ty::Tup(items.iter().map(|ty| map_type_params(ty, params, f)).collect()) + Type::Array(ref inner) => { //ref ty, ref expr) => { + Type::from(TypeArray { elem: Box::new(map_type_params(&inner.elem, params, f)), ..inner.clone() }) }, - Ty::Path(None, ref path) => { + ref ty @ Type::Never(_) => ty.clone(), + Type::Tuple(ref inner) => { + Type::from( + TypeTuple { + elems: inner.elems.iter().map(|ty| map_type_params(&ty, params, f)).collect(), + ..inner.clone() + } + ) + }, + Type::Path(TypePath { qself: None, ref path }) => { if let Some(ident) = path_to_ident(path) { if params.iter().any(|param| param.ident == ident) { return f(ident); } } - Ty::Path(None, map_type_params_in_path(path, params, f)) + Type::from(TypePath { qself: None, path: map_type_params_in_path(path, params, f) }) } - Ty::Path(ref qself, ref path) => { - Ty::Path( - qself.as_ref().map(|qself| { + Type::Path(TypePath { ref qself, ref path }) => { + Type::from(TypePath { + qself: qself.as_ref().map(|qself| { QSelf { ty: Box::new(map_type_params(&qself.ty, params, f)), position: qself.position, + ..qself.clone() } }), - map_type_params_in_path(path, params, f), - ) + path: map_type_params_in_path(path, params, f), + }) + }, + Type::Paren(ref inner) => { + Type::from(TypeParen { elem: Box::new(map_type_params(&inner.elem, params, f)), ..inner.clone() }) }, - Ty::Paren(ref ty) => Ty::Paren(Box::new(map_type_params(ty, params, f))), ref ty => panic!("type {:?} cannot be mapped yet", ty), } } -fn map_type_params_in_path<F>(path: &Path, params: &[TyParam], f: &mut F) -> Path +fn map_type_params_in_path<F>(path: &Path, params: &[&TypeParam], f: &mut F) -> Path where - F: FnMut(&Ident) -> Ty, + F: FnMut(&Ident) -> Type, { Path { - global: path.global, + leading_colon: path.leading_colon, segments: path.segments.iter().map(|segment| { PathSegment { ident: segment.ident.clone(), - parameters: match segment.parameters { - PathParameters::AngleBracketed(ref data) => { - PathParameters::AngleBracketed(AngleBracketedParameterData { - lifetimes: data.lifetimes.clone(), - types: data.types.iter().map(|ty| { - map_type_params(ty, params, f) - }).collect(), - bindings: data.bindings.iter().map(|binding| { - TypeBinding { - ident: binding.ident.clone(), - ty: map_type_params(&binding.ty, params, f), + arguments: match segment.arguments { + PathArguments::AngleBracketed(ref data) => { + PathArguments::AngleBracketed(AngleBracketedGenericArguments { + args: data.args.iter().map(|arg| { + match arg { + ty @ &GenericArgument::Lifetime(_) => ty.clone(), + &GenericArgument::Type(ref data) => { + GenericArgument::Type(map_type_params(data, params, f)) + }, + &GenericArgument::Binding(ref data) => GenericArgument::Binding(Binding { + ty: map_type_params(&data.ty, params, f), + ..data.clone() + }), + ref arg => panic!("arguments {:?} cannot be mapped yet", arg) } }).collect(), + ..data.clone() }) }, + ref arg @ PathArguments::None => arg.clone(), ref parameters => { panic!("parameters {:?} cannot be mapped yet", parameters) - }, + } }, } }).collect(), } } -pub fn path<S>(segments: S) -> Path -where - S: IntoIterator, - <S as IntoIterator>::Item: AsRef<str>, -{ - Path { - global: true, - segments: segments.into_iter().map(|s| s.as_ref().into()).collect(), - } -} - fn path_to_ident(path: &Path) -> Option<&Ident> { match *path { - Path { global: false, ref segments } if segments.len() == 1 => { - if segments[0].parameters.is_empty() { + Path { leading_colon: None, ref segments } if segments.len() == 1 => { + if segments[0].arguments.is_empty() { Some(&segments[0].ident) } else { None @@ -286,36 +303,41 @@ where } } -pub fn parse_variant_attrs<A>(variant: &Variant) -> A +pub fn parse_variant_attrs<A>(variant: &VariantAst) -> A where A: FromVariant, { - match A::from_variant(variant) { + let v = Variant { + ident: *variant.ident, + attrs: variant.attrs.to_vec(), + fields: variant.fields.clone(), + discriminant: variant.discriminant.clone(), + }; + match A::from_variant(&v) { Ok(attrs) => attrs, Err(e) => panic!("failed to parse variant attributes: {}", e), } } + pub fn ref_pattern<'a>( - name: &Ident, - variant: &'a Variant, + variant: &'a VariantInfo, prefix: &str, ) -> (Tokens, Vec<BindingInfo<'a>>) { - synstructure::match_pattern( - &name, - &variant.data, - &BindOpts::with_prefix(BindStyle::Ref, prefix.to_owned()), - ) + let mut v = variant.clone(); + v.bind_with(|_| BindStyle::Ref); + v.bindings_mut().iter_mut().for_each(|b| { b.binding = Ident::from(format!("{}_{}", b.binding, prefix)) }); + (v.pat(), v.bindings().iter().cloned().collect()) } pub fn trait_parts<'input, 'path>( input: &'input DeriveInput, - trait_path: &'path [&'path str], -) -> (ImplGenerics<'input>, TyGenerics<'input>, WhereClause<'input, 'path>) { + trait_path: &'path Path, +) -> (ImplGenerics<'input>, TypeGenerics<'input>, WhereClause<'input, 'path>) { let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); let where_clause = WhereClause { - inner: where_clause.clone(), - params: &input.generics.ty_params, + inner: where_clause.cloned(), + params: input.generics.type_params().into_iter().collect::<Vec<&TypeParam>>(), trait_path, trait_output: None, bounded_types: HashSet::new() @@ -323,88 +345,35 @@ pub fn trait_parts<'input, 'path>( (impl_generics, ty_generics, where_clause) } -fn trait_ref(path: &[&str], output: Option<(&str, Ty)>) -> Path { - let (name, parent) = path.split_last().unwrap(); - let last_segment = PathSegment { - ident: (*name).into(), - parameters: PathParameters::AngleBracketed( - AngleBracketedParameterData { - bindings: output.into_iter().map(|(param, ty)| { - TypeBinding { ident: param.into(), ty } - }).collect(), - .. Default::default() - } - ) +fn trait_ref(path: &Path, output: Option<(Ident, Type)>) -> Path { + let segments = path.segments.iter().collect::<Vec<&PathSegment>>(); + let (name, parent) = segments.split_last().unwrap(); + + let last_segment: PathSegment = if let Some((param, ty)) = output { + parse_quote!(#name<#param = #ty>) + } else { + parse_quote!(#name) }; - Path { - global: true, - segments: { - parent - .iter() - .cloned() - .map(Into::into) - .chain(iter::once(last_segment)) - .collect() - }, - } + parse_quote!(::#(#parent::)*#last_segment) } pub fn value<'a>( - name: &Ident, - variant: &'a Variant, + variant: &'a VariantInfo, prefix: &str, ) -> (Tokens, Vec<BindingInfo<'a>>) { - synstructure::match_pattern( - &name, - &variant.data, - &BindOpts::with_prefix(BindStyle::Move, prefix.to_owned()), - ) -} - -pub fn variant_ctor<'a>( - input: &'a DeriveInput, - variant: &Variant, -) -> Cow<'a, Ident> { - match input.body { - Body::Struct(_) => Cow::Borrowed(&input.ident), - Body::Enum(_) => { - Cow::Owned(Ident::from( - format!("{}::{}", input.ident, variant.ident), - )) - }, - } -} - -pub fn variants(input: &DeriveInput) -> Cow<[Variant]> { - match input.body { - Body::Enum(ref variants) => (&**variants).into(), - Body::Struct(ref data) => { - vec![Variant { - ident: input.ident.clone(), - attrs: input.attrs.clone(), - data: data.clone(), - discriminant: None, - }].into() - }, - } + let mut v = variant.clone(); + v.bindings_mut().iter_mut().for_each(|b| { b.binding = Ident::from(format!("{}_{}", b.binding, prefix)) }); + v.bind_with(|_| BindStyle::Move); + (v.pat(), v.bindings().iter().cloned().collect()) } pub fn where_predicate( - bounded_ty: Ty, - trait_path: &[&str], - trait_output: Option<(&str, Ty)>, + bounded_ty: Type, + trait_path: &Path, + trait_output: Option<(Ident, Type)>, ) -> WherePredicate { - WherePredicate::BoundPredicate(WhereBoundPredicate { - bound_lifetimes: vec![], - bounded_ty, - bounds: vec![TyParamBound::Trait( - PolyTraitRef { - bound_lifetimes: vec![], - trait_ref: trait_ref(trait_path, trait_output), - }, - TraitBoundModifier::None - )], - }) + let trait_ref = trait_ref(trait_path, trait_output); + parse_quote!(#bounded_ty: #trait_ref) } /// Transforms "FooBar" to "foo-bar". diff --git a/components/style_derive/compute_squared_distance.rs b/components/style_derive/compute_squared_distance.rs index cbdd9c62acc..509d1b5be95 100644 --- a/components/style_derive/compute_squared_distance.rs +++ b/components/style_derive/compute_squared_distance.rs @@ -6,52 +6,54 @@ use animate::AnimationVariantAttrs; use cg; use quote::Tokens; use syn::{DeriveInput, Path}; +use synstructure; pub fn derive(input: DeriveInput) -> Tokens { let name = &input.ident; - let trait_path = &["values", "distance", "ComputeSquaredDistance"]; + let trait_path = parse_quote!(values::distance::ComputeSquaredDistance); let (impl_generics, ty_generics, mut where_clause) = - cg::trait_parts(&input, trait_path); + cg::trait_parts(&input, &trait_path); let input_attrs = cg::parse_input_attrs::<DistanceInputAttrs>(&input); - let variants = cg::variants(&input); - let mut match_body = quote!(); - let mut append_error_clause = variants.len() > 1; - match_body.append_all(variants.iter().map(|variant| { - let attrs = cg::parse_variant_attrs::<AnimationVariantAttrs>(variant); + let s = synstructure::Structure::new(&input); + let mut append_error_clause = s.variants().len() > 1; + + let mut match_body = s.variants().iter().fold(quote!(), |body, variant| { + let attrs = cg::parse_variant_attrs::<AnimationVariantAttrs>(&variant.ast()); if attrs.error { append_error_clause = true; - return None; + return body; } - let name = cg::variant_ctor(&input, variant); - let (this_pattern, this_info) = cg::ref_pattern(&name, &variant, "this"); - let (other_pattern, other_info) = cg::ref_pattern(&name, &variant, "other"); + + let (this_pattern, this_info) = cg::ref_pattern(&variant, "this"); + let (other_pattern, other_info) = cg::ref_pattern(&variant, "other"); let sum = if this_info.is_empty() { quote! { ::values::distance::SquaredDistance::Value(0.) } } else { let mut sum = quote!(); sum.append_separated(this_info.iter().zip(&other_info).map(|(this, other)| { - where_clause.add_trait_bound(&this.field.ty); + where_clause.add_trait_bound(&this.ast().ty); quote! { ::values::distance::ComputeSquaredDistance::compute_squared_distance(#this, #other)? } - }), "+"); + }), quote!(+)); sum }; - Some(quote! { + quote! { + #body (&#this_pattern, &#other_pattern) => { Ok(#sum) } - }) - })); + } + }); if append_error_clause { if let Some(fallback) = input_attrs.fallback { - match_body.append(quote! { + match_body.append_all(quote! { (this, other) => #fallback(this, other) }); } else { - match_body.append(quote! { _ => Err(()) }); + match_body.append_all(quote! { _ => Err(()) }); } } diff --git a/components/style_derive/lib.rs b/components/style_derive/lib.rs index 7778b7ea39c..e414a3bd3f2 100644 --- a/components/style_derive/lib.rs +++ b/components/style_derive/lib.rs @@ -7,7 +7,7 @@ #[macro_use] extern crate darling; extern crate proc_macro; #[macro_use] extern crate quote; -extern crate syn; +#[macro_use] extern crate syn; extern crate synstructure; use proc_macro::TokenStream; @@ -23,42 +23,42 @@ mod to_css; #[proc_macro_derive(Animate, attributes(animate, animation))] pub fn derive_animate(stream: TokenStream) -> TokenStream { - let input = syn::parse_derive_input(&stream.to_string()).unwrap(); - animate::derive(input).to_string().parse().unwrap() + let input = syn::parse(stream).unwrap(); + animate::derive(input).into() } #[proc_macro_derive(ComputeSquaredDistance, attributes(animation, distance))] pub fn derive_compute_squared_distance(stream: TokenStream) -> TokenStream { - let input = syn::parse_derive_input(&stream.to_string()).unwrap(); - compute_squared_distance::derive(input).to_string().parse().unwrap() + let input = syn::parse(stream).unwrap(); + compute_squared_distance::derive(input).into() } #[proc_macro_derive(ToAnimatedValue)] pub fn derive_to_animated_value(stream: TokenStream) -> TokenStream { - let input = syn::parse_derive_input(&stream.to_string()).unwrap(); - to_animated_value::derive(input).to_string().parse().unwrap() + let input = syn::parse(stream).unwrap(); + to_animated_value::derive(input).into() } #[proc_macro_derive(Parse, attributes(css))] pub fn derive_parse(stream: TokenStream) -> TokenStream { - let input = syn::parse_derive_input(&stream.to_string()).unwrap(); - parse::derive(input).to_string().parse().unwrap() + let input = syn::parse(stream).unwrap(); + parse::derive(input).into() } #[proc_macro_derive(ToAnimatedZero, attributes(animation))] pub fn derive_to_animated_zero(stream: TokenStream) -> TokenStream { - let input = syn::parse_derive_input(&stream.to_string()).unwrap(); - to_animated_zero::derive(input).to_string().parse().unwrap() + let input = syn::parse(stream).unwrap(); + to_animated_zero::derive(input).into() } #[proc_macro_derive(ToComputedValue, attributes(compute))] pub fn derive_to_computed_value(stream: TokenStream) -> TokenStream { - let input = syn::parse_derive_input(&stream.to_string()).unwrap(); - to_computed_value::derive(input).to_string().parse().unwrap() + let input = syn::parse(stream).unwrap(); + to_computed_value::derive(input).into() } #[proc_macro_derive(ToCss, attributes(css))] pub fn derive_to_css(stream: TokenStream) -> TokenStream { - let input = syn::parse_derive_input(&stream.to_string()).unwrap(); - to_css::derive(input).to_string().parse().unwrap() + let input = syn::parse(stream).unwrap(); + to_css::derive(input).into() } diff --git a/components/style_derive/parse.rs b/components/style_derive/parse.rs index 79ada00878f..fb429a05599 100644 --- a/components/style_derive/parse.rs +++ b/components/style_derive/parse.rs @@ -10,38 +10,40 @@ use to_css::CssVariantAttrs; pub fn derive(input: DeriveInput) -> Tokens { let name = &input.ident; + let s = synstructure::Structure::new(&input); - let mut match_body = quote! {}; - - let style = synstructure::BindStyle::Ref.into(); - synstructure::each_variant(&input, &style, |bindings, variant| { + let match_body = s.variants().iter().fold(quote!(), |match_body, variant| { + let bindings = variant.bindings(); assert!( bindings.is_empty(), "Parse is only supported for single-variant enums for now" ); - let variant_attrs = cg::parse_variant_attrs::<CssVariantAttrs>(variant); + let variant_attrs = cg::parse_variant_attrs::<CssVariantAttrs>(&variant.ast()); let identifier = cg::to_css_identifier( - &variant_attrs.keyword.as_ref().unwrap_or(&variant.ident).as_ref(), + &variant_attrs.keyword.unwrap_or(variant.ast().ident.as_ref().into()), ); - let ident = &variant.ident; + let ident = &variant.ast().ident; - match_body = quote! { + let mut body = quote! { #match_body #identifier => Ok(#name::#ident), }; + let aliases = match variant_attrs.aliases { Some(aliases) => aliases, - None => return, + None => return body, }; for alias in aliases.split(",") { - match_body = quote! { - #match_body + body = quote! { + #body #alias => Ok(#name::#ident), }; } + + body }); let parse_trait_impl = quote! { diff --git a/components/style_derive/to_animated_value.rs b/components/style_derive/to_animated_value.rs index 7865ba597e9..5d9cdbc0138 100644 --- a/components/style_derive/to_animated_value.rs +++ b/components/style_derive/to_animated_value.rs @@ -4,17 +4,17 @@ use cg; use quote; -use syn; +use syn::{self, Ident}; use synstructure::BindStyle; pub fn derive(input: syn::DeriveInput) -> quote::Tokens { let name = &input.ident; - let trait_path = &["values", "animated", "ToAnimatedValue"]; + let trait_path = parse_quote!(values::animated::ToAnimatedValue); let (impl_generics, ty_generics, mut where_clause, animated_value_type) = - cg::fmap_trait_parts(&input, trait_path, "AnimatedValue"); + cg::fmap_trait_parts(&input, &trait_path, Ident::from("AnimatedValue")); let to_body = cg::fmap_match(&input, BindStyle::Move, |binding| { - where_clause.add_trait_bound(&binding.field.ty); + where_clause.add_trait_bound(&binding.ast().ty); quote!(::values::animated::ToAnimatedValue::to_animated_value(#binding)) }); let from_body = cg::fmap_match(&input, BindStyle::Move, |binding| { diff --git a/components/style_derive/to_animated_zero.rs b/components/style_derive/to_animated_zero.rs index be1210faa7a..674a0201fcc 100644 --- a/components/style_derive/to_animated_zero.rs +++ b/components/style_derive/to_animated_zero.rs @@ -6,31 +6,30 @@ use animate::{AnimationVariantAttrs, AnimationFieldAttrs}; use cg; use quote; use syn; -use synstructure::{self, BindStyle}; +use synstructure; pub fn derive(input: syn::DeriveInput) -> quote::Tokens { let name = &input.ident; - let trait_path = &["values", "animated", "ToAnimatedZero"]; + let trait_path = parse_quote!(values::animated::ToAnimatedZero); let (impl_generics, ty_generics, mut where_clause) = - cg::trait_parts(&input, trait_path); + cg::trait_parts(&input, &trait_path); - let bind_opts = BindStyle::Ref.into(); - let to_body = synstructure::each_variant(&input, &bind_opts, |bindings, variant| { - let attrs = cg::parse_variant_attrs::<AnimationVariantAttrs>(variant); + let s = synstructure::Structure::new(&input); + let to_body = s.each_variant(|variant| { + let attrs = cg::parse_variant_attrs::<AnimationVariantAttrs>(&variant.ast()); if attrs.error { return Some(quote! { Err(()) }); } - let name = cg::variant_ctor(&input, variant); - let (mapped, mapped_bindings) = cg::value(&name, variant, "mapped"); - let bindings_pairs = bindings.into_iter().zip(mapped_bindings); + let (mapped, mapped_bindings) = cg::value(variant, "mapped"); + let bindings_pairs = variant.bindings().into_iter().zip(mapped_bindings); let mut computations = quote!(); computations.append_all(bindings_pairs.map(|(binding, mapped_binding)| { - let field_attrs = cg::parse_field_attrs::<AnimationFieldAttrs>(&binding.field); + let field_attrs = cg::parse_field_attrs::<AnimationFieldAttrs>(&binding.ast()); if field_attrs.constant { - if cg::is_parameterized(&binding.field.ty, where_clause.params, None) { - where_clause.inner.predicates.push(cg::where_predicate( - binding.field.ty.clone(), - &["std", "clone", "Clone"], + if cg::is_parameterized(&binding.ast().ty, &where_clause.params, None) { + where_clause.add_predicate(cg::where_predicate( + binding.ast().ty.clone(), + &parse_quote!(std::clone::Clone), None, )); } @@ -38,14 +37,14 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens { let #mapped_binding = ::std::clone::Clone::clone(#binding); } } else { - where_clause.add_trait_bound(&binding.field.ty); + where_clause.add_trait_bound(&binding.ast().ty); quote! { let #mapped_binding = ::values::animated::ToAnimatedZero::to_animated_zero(#binding)?; } } })); - computations.append(quote! { Ok(#mapped) }); + computations.append_all(quote! { Ok(#mapped) }); Some(computations) }); diff --git a/components/style_derive/to_computed_value.rs b/components/style_derive/to_computed_value.rs index c53b25408e9..198d5cfe17c 100644 --- a/components/style_derive/to_computed_value.rs +++ b/components/style_derive/to_computed_value.rs @@ -4,29 +4,29 @@ use cg; use quote::Tokens; -use syn::DeriveInput; +use syn::{Ident, DeriveInput}; use synstructure::BindStyle; pub fn derive(input: DeriveInput) -> Tokens { let name = &input.ident; - let trait_path = &["values", "computed", "ToComputedValue"]; + let trait_path = parse_quote!(values::computed::ToComputedValue); let (impl_generics, ty_generics, mut where_clause, computed_value_type) = - cg::fmap_trait_parts(&input, trait_path, "ComputedValue"); + cg::fmap_trait_parts(&input, &trait_path, Ident::from("ComputedValue")); let to_body = cg::fmap_match(&input, BindStyle::Ref, |binding| { - let attrs = cg::parse_field_attrs::<ComputedValueAttrs>(&binding.field); + let attrs = cg::parse_field_attrs::<ComputedValueAttrs>(&binding.ast()); if attrs.clone { - if cg::is_parameterized(&binding.field.ty, where_clause.params, None) { - where_clause.inner.predicates.push(cg::where_predicate( - binding.field.ty.clone(), - &["std", "clone", "Clone"], + if cg::is_parameterized(&binding.ast().ty, &where_clause.params, None) { + where_clause.add_predicate(cg::where_predicate( + binding.ast().ty.clone(), + &parse_quote!(std::clone::Clone), None, )); } quote! { ::std::clone::Clone::clone(#binding) } } else { if !attrs.ignore_bound { - where_clause.add_trait_bound(&binding.field.ty); + where_clause.add_trait_bound(&binding.ast().ty); } quote! { ::values::computed::ToComputedValue::to_computed_value(#binding, context) @@ -34,7 +34,7 @@ pub fn derive(input: DeriveInput) -> Tokens { } }); let from_body = cg::fmap_match(&input, BindStyle::Ref, |binding| { - let attrs = cg::parse_field_attrs::<ComputedValueAttrs>(&binding.field); + let attrs = cg::parse_field_attrs::<ComputedValueAttrs>(&binding.ast()); if attrs.clone { quote! { ::std::clone::Clone::clone(#binding) } } else { diff --git a/components/style_derive/to_css.rs b/components/style_derive/to_css.rs index 93e36753abf..f86418b2361 100644 --- a/components/style_derive/to_css.rs +++ b/components/style_derive/to_css.rs @@ -5,20 +5,23 @@ use cg; use darling::{Error, FromMetaItem}; use quote::Tokens; -use syn::{self, DeriveInput, Ident}; +use syn::{self, Ident}; use synstructure; -pub fn derive(input: DeriveInput) -> Tokens { +pub fn derive(input: syn::DeriveInput) -> Tokens { let name = &input.ident; - let trait_path = &["style_traits", "ToCss"]; + let trait_path = parse_quote!(style_traits::ToCss); let (impl_generics, ty_generics, mut where_clause) = - cg::trait_parts(&input, trait_path); + cg::trait_parts(&input, &trait_path); let input_attrs = cg::parse_input_attrs::<CssInputAttrs>(&input); - let style = synstructure::BindStyle::Ref.into(); - let match_body = synstructure::each_variant(&input, &style, |bindings, variant| { - let identifier = cg::to_css_identifier(variant.ident.as_ref()); - let variant_attrs = cg::parse_variant_attrs::<CssVariantAttrs>(variant); + let s = synstructure::Structure::new(&input); + + let match_body = s.each_variant(|variant| { + let bindings = variant.bindings(); + let identifier = cg::to_css_identifier(variant.ast().ident.as_ref()); + let ast = variant.ast(); + let variant_attrs = cg::parse_variant_attrs::<CssVariantAttrs>(&ast); let separator = if variant_attrs.comma { ", " } else { " " }; if variant_attrs.dimension { @@ -49,9 +52,9 @@ pub fn derive(input: DeriveInput) -> Tokens { }; } else { for binding in bindings { - let attrs = cg::parse_field_attrs::<CssFieldAttrs>(&binding.field); + let attrs = cg::parse_field_attrs::<CssFieldAttrs>(&binding.ast()); if !attrs.ignore_bound { - where_clause.add_trait_bound(&binding.field.ty); + where_clause.add_trait_bound(&binding.ast().ty); } expr = quote! { #expr @@ -107,7 +110,7 @@ pub fn derive(input: DeriveInput) -> Tokens { }; if input_attrs.derive_debug { - impls.append(quote! { + impls.append_all(quote! { impl #impl_generics ::std::fmt::Debug for #name #ty_generics #where_clause { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { ::style_traits::ToCss::to_css( @@ -137,7 +140,7 @@ pub struct CssVariantAttrs { pub iterable: bool, pub comma: bool, pub dimension: bool, - pub keyword: Option<Ident>, + pub keyword: Option<String>, pub aliases: Option<String>, } @@ -157,7 +160,7 @@ impl FromMetaItem for Function { } fn from_string(name: &str) -> Result<Self, Error> { - let name = syn::parse_ident(name).map_err(Error::custom)?; + let name = Ident::from(name); Ok(Self { name: Some(name) }) } } |