aboutsummaryrefslogtreecommitdiffstats
path: root/components/style_derive
diff options
context:
space:
mode:
authorBastien Orivel <eijebong@bananium.fr>2018-02-12 16:49:28 +0100
committerBastien Orivel <eijebong@bananium.fr>2018-02-12 17:08:55 +0100
commit9faa579c892ed4e45faf40a161e42da95a11f14c (patch)
treeee731f096a36c8e631374648345cff6e79562a69 /components/style_derive
parentcf6330b6c169273d5c0de7b6e39dbd9d48c36111 (diff)
downloadservo-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.toml8
-rw-r--r--components/style_derive/animate.rs53
-rw-r--r--components/style_derive/cg.rs353
-rw-r--r--components/style_derive/compute_squared_distance.rs38
-rw-r--r--components/style_derive/lib.rs30
-rw-r--r--components/style_derive/parse.rs24
-rw-r--r--components/style_derive/to_animated_value.rs8
-rw-r--r--components/style_derive/to_animated_zero.rs31
-rw-r--r--components/style_derive/to_computed_value.rs20
-rw-r--r--components/style_derive/to_css.rs29
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) })
}
}