mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Auto merge of #18208 - servo:derive-all-the-things, r=emilio
Use darling and derive more things <!-- 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/18208) <!-- Reviewable:end -->
This commit is contained in:
commit
d3c2017b23
10 changed files with 95 additions and 106 deletions
40
Cargo.lock
generated
40
Cargo.lock
generated
|
@ -615,6 +615,36 @@ dependencies = [
|
|||
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"darling_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"darling_macro 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ident_case 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"darling_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dbghelp-sys"
|
||||
version = "0.2.0"
|
||||
|
@ -1306,6 +1336,11 @@ dependencies = [
|
|||
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.1.2"
|
||||
|
@ -3073,6 +3108,7 @@ dependencies = [
|
|||
name = "style_derive"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"darling 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"synstructure 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3711,6 +3747,9 @@ dependencies = [
|
|||
"checksum core-text 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "16ce16d9ed00181016c11ff48e561314bec92bfbce9fe48f319366618d4e5de6"
|
||||
"checksum cssparser 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1f9442c00898020a56c9485d64c9c8f14ae30ba45be89d15846046593383467f"
|
||||
"checksum cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "079adec4af52bb5275eadd004292028c79eb3c5f5b4ee8086a36d4197032f6df"
|
||||
"checksum darling 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9861a8495606435477df581bc858ccf15a3469747edf175b94a4704fd9aaedac"
|
||||
"checksum darling_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1486a8b00b45062c997f767738178b43219133dd0c8c826cb811e60563810821"
|
||||
"checksum darling_macro 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a86ec160aa0c3dd492dd4a14ec8104ad8f1a9400a820624db857998cc1f80f9"
|
||||
"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
|
||||
"checksum dbus 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4aee01fb76ada3e5e7ca642ea6664ebf7308a810739ca2aca44909a1191ac254"
|
||||
"checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3"
|
||||
|
@ -3769,6 +3808,7 @@ dependencies = [
|
|||
"checksum hyper 0.10.10 (registry+https://github.com/rust-lang/crates.io-index)" = "36e108e0b1fa2d17491cbaac4bc460dc0956029d10ccf83c913dd0e5db3e7f07"
|
||||
"checksum hyper-openssl 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "85a372eb692590b3fe014c196c30f9f52d4c42f58cd49dd94caeee1593c9cc37"
|
||||
"checksum hyper_serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cbe43f514f80494e9329c9fc47d61b85b167d245685424637a0f4a409177e444"
|
||||
"checksum ident_case 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c9826188e666f2ed92071d2dadef6edc430b11b158b5b2b3f4babbcc891eaaa"
|
||||
"checksum idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2233d4940b1f19f0418c158509cd7396b8d70a5db5705ce410914dc8fa603b37"
|
||||
"checksum image 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d95816db758249fe16f23a4e23f1a3a817fe11892dbfd1c5836f625324702158"
|
||||
"checksum immeta 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0b9260463a221bfe3f02100c56e2d14c050d5ffe7e44a43d0a1b2b1f2b523502"
|
||||
|
|
|
@ -787,40 +787,6 @@ impl ToAnimatedZero for Visibility {
|
|||
}
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/css-transitions/#animtype-length
|
||||
impl Animate for VerticalAlign {
|
||||
#[inline]
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
match (self, other) {
|
||||
(
|
||||
&VerticalAlign::LengthOrPercentage(ref this),
|
||||
&VerticalAlign::LengthOrPercentage(ref other),
|
||||
) => {
|
||||
Ok(VerticalAlign::LengthOrPercentage(
|
||||
this.animate(other, procedure)?
|
||||
))
|
||||
},
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeSquaredDistance for VerticalAlign {
|
||||
#[inline]
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
||||
match (self, other) {
|
||||
(&VerticalAlign::LengthOrPercentage(ref this), &VerticalAlign::LengthOrPercentage(ref other)) => {
|
||||
this.compute_squared_distance(other)
|
||||
},
|
||||
_ => {
|
||||
// FIXME(nox): Should this return `Ok(SquaredDistance::Value(0.))`
|
||||
// if `self` and `other` are the same keyword value?
|
||||
Err(())
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToAnimatedZero for VerticalAlign {
|
||||
#[inline]
|
||||
fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
|
||||
|
@ -2459,24 +2425,6 @@ impl ToAnimatedZero for TransformList {
|
|||
}
|
||||
}
|
||||
|
||||
impl<A, B> ToAnimatedZero for Either<A, B>
|
||||
where
|
||||
A: ToAnimatedZero,
|
||||
B: ToAnimatedZero,
|
||||
{
|
||||
#[inline]
|
||||
fn to_animated_zero(&self) -> Result<Self, ()> {
|
||||
match *self {
|
||||
Either::First(ref first) => {
|
||||
Ok(Either::First(first.to_animated_zero()?))
|
||||
},
|
||||
Either::Second(ref second) => {
|
||||
Ok(Either::Second(second.to_animated_zero()?))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Animated SVGPaint
|
||||
pub type IntermediateSVGPaint = SVGPaint<AnimatedRGBA, ComputedUrl>;
|
||||
|
||||
|
|
|
@ -370,11 +370,12 @@ ${helpers.single_keyword("position", "static absolute relative fixed",
|
|||
/// The keywords are the same, and the `LengthOrPercentage` is computed
|
||||
/// here.
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, PartialEq)]
|
||||
pub enum T {
|
||||
% for keyword in vertical_align_keywords:
|
||||
${to_rust_ident(keyword)},
|
||||
#[animation(error)] // only animatable as a length
|
||||
${to_rust_ident(keyword)},
|
||||
% endfor
|
||||
LengthOrPercentage(computed::LengthOrPercentage),
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ impl Parse for Impossible {
|
|||
/// A struct representing one of two kinds of values.
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, HasViewportPercentage)]
|
||||
#[derive(PartialEq, ToAnimatedValue, ToComputedValue, ToCss)]
|
||||
#[derive(PartialEq, ToAnimatedValue, ToAnimatedZero, ToComputedValue, ToCss)]
|
||||
pub enum Either<A, B> {
|
||||
/// The first value.
|
||||
First(A),
|
||||
|
|
|
@ -10,6 +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"
|
||||
|
|
|
@ -14,7 +14,13 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
|||
|
||||
let variants = cg::variants(&input);
|
||||
let mut match_body = quote!();
|
||||
match_body.append_all(variants.iter().map(|variant| {
|
||||
let mut append_error_clause = variants.len() > 1;
|
||||
match_body.append_all(variants.iter().flat_map(|variant| {
|
||||
let attrs = cg::parse_variant_attrs::<AnimateAttrs>(variant);
|
||||
if attrs.error {
|
||||
append_error_clause = true;
|
||||
return None;
|
||||
}
|
||||
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");
|
||||
|
@ -29,15 +35,15 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
|||
let #result = ::values::animated::Animate::animate(#this, #other, procedure)?;
|
||||
}
|
||||
}));
|
||||
quote! {
|
||||
Some(quote! {
|
||||
(&#this_pattern, &#other_pattern) => {
|
||||
#computations
|
||||
Ok(#result_value)
|
||||
}
|
||||
}
|
||||
})
|
||||
}));
|
||||
|
||||
if variants.len() > 1 {
|
||||
if append_error_clause {
|
||||
match_body = quote! { #match_body, _ => Err(()), };
|
||||
}
|
||||
|
||||
|
@ -57,3 +63,9 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, FromVariant)]
|
||||
#[darling(attributes(animate), default)]
|
||||
pub struct AnimateAttrs {
|
||||
pub error: bool,
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* 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 darling::FromVariant;
|
||||
use quote::Tokens;
|
||||
use std::borrow::Cow;
|
||||
use std::iter;
|
||||
|
@ -136,6 +137,16 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse_variant_attrs<A>(variant: &Variant) -> A
|
||||
where
|
||||
A: FromVariant,
|
||||
{
|
||||
match A::from_variant(variant) {
|
||||
Ok(attrs) => attrs,
|
||||
Err(e) => panic!("failed to parse attributes: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ref_pattern<'a>(
|
||||
name: &Ident,
|
||||
variant: &'a Variant,
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* 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 animate::AnimateAttrs;
|
||||
use cg;
|
||||
use quote;
|
||||
use syn;
|
||||
|
@ -14,7 +15,13 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
|||
|
||||
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::<AnimateAttrs>(variant);
|
||||
if attrs.error {
|
||||
append_error_clause = true;
|
||||
return None;
|
||||
}
|
||||
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");
|
||||
|
@ -32,14 +39,14 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
|||
}), "+");
|
||||
sum
|
||||
};
|
||||
quote! {
|
||||
Some(quote! {
|
||||
(&#this_pattern, &#other_pattern) => {
|
||||
Ok(#sum)
|
||||
}
|
||||
}
|
||||
})
|
||||
}));
|
||||
|
||||
if variants.len() > 1 {
|
||||
if append_error_clause {
|
||||
match_body = quote! { #match_body, _ => Err(()), };
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* 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/. */
|
||||
|
||||
#[macro_use] extern crate darling;
|
||||
extern crate proc_macro;
|
||||
#[macro_use] extern crate quote;
|
||||
extern crate syn;
|
||||
|
@ -18,13 +19,13 @@ mod to_animated_zero;
|
|||
mod to_computed_value;
|
||||
mod to_css;
|
||||
|
||||
#[proc_macro_derive(Animate)]
|
||||
#[proc_macro_derive(Animate, attributes(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()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(ComputeSquaredDistance)]
|
||||
#[proc_macro_derive(ComputeSquaredDistance, attributes(animation))]
|
||||
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()
|
||||
|
|
|
@ -16,47 +16,8 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
|||
let style = synstructure::BindStyle::Ref.into();
|
||||
let match_body = synstructure::each_variant(&input, &style, |bindings, variant| {
|
||||
let mut identifier = to_css_identifier(variant.ident.as_ref());
|
||||
let mut css_attrs = variant.attrs.iter().filter(|attr| attr.name() == "css");
|
||||
let (is_function, use_comma) = css_attrs.next().map_or((false, false), |attr| {
|
||||
match attr.value {
|
||||
syn::MetaItem::List(ref ident, ref items) if ident.as_ref() == "css" => {
|
||||
let mut nested = items.iter();
|
||||
let mut is_function = false;
|
||||
let mut use_comma = false;
|
||||
for attr in nested.by_ref() {
|
||||
match *attr {
|
||||
syn::NestedMetaItem::MetaItem(syn::MetaItem::Word(ref ident)) => {
|
||||
match ident.as_ref() {
|
||||
"function" => {
|
||||
if is_function {
|
||||
panic!("repeated `#[css(function)]` attribute");
|
||||
}
|
||||
is_function = true;
|
||||
},
|
||||
"comma" => {
|
||||
if use_comma {
|
||||
panic!("repeated `#[css(comma)]` attribute");
|
||||
}
|
||||
use_comma = true;
|
||||
},
|
||||
_ => panic!("only `#[css(function | comma)]` is supported for now"),
|
||||
}
|
||||
},
|
||||
_ => panic!("only `#[css(<ident...>)]` is supported for now"),
|
||||
}
|
||||
}
|
||||
if nested.next().is_some() {
|
||||
panic!("only `#[css()]` or `#[css(<ident>)]` is supported for now")
|
||||
}
|
||||
(is_function, use_comma)
|
||||
},
|
||||
_ => panic!("only `#[css(...)]` is supported for now"),
|
||||
}
|
||||
});
|
||||
if css_attrs.next().is_some() {
|
||||
panic!("only a single `#[css(...)]` attribute is supported for now");
|
||||
}
|
||||
let separator = if use_comma { ", " } else { " " };
|
||||
let css_attrs = cg::parse_variant_attrs::<CssAttrs>(variant);
|
||||
let separator = if css_attrs.comma { ", " } else { " " };
|
||||
let mut expr = if !bindings.is_empty() {
|
||||
let mut expr = quote! {};
|
||||
for binding in bindings {
|
||||
|
@ -80,7 +41,7 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
|||
::std::fmt::Write::write_str(dest, #identifier)
|
||||
}
|
||||
};
|
||||
if is_function {
|
||||
if css_attrs.function {
|
||||
identifier.push_str("(");
|
||||
expr = quote! {
|
||||
::std::fmt::Write::write_str(dest, #identifier)?;
|
||||
|
@ -107,6 +68,13 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default, FromVariant)]
|
||||
#[darling(attributes(css), default)]
|
||||
struct CssAttrs {
|
||||
function: bool,
|
||||
comma: bool,
|
||||
}
|
||||
|
||||
/// 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