mirror of
https://github.com/servo/servo.git
synced 2025-08-09 15:35:34 +01:00
Introduce style_derive::cg
This commit is contained in:
parent
1c9c0334ba
commit
f275895028
9 changed files with 289 additions and 483 deletions
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue