aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2017-08-23 10:01:15 -0500
committerGitHub <noreply@github.com>2017-08-23 10:01:15 -0500
commite629f8da7ba373f6575c2e9ccc6259b7f2c4e3e4 (patch)
tree841a4d436a7b0b27c42cfbdf024f3a8eb50bb55c
parent2e775abfa4563fc5db467c5c79f9d2507f6bb2e7 (diff)
parentf2758950284610265b9245beed179c8729715a6b (diff)
downloadservo-e629f8da7ba373f6575c2e9ccc6259b7f2c4e3e4.tar.gz
servo-e629f8da7ba373f6575c2e9ccc6259b7f2c4e3e4.zip
Auto merge of #18200 - servo:derive-all-the-things, r=emilio
Introduce style_derive::cg <!-- Reviewable:start --> This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/18200) <!-- Reviewable:end -->
-rw-r--r--components/style_derive/animate.rs88
-rw-r--r--components/style_derive/cg.rs219
-rw-r--r--components/style_derive/compute_squared_distance.rs79
-rw-r--r--components/style_derive/has_viewport_percentage.rs27
-rw-r--r--components/style_derive/lib.rs1
-rw-r--r--components/style_derive/to_animated_value.rs117
-rw-r--r--components/style_derive/to_animated_zero.rs69
-rw-r--r--components/style_derive/to_computed_value.rs118
-rw-r--r--components/style_derive/to_css.rs58
9 files changed, 291 insertions, 485 deletions
diff --git a/components/style_derive/animate.rs b/components/style_derive/animate.rs
index 5ce1040e94c..888a5e61c8e 100644
--- a/components/style_derive/animate.rs
+++ b/components/style_derive/animate.rs
@@ -2,56 +2,29 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+use cg;
use quote;
-use std::borrow::Cow;
use syn;
-use synstructure;
pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
let name = &input.ident;
- let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
- let mut where_clause = where_clause.clone();
- for param in &input.generics.ty_params {
- where_clause.predicates.push(where_predicate(syn::Ty::Path(None, param.ident.clone().into())))
- }
+ let trait_path = &["values", "animated", "Animate"];
+ let (impl_generics, ty_generics, mut where_clause) =
+ cg::trait_parts(&input, trait_path);
- let variants = variants(&input);
+ let variants = cg::variants(&input);
let mut match_body = quote!();
match_body.append_all(variants.iter().map(|variant| {
- let name = match input.body {
- syn::Body::Struct(_) => Cow::Borrowed(&input.ident),
- syn::Body::Enum(_) => {
- Cow::Owned(syn::Ident::from(format!("{}::{}", input.ident, variant.ident)))
- },
- };
- let (this_pattern, this_info) = synstructure::match_pattern(
- &name,
- &variant.data,
- &synstructure::BindOpts::with_prefix(
- synstructure::BindStyle::Ref,
- "this".to_owned(),
- ),
- );
- let (other_pattern, other_info) = synstructure::match_pattern(
- &name,
- &variant.data,
- &synstructure::BindOpts::with_prefix(
- synstructure::BindStyle::Ref,
- "other".to_owned(),
- ),
- );
- let (result_value, result_info) = synstructure::match_pattern(
- &name,
- &variant.data,
- &synstructure::BindOpts::with_prefix(
- synstructure::BindStyle::Move,
- "result".to_owned(),
- ),
- );
+ 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 mut computations = quote!();
let iter = result_info.iter().zip(this_info.iter().zip(&other_info));
computations.append_all(iter.map(|(result, (this, other))| {
- where_clause.predicates.push(where_predicate(this.field.ty.clone()));
+ where_clause.predicates.push(
+ cg::where_predicate(this.field.ty.clone(), trait_path),
+ );
quote! {
let #result = ::values::animated::Animate::animate(#this, #other, procedure)?;
}
@@ -84,40 +57,3 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
}
}
}
-
-fn variants(input: &syn::DeriveInput) -> Cow<[syn::Variant]> {
- match input.body {
- syn::Body::Enum(ref variants) => (&**variants).into(),
- syn::Body::Struct(ref data) => {
- vec![syn::Variant {
- ident: input.ident.clone(),
- attrs: input.attrs.clone(),
- data: data.clone(),
- discriminant: None,
- }].into()
- },
- }
-}
-
-fn where_predicate(ty: syn::Ty) -> syn::WherePredicate {
- syn::WherePredicate::BoundPredicate(
- syn::WhereBoundPredicate {
- bound_lifetimes: vec![],
- bounded_ty: ty,
- bounds: vec![syn::TyParamBound::Trait(
- syn::PolyTraitRef {
- bound_lifetimes: vec![],
- trait_ref: syn::Path {
- global: true,
- segments: vec![
- "values".into(),
- "animated".into(),
- "Animate".into(),
- ],
- },
- },
- syn::TraitBoundModifier::None,
- )],
- },
- )
-}
diff --git a/components/style_derive/cg.rs b/components/style_derive/cg.rs
new file mode 100644
index 00000000000..af60591d7c6
--- /dev/null
+++ b/components/style_derive/cg.rs
@@ -0,0 +1,219 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use quote::Tokens;
+use std::borrow::Cow;
+use std::iter;
+use syn::{AngleBracketedParameterData, Body, DeriveInput, Ident, ImplGenerics};
+use syn::{Path, PathParameters, PathSegment, PolyTraitRef, QSelf};
+use syn::{TraitBoundModifier, Ty, TyGenerics, TyParam, TyParamBound, TypeBinding};
+use syn::{Variant, WhereBoundPredicate, WhereClause, WherePredicate};
+use syn::visit::{self, Visitor};
+use synstructure::{self, BindOpts, BindStyle, BindingInfo};
+
+pub fn fmap_match<F>(
+ input: &DeriveInput,
+ bind_style: BindStyle,
+ mut f: F,
+) -> Tokens
+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 computations = quote!();
+ computations.append_all(fields_pairs.map(|(field, mapped_field)| {
+ let expr = f(field);
+ quote! { let #mapped_field = #expr; }
+ }));
+ computations.append(mapped);
+ Some(computations)
+ })
+}
+
+pub fn fmap_trait_parts<'a>(
+ input: &'a DeriveInput,
+ trait_path: &[&str],
+ trait_output: &str,
+) -> (ImplGenerics<'a>, TyGenerics<'a>, WhereClause, Path) {
+ let (impl_generics, ty_generics, where_clause) = trait_parts(input, trait_path);
+ 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| {
+ Ty::Path(
+ Some(QSelf {
+ ty: Box::new(Ty::Path(None, ty.ident.clone().into())),
+ position: trait_path.len(),
+ }),
+ path(trait_path.iter().chain(iter::once(&trait_output))),
+ )
+ }).collect(),
+ .. Default::default()
+ }),
+ }.into();
+ (impl_generics, ty_generics, where_clause, output_ty)
+}
+
+fn fmap_trait_where_predicate(
+ bounded_ty: Ty,
+ trait_path: &[&str],
+ trait_output: Option<(&str, Ty)>,
+) -> WherePredicate {
+ WherePredicate::BoundPredicate(WhereBoundPredicate {
+ bound_lifetimes: vec![],
+ bounded_ty,
+ bounds: vec![TyParamBound::Trait(
+ PolyTraitRef {
+ bound_lifetimes: vec![],
+ trait_ref: fmap_trait_ref(trait_path, trait_output),
+ },
+ TraitBoundModifier::None
+ )],
+ })
+}
+
+fn fmap_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()
+ }
+ )
+ };
+ Path {
+ global: true,
+ segments: {
+ parent
+ .iter()
+ .cloned()
+ .map(Into::into)
+ .chain(iter::once(last_segment))
+ .collect()
+ },
+ }
+}
+
+pub fn is_parameterized(ty: &Ty, params: &[TyParam]) -> bool {
+ struct IsParameterized<'a> {
+ params: &'a [TyParam],
+ has_free: bool,
+ }
+
+ impl<'a> Visitor for IsParameterized<'a> {
+ fn visit_path(&mut self, path: &Path) {
+ if !path.global && path.segments.len() == 1 {
+ if self.params.iter().any(|param| param.ident == path.segments[0].ident) {
+ self.has_free = true;
+ }
+ }
+ visit::walk_path(self, path);
+ }
+ }
+
+ let mut visitor = IsParameterized { params: params, has_free: false };
+ visitor.visit_ty(ty);
+ visitor.has_free
+}
+
+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(),
+ }
+}
+
+pub fn ref_pattern<'a>(
+ name: &Ident,
+ variant: &'a Variant,
+ prefix: &str,
+) -> (Tokens, Vec<BindingInfo<'a>>) {
+ synstructure::match_pattern(
+ &name,
+ &variant.data,
+ &BindOpts::with_prefix(BindStyle::Ref, prefix.to_owned()),
+ )
+}
+
+pub fn trait_parts<'a>(
+ input: &'a DeriveInput,
+ trait_path: &[&str],
+) -> (ImplGenerics<'a>, TyGenerics<'a>, WhereClause) {
+ let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
+ let mut where_clause = where_clause.clone();
+ for param in &input.generics.ty_params {
+ where_clause.predicates.push(fmap_trait_where_predicate(
+ Ty::Path(None, param.ident.clone().into()),
+ trait_path,
+ None,
+ ));
+ }
+ (impl_generics, ty_generics, where_clause)
+}
+
+pub fn value<'a>(
+ name: &Ident,
+ variant: &'a Variant,
+ 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()
+ },
+ }
+}
+
+pub fn where_predicate(ty: Ty, segments: &[&str]) -> WherePredicate {
+ WherePredicate::BoundPredicate(WhereBoundPredicate {
+ bound_lifetimes: vec![],
+ bounded_ty: ty,
+ bounds: vec![TyParamBound::Trait(
+ PolyTraitRef {
+ bound_lifetimes: vec![],
+ trait_ref: path(segments),
+ },
+ TraitBoundModifier::None,
+ )],
+ })
+}
diff --git a/components/style_derive/compute_squared_distance.rs b/components/style_derive/compute_squared_distance.rs
index 46aa376319d..df02d1312cc 100644
--- a/components/style_derive/compute_squared_distance.rs
+++ b/components/style_derive/compute_squared_distance.rs
@@ -2,50 +2,30 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+use cg;
use quote;
-use std::borrow::Cow;
use syn;
-use synstructure;
pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
let name = &input.ident;
- let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
- let mut where_clause = where_clause.clone();
- for param in &input.generics.ty_params {
- where_clause.predicates.push(where_predicate(syn::Ty::Path(None, param.ident.clone().into())))
- }
+ let trait_path = &["values", "distance", "ComputeSquaredDistance"];
+ let (impl_generics, ty_generics, mut where_clause) =
+ cg::trait_parts(&input, trait_path);
- let variants = variants(&input);
+ let variants = cg::variants(&input);
let mut match_body = quote!();
match_body.append_all(variants.iter().map(|variant| {
- let name = match input.body {
- syn::Body::Struct(_) => Cow::Borrowed(&input.ident),
- syn::Body::Enum(_) => {
- Cow::Owned(syn::Ident::from(format!("{}::{}", input.ident, variant.ident)))
- },
- };
- let (this_pattern, this_info) = synstructure::match_pattern(
- &name,
- &variant.data,
- &synstructure::BindOpts::with_prefix(
- synstructure::BindStyle::Ref,
- "this".to_owned(),
- ),
- );
- let (other_pattern, other_info) = synstructure::match_pattern(
- &name,
- &variant.data,
- &synstructure::BindOpts::with_prefix(
- synstructure::BindStyle::Ref,
- "other".to_owned(),
- ),
- );
+ 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 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.predicates.push(where_predicate(this.field.ty.clone()));
+ where_clause.predicates.push(
+ cg::where_predicate(this.field.ty.clone(), trait_path),
+ );
quote! {
::values::distance::ComputeSquaredDistance::compute_squared_distance(#this, #other)?
}
@@ -78,40 +58,3 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
}
}
}
-
-fn variants(input: &syn::DeriveInput) -> Cow<[syn::Variant]> {
- match input.body {
- syn::Body::Enum(ref variants) => (&**variants).into(),
- syn::Body::Struct(ref data) => {
- vec![syn::Variant {
- ident: input.ident.clone(),
- attrs: input.attrs.clone(),
- data: data.clone(),
- discriminant: None,
- }].into()
- },
- }
-}
-
-fn where_predicate(ty: syn::Ty) -> syn::WherePredicate {
- syn::WherePredicate::BoundPredicate(
- syn::WhereBoundPredicate {
- bound_lifetimes: vec![],
- bounded_ty: ty,
- bounds: vec![syn::TyParamBound::Trait(
- syn::PolyTraitRef {
- bound_lifetimes: vec![],
- trait_ref: syn::Path {
- global: true,
- segments: vec![
- "values".into(),
- "distance".into(),
- "ComputeSquaredDistance".into(),
- ],
- },
- },
- syn::TraitBoundModifier::None,
- )],
- },
- )
-}
diff --git a/components/style_derive/has_viewport_percentage.rs b/components/style_derive/has_viewport_percentage.rs
index 24e4b919c22..5f26d988b8a 100644
--- a/components/style_derive/has_viewport_percentage.rs
+++ b/components/style_derive/has_viewport_percentage.rs
@@ -2,17 +2,16 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+use cg;
use quote;
use syn;
use synstructure;
pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
let name = &input.ident;
- let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
- let mut where_clause = where_clause.clone();
- for param in &input.generics.ty_params {
- where_clause.predicates.push(where_predicate(syn::Ty::Path(None, param.ident.clone().into())))
- }
+ let trait_path = &["style_traits", "HasViewportPercentage"];
+ let (impl_generics, ty_generics, mut where_clause) =
+ cg::trait_parts(&input, trait_path);
let style = synstructure::BindStyle::Ref.into();
let match_body = synstructure::each_variant(&input, &style, |bindings, _| {
@@ -22,7 +21,9 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
};
let mut expr = quote!(::style_traits::HasViewportPercentage::has_viewport_percentage(#first));
for binding in rest {
- where_clause.predicates.push(where_predicate(binding.field.ty.clone()));
+ where_clause.predicates.push(
+ cg::where_predicate(binding.field.ty.clone(), trait_path),
+ );
expr = quote!(#expr || ::style_traits::HasViewportPercentage::has_viewport_percentage(#binding));
}
Some(expr)
@@ -40,17 +41,3 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
}
}
}
-
-fn where_predicate(ty: syn::Ty) -> syn::WherePredicate {
- syn::WherePredicate::BoundPredicate(syn::WhereBoundPredicate {
- bound_lifetimes: vec![],
- bounded_ty: ty,
- bounds: vec![syn::TyParamBound::Trait(
- syn::PolyTraitRef {
- bound_lifetimes: vec![],
- trait_ref: syn::parse_path("::style_traits::HasViewportPercentage").unwrap(),
- },
- syn::TraitBoundModifier::None
- )],
- })
-}
diff --git a/components/style_derive/lib.rs b/components/style_derive/lib.rs
index a41925ab410..e2b10dc47aa 100644
--- a/components/style_derive/lib.rs
+++ b/components/style_derive/lib.rs
@@ -10,6 +10,7 @@ extern crate synstructure;
use proc_macro::TokenStream;
mod animate;
+mod cg;
mod compute_squared_distance;
mod has_viewport_percentage;
mod to_animated_value;
diff --git a/components/style_derive/to_animated_value.rs b/components/style_derive/to_animated_value.rs
index ab13a26d5c8..5a66ddf65a4 100644
--- a/components/style_derive/to_animated_value.rs
+++ b/components/style_derive/to_animated_value.rs
@@ -2,49 +2,24 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+use cg;
use quote;
use syn;
-use synstructure;
+use synstructure::BindStyle;
pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
let name = &input.ident;
- let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
- let mut where_clause = where_clause.clone();
- for param in &input.generics.ty_params {
- where_clause.predicates.push(where_predicate(syn::Ty::Path(None, param.ident.clone().into()), None));
- }
-
- let animated_value_type = syn::Path::from(syn::PathSegment {
- ident: name.clone(),
- parameters: syn::PathParameters::AngleBracketed(syn::AngleBracketedParameterData {
- lifetimes: input.generics.lifetimes.iter().map(|l| {
- l.lifetime.clone()
- }).collect(),
- types: input.generics.ty_params.iter().map(|ty| {
- syn::Ty::Path(
- Some(syn::QSelf {
- ty: Box::new(syn::Ty::Path(None, ty.ident.clone().into())),
- position: 3,
- }),
- syn::Path {
- global: true,
- segments: vec![
- "values".into(),
- "animated".into(),
- "ToAnimatedValue".into(),
- "AnimatedValue".into(),
- ],
- },
- )
- }).collect(),
- .. Default::default()
- }),
- });
-
- let to_body = match_body(&input, |field| {
+ let (impl_generics, ty_generics, where_clause, animated_value_type) =
+ cg::fmap_trait_parts(
+ &input,
+ &["values", "animated", "ToAnimatedValue"],
+ "AnimatedValue",
+ );
+
+ let to_body = cg::fmap_match(&input, BindStyle::Move, |field| {
quote!(::values::animated::ToAnimatedValue::to_animated_value(#field))
});
- let from_body = match_body(&input, |field| {
+ let from_body = cg::fmap_match(&input, BindStyle::Move, |field| {
quote!(::values::animated::ToAnimatedValue::from_animated_value(#field))
});
@@ -69,73 +44,3 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
}
}
}
-
-fn match_body<F>(input: &syn::DeriveInput, f: F) -> quote::Tokens
-where
- F: Fn(&synstructure::BindingInfo) -> quote::Tokens,
-{
- let by_value = synstructure::BindStyle::Move.into();
- synstructure::each_variant(&input, &by_value, |fields, variant| {
- let name = if let syn::Body::Enum(_) = input.body {
- format!("{}::{}", input.ident, variant.ident).into()
- } else {
- variant.ident.clone()
- };
- let (animated_value, computed_fields) = synstructure::match_pattern(&name, &variant.data, &by_value);
- let fields_pairs = fields.iter().zip(computed_fields.iter());
- let mut computations = quote!();
- computations.append_all(fields_pairs.map(|(field, computed_field)| {
- let expr = f(field);
- quote!(let #computed_field = #expr;)
- }));
- Some(quote!(
- #computations
- #animated_value
- ))
- })
-}
-
-/// `#ty: ::values::animated::ToAnimatedValue<AnimatedValue = #animated_value,>`
-fn where_predicate(ty: syn::Ty, animated_value: Option<syn::Ty>) -> syn::WherePredicate {
- syn::WherePredicate::BoundPredicate(syn::WhereBoundPredicate {
- bound_lifetimes: vec![],
- bounded_ty: ty,
- bounds: vec![syn::TyParamBound::Trait(
- syn::PolyTraitRef {
- bound_lifetimes: vec![],
- trait_ref: trait_ref(animated_value),
- },
- syn::TraitBoundModifier::None
- )],
- })
-}
-
-/// `::values::animated::ToAnimatedValue<AnimatedValue = #animated_value,>`
-fn trait_ref(animated_value: Option<syn::Ty>) -> syn::Path {
- syn::Path {
- global: true,
- segments: vec![
- "values".into(),
- "animated".into(),
- syn::PathSegment {
- ident: "ToAnimatedValue".into(),
- parameters: syn::PathParameters::AngleBracketed(
- syn::AngleBracketedParameterData {
- bindings: trait_bindings(animated_value),
- .. Default::default()
- }
- ),
- }
- ],
- }
-}
-
-/// `AnimatedValue = #animated_value,`
-fn trait_bindings(animated_value: Option<syn::Ty>) -> Vec<syn::TypeBinding> {
- animated_value.into_iter().map(|ty| {
- syn::TypeBinding {
- ident: "AnimatedValue".into(),
- ty: ty,
- }
- }).collect()
-}
diff --git a/components/style_derive/to_animated_zero.rs b/components/style_derive/to_animated_zero.rs
index f44443f4a34..d9e67a8a9fe 100644
--- a/components/style_derive/to_animated_zero.rs
+++ b/components/style_derive/to_animated_zero.rs
@@ -2,78 +2,31 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+use cg;
use quote;
use syn;
-use synstructure;
+use synstructure::BindStyle;
pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
let name = &input.ident;
- let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
- let mut where_clause = where_clause.clone();
- for param in &input.generics.ty_params {
- where_clause.predicates.push(
- where_predicate(syn::Ty::Path(None, param.ident.clone().into())),
- );
- }
+ let (impl_generics, ty_generics, where_clause) = cg::trait_parts(
+ &input,
+ &["values", "animated", "ToAnimatedZero"],
+ );
- let to_body = match_body(&input);
+ let to_body = cg::fmap_match(&input, BindStyle::Ref, |field| {
+ quote! { ::values::animated::ToAnimatedZero::to_animated_zero(#field)? }
+ });
quote! {
impl #impl_generics ::values::animated::ToAnimatedZero for #name #ty_generics #where_clause {
#[allow(unused_variables)]
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
- match *self {
+ Ok(match *self {
#to_body
- }
+ })
}
}
}
}
-
-fn match_body(input: &syn::DeriveInput) -> quote::Tokens {
- synstructure::each_variant(&input, &synstructure::BindStyle::Ref.into(), |fields, variant| {
- let name = if let syn::Body::Enum(_) = input.body {
- format!("{}::{}", input.ident, variant.ident).into()
- } else {
- variant.ident.clone()
- };
- let (zero, computed_fields) = synstructure::match_pattern(
- &name,
- &variant.data,
- &synstructure::BindStyle::Move.into(),
- );
- let fields_pairs = fields.iter().zip(computed_fields.iter());
- let mut computations = quote!();
- computations.append_all(fields_pairs.map(|(field, computed_field)| {
- quote! {
- let #computed_field = ::values::animated::ToAnimatedZero::to_animated_zero(#field)?;
- }
- }));
- Some(quote!(
- #computations
- Ok(#zero)
- ))
- })
-}
-
-fn where_predicate(ty: syn::Ty) -> syn::WherePredicate {
- syn::WherePredicate::BoundPredicate(syn::WhereBoundPredicate {
- bound_lifetimes: vec![],
- bounded_ty: ty,
- bounds: vec![syn::TyParamBound::Trait(
- syn::PolyTraitRef {
- bound_lifetimes: vec![],
- trait_ref: syn::Path {
- global: true,
- segments: vec![
- "values".into(),
- "animated".into(),
- "ToAnimatedZero".into(),
- ],
- },
- },
- syn::TraitBoundModifier::None,
- )],
- })
-}
diff --git a/components/style_derive/to_computed_value.rs b/components/style_derive/to_computed_value.rs
index d7c4801dbf8..967f3320a37 100644
--- a/components/style_derive/to_computed_value.rs
+++ b/components/style_derive/to_computed_value.rs
@@ -2,49 +2,24 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+use cg;
use quote;
use syn;
-use synstructure;
+use synstructure::BindStyle;
pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
let name = &input.ident;
- let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
- let mut where_clause = where_clause.clone();
- for param in &input.generics.ty_params {
- where_clause.predicates.push(where_predicate(syn::Ty::Path(None, param.ident.clone().into()), None));
- }
-
- let computed_value_type = syn::Path::from(syn::PathSegment {
- ident: name.clone(),
- parameters: syn::PathParameters::AngleBracketed(syn::AngleBracketedParameterData {
- lifetimes: input.generics.lifetimes.iter().map(|l| {
- l.lifetime.clone()
- }).collect(),
- types: input.generics.ty_params.iter().map(|ty| {
- syn::Ty::Path(
- Some(syn::QSelf {
- ty: Box::new(syn::Ty::Path(None, ty.ident.clone().into())),
- position: 3,
- }),
- syn::Path {
- global: true,
- segments: vec![
- "values".into(),
- "computed".into(),
- "ToComputedValue".into(),
- "ComputedValue".into(),
- ],
- },
- )
- }).collect(),
- .. Default::default()
- }),
- });
-
- let to_body = match_body(&input, |field| {
+ let (impl_generics, ty_generics, where_clause, computed_value_type) =
+ cg::fmap_trait_parts(
+ &input,
+ &["values", "computed", "ToComputedValue"],
+ "ComputedValue",
+ );
+
+ let to_body = cg::fmap_match(&input, BindStyle::Ref, |field| {
quote!(::values::computed::ToComputedValue::to_computed_value(#field, context))
});
- let from_body = match_body(&input, |field| {
+ let from_body = cg::fmap_match(&input, BindStyle::Ref, |field| {
quote!(::values::computed::ToComputedValue::from_computed_value(#field))
});
@@ -69,74 +44,3 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
}
}
}
-
-fn match_body<F>(input: &syn::DeriveInput, f: F) -> quote::Tokens
- where F: Fn(&synstructure::BindingInfo) -> quote::Tokens,
-{
- let by_ref = synstructure::BindStyle::Ref.into();
- let by_value = synstructure::BindStyle::Move.into();
-
- synstructure::each_variant(&input, &by_ref, |fields, variant| {
- let name = if let syn::Body::Enum(_) = input.body {
- format!("{}::{}", input.ident, variant.ident).into()
- } else {
- variant.ident.clone()
- };
- let (computed_value, computed_fields) = synstructure::match_pattern(&name, &variant.data, &by_value);
- let fields_pairs = fields.iter().zip(computed_fields.iter());
- let mut computations = quote!();
- computations.append_all(fields_pairs.map(|(field, computed_field)| {
- let expr = f(field);
- quote!(let #computed_field = #expr;)
- }));
- Some(quote!(
- #computations
- #computed_value
- ))
- })
-}
-
-/// `#ty: ::values::computed::ToComputedValue<ComputedValue = #computed_value,>`
-fn where_predicate(ty: syn::Ty, computed_value: Option<syn::Ty>) -> syn::WherePredicate {
- syn::WherePredicate::BoundPredicate(syn::WhereBoundPredicate {
- bound_lifetimes: vec![],
- bounded_ty: ty,
- bounds: vec![syn::TyParamBound::Trait(
- syn::PolyTraitRef {
- bound_lifetimes: vec![],
- trait_ref: trait_ref(computed_value),
- },
- syn::TraitBoundModifier::None
- )],
- })
-}
-
-/// `::values::computed::ToComputedValue<ComputedValue = #computed_value,>`
-fn trait_ref(computed_value: Option<syn::Ty>) -> syn::Path {
- syn::Path {
- global: true,
- segments: vec![
- "values".into(),
- "computed".into(),
- syn::PathSegment {
- ident: "ToComputedValue".into(),
- parameters: syn::PathParameters::AngleBracketed(
- syn::AngleBracketedParameterData {
- bindings: trait_bindings(computed_value),
- .. Default::default()
- }
- ),
- }
- ],
- }
-}
-
-/// `ComputedValue = #computed_value,`
-fn trait_bindings(computed_value: Option<syn::Ty>) -> Vec<syn::TypeBinding> {
- computed_value.into_iter().map(|ty| {
- syn::TypeBinding {
- ident: "ComputedValue".into(),
- ty: ty,
- }
- }).collect()
-}
diff --git a/components/style_derive/to_css.rs b/components/style_derive/to_css.rs
index 2dbf8731e45..fbbccb5a493 100644
--- a/components/style_derive/to_css.rs
+++ b/components/style_derive/to_css.rs
@@ -2,17 +2,16 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+use cg;
use quote;
use syn;
use synstructure;
pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
let name = &input.ident;
- let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
- let mut where_clause = where_clause.clone();
- for param in &input.generics.ty_params {
- where_clause.predicates.push(where_predicate(syn::Ty::Path(None, param.ident.clone().into())))
- }
+ let trait_path = &["style_traits", "ToCss"];
+ let (impl_generics, ty_generics, mut where_clause) =
+ cg::trait_parts(&input, trait_path);
let style = synstructure::BindStyle::Ref.into();
let match_body = synstructure::each_variant(&input, &style, |bindings, variant| {
@@ -61,8 +60,10 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
let mut expr = if !bindings.is_empty() {
let mut expr = quote! {};
for binding in bindings {
- if has_free_params(&binding.field.ty, &input.generics.ty_params) {
- where_clause.predicates.push(where_predicate(binding.field.ty.clone()));
+ if cg::is_parameterized(&binding.field.ty, &input.generics.ty_params) {
+ where_clause.predicates.push(
+ cg::where_predicate(binding.field.ty.clone(), trait_path),
+ );
}
expr = quote! {
#expr
@@ -106,49 +107,6 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
}
}
-/// Returns whether `ty` is parameterized by any parameter from `params`.
-fn has_free_params(ty: &syn::Ty, params: &[syn::TyParam]) -> bool {
- use syn::visit::Visitor;
-
- struct HasFreeParams<'a> {
- params: &'a [syn::TyParam],
- has_free: bool,
- }
-
- impl<'a> Visitor for HasFreeParams<'a> {
- fn visit_path(&mut self, path: &syn::Path) {
- if !path.global && path.segments.len() == 1 {
- if self.params.iter().any(|param| param.ident == path.segments[0].ident) {
- self.has_free = true;
- }
- }
- syn::visit::walk_path(self, path);
- }
- }
-
- let mut visitor = HasFreeParams { params: params, has_free: false };
- visitor.visit_ty(ty);
- visitor.has_free
-}
-
-/// `#ty: ::style_traits::ToCss`
-fn where_predicate(ty: syn::Ty) -> syn::WherePredicate {
- syn::WherePredicate::BoundPredicate(syn::WhereBoundPredicate {
- bound_lifetimes: vec![],
- bounded_ty: ty,
- bounds: vec![syn::TyParamBound::Trait(
- syn::PolyTraitRef {
- bound_lifetimes: vec![],
- trait_ref: syn::Path {
- global: true,
- segments: vec!["style_traits".into(), "ToCss".into()],
- },
- },
- syn::TraitBoundModifier::None
- )],
- })
-}
-
/// Transforms "FooBar" to "foo-bar".
///
/// If the first Camel segment is "Moz" or "Webkit", the result string