mirror of
https://github.com/servo/servo.git
synced 2025-06-23 16:44:33 +01:00
Auto merge of #17291 - servo:derive-all-the-things, r=<try>
Function support for #[derive(ToCss)] and an Animatable fix
This commit is contained in:
commit
44eb8c8e4f
10 changed files with 100 additions and 80 deletions
|
@ -401,7 +401,7 @@ impl CounterStyleOrNone {
|
||||||
use gecko_bindings::bindings::Gecko_SetCounterStyleToName as set_name;
|
use gecko_bindings::bindings::Gecko_SetCounterStyleToName as set_name;
|
||||||
use gecko_bindings::bindings::Gecko_SetCounterStyleToSymbols as set_symbols;
|
use gecko_bindings::bindings::Gecko_SetCounterStyleToSymbols as set_symbols;
|
||||||
match self {
|
match self {
|
||||||
CounterStyleOrNone::None_ => unsafe {
|
CounterStyleOrNone::None => unsafe {
|
||||||
set_name(gecko_value, atom!("none").into_addrefed());
|
set_name(gecko_value, atom!("none").into_addrefed());
|
||||||
},
|
},
|
||||||
CounterStyleOrNone::Name(name) => unsafe {
|
CounterStyleOrNone::Name(name) => unsafe {
|
||||||
|
|
|
@ -1246,7 +1246,14 @@ impl Animatable for LengthOrPercentageOrNone {
|
||||||
(LengthOrPercentageOrNone::None, LengthOrPercentageOrNone::None) => {
|
(LengthOrPercentageOrNone::None, LengthOrPercentageOrNone::None) => {
|
||||||
Ok(LengthOrPercentageOrNone::None)
|
Ok(LengthOrPercentageOrNone::None)
|
||||||
}
|
}
|
||||||
_ => Err(())
|
(this, other) => {
|
||||||
|
let this = <Option<CalcLengthOrPercentage>>::from(this);
|
||||||
|
let other = <Option<CalcLengthOrPercentage>>::from(other);
|
||||||
|
match this.add_weighted(&other, self_portion, other_portion) {
|
||||||
|
Ok(Some(result)) => Ok(LengthOrPercentageOrNone::Calc(result)),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1273,7 +1280,12 @@ impl Animatable for LengthOrPercentageOrNone {
|
||||||
LengthOrPercentageOrNone::Percentage(ref other)) => {
|
LengthOrPercentageOrNone::Percentage(ref other)) => {
|
||||||
this.compute_distance(other)
|
this.compute_distance(other)
|
||||||
},
|
},
|
||||||
_ => Err(())
|
(this, other) => {
|
||||||
|
// If one of the element is Auto, Option<> will be None, and the returned distance is Err(())
|
||||||
|
let this = <Option<CalcLengthOrPercentage>>::from(this);
|
||||||
|
let other = <Option<CalcLengthOrPercentage>>::from(other);
|
||||||
|
this.compute_distance(&other)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
|
||||||
pub fn from_gecko_keyword(value: u32) -> Self {
|
pub fn from_gecko_keyword(value: u32) -> Self {
|
||||||
use gecko_bindings::structs;
|
use gecko_bindings::structs;
|
||||||
SpecifiedValue::CounterStyle(if value == structs::NS_STYLE_LIST_STYLE_NONE {
|
SpecifiedValue::CounterStyle(if value == structs::NS_STYLE_LIST_STYLE_NONE {
|
||||||
CounterStyleOrNone::None_
|
CounterStyleOrNone::None
|
||||||
} else {
|
} else {
|
||||||
<%
|
<%
|
||||||
values = """disc circle square decimal lower-roman
|
values = """disc circle square decimal lower-roman
|
||||||
|
|
|
@ -62,7 +62,7 @@
|
||||||
list_style_type::SpecifiedValue::none
|
list_style_type::SpecifiedValue::none
|
||||||
% else:
|
% else:
|
||||||
use values::generics::CounterStyleOrNone;
|
use values::generics::CounterStyleOrNone;
|
||||||
list_style_type::SpecifiedValue::CounterStyle(CounterStyleOrNone::None_)
|
list_style_type::SpecifiedValue::CounterStyle(CounterStyleOrNone::None)
|
||||||
% endif
|
% endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -157,6 +157,25 @@ impl From<LengthOrPercentageOrAuto> for Option<CalcLengthOrPercentage> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<LengthOrPercentageOrNone> for Option<CalcLengthOrPercentage> {
|
||||||
|
fn from(len: LengthOrPercentageOrNone) -> Option<CalcLengthOrPercentage> {
|
||||||
|
match len {
|
||||||
|
LengthOrPercentageOrNone::Percentage(this) => {
|
||||||
|
Some(CalcLengthOrPercentage::new(Au(0), Some(this)))
|
||||||
|
}
|
||||||
|
LengthOrPercentageOrNone::Length(this) => {
|
||||||
|
Some(CalcLengthOrPercentage::new(this, None))
|
||||||
|
}
|
||||||
|
LengthOrPercentageOrNone::Calc(this) => {
|
||||||
|
Some(this)
|
||||||
|
}
|
||||||
|
LengthOrPercentageOrNone::None => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ToCss for CalcLengthOrPercentage {
|
impl ToCss for CalcLengthOrPercentage {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
match (self.length, self.percentage) {
|
match (self.length, self.percentage) {
|
||||||
|
|
|
@ -92,7 +92,7 @@ pub struct Ellipse<H, V, LengthOrPercentage> {
|
||||||
/// https://drafts.csswg.org/css-shapes/#typedef-shape-radius
|
/// https://drafts.csswg.org/css-shapes/#typedef-shape-radius
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, ToComputedValue)]
|
#[derive(Clone, Copy, Debug, PartialEq, ToComputedValue, ToCss)]
|
||||||
pub enum ShapeRadius<LengthOrPercentage> {
|
pub enum ShapeRadius<LengthOrPercentage> {
|
||||||
Length(LengthOrPercentage),
|
Length(LengthOrPercentage),
|
||||||
ClosestSide,
|
ClosestSide,
|
||||||
|
@ -161,17 +161,6 @@ impl<L> Default for ShapeRadius<L> {
|
||||||
fn default() -> Self { ShapeRadius::ClosestSide }
|
fn default() -> Self { ShapeRadius::ClosestSide }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<L: ToCss> ToCss for ShapeRadius<L> {
|
|
||||||
#[inline]
|
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
|
||||||
match *self {
|
|
||||||
ShapeRadius::Length(ref lop) => lop.to_css(dest),
|
|
||||||
ShapeRadius::ClosestSide => dest.write_str("closest-side"),
|
|
||||||
ShapeRadius::FarthestSide => dest.write_str("farthest-side"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<L: ToCss> ToCss for Polygon<L> {
|
impl<L: ToCss> ToCss for Polygon<L> {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
dest.write_str("polygon(")?;
|
dest.write_str("polygon(")?;
|
||||||
|
|
|
@ -5,15 +5,13 @@
|
||||||
//! Generic types for legacy Gecko-only properties that should probably be
|
//! Generic types for legacy Gecko-only properties that should probably be
|
||||||
//! unshipped at some point in the future.
|
//! unshipped at some point in the future.
|
||||||
|
|
||||||
use std::fmt;
|
|
||||||
use style_traits::ToCss;
|
|
||||||
|
|
||||||
/// A generic value for scroll snap points.
|
/// A generic value for scroll snap points.
|
||||||
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
|
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue, ToCss)]
|
||||||
pub enum ScrollSnapPoint<LengthOrPercentage> {
|
pub enum ScrollSnapPoint<LengthOrPercentage> {
|
||||||
/// `none`
|
/// `none`
|
||||||
None,
|
None,
|
||||||
/// `repeat(<length-or-percentage>)`
|
/// `repeat(<length-or-percentage>)`
|
||||||
|
#[css(function)]
|
||||||
Repeat(LengthOrPercentage)
|
Repeat(LengthOrPercentage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,22 +31,3 @@ impl<L> ScrollSnapPoint<L> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<L> ToCss for ScrollSnapPoint<L>
|
|
||||||
where
|
|
||||||
L: ToCss,
|
|
||||||
{
|
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
|
||||||
where
|
|
||||||
W: fmt::Write,
|
|
||||||
{
|
|
||||||
match *self {
|
|
||||||
ScrollSnapPoint::None => dest.write_str("none"),
|
|
||||||
ScrollSnapPoint::Repeat(ref length) => {
|
|
||||||
dest.write_str("repeat(")?;
|
|
||||||
length.to_css(dest)?;
|
|
||||||
dest.write_str(")")
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -54,13 +54,14 @@ impl SymbolsType {
|
||||||
///
|
///
|
||||||
/// Since wherever <counter-style> is used, 'none' is a valid value as
|
/// Since wherever <counter-style> is used, 'none' is a valid value as
|
||||||
/// well, we combine them into one type to make code simpler.
|
/// well, we combine them into one type to make code simpler.
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, Eq, PartialEq, ToCss)]
|
||||||
pub enum CounterStyleOrNone {
|
pub enum CounterStyleOrNone {
|
||||||
/// none
|
/// `none`
|
||||||
None_,
|
None,
|
||||||
/// <counter-style-name>
|
/// `<counter-style-name>`
|
||||||
Name(CustomIdent),
|
Name(CustomIdent),
|
||||||
/// symbols()
|
/// `symbols()`
|
||||||
|
#[css(function)]
|
||||||
Symbols(SymbolsType, Symbols),
|
Symbols(SymbolsType, Symbols),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +85,7 @@ impl Parse for CounterStyleOrNone {
|
||||||
return Ok(CounterStyleOrNone::Name(name));
|
return Ok(CounterStyleOrNone::Name(name));
|
||||||
}
|
}
|
||||||
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
||||||
return Ok(CounterStyleOrNone::None_);
|
return Ok(CounterStyleOrNone::None);
|
||||||
}
|
}
|
||||||
if input.try(|i| i.expect_function_matching("symbols")).is_ok() {
|
if input.try(|i| i.expect_function_matching("symbols")).is_ok() {
|
||||||
return input.parse_nested_block(|input| {
|
return input.parse_nested_block(|input| {
|
||||||
|
@ -108,23 +109,6 @@ impl Parse for CounterStyleOrNone {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for CounterStyleOrNone {
|
|
||||||
#[inline]
|
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
|
||||||
match self {
|
|
||||||
&CounterStyleOrNone::None_ => dest.write_str("none"),
|
|
||||||
&CounterStyleOrNone::Name(ref name) => name.to_css(dest),
|
|
||||||
&CounterStyleOrNone::Symbols(ref symbols_type, ref symbols) => {
|
|
||||||
dest.write_str("symbols(")?;
|
|
||||||
symbols_type.to_css(dest)?;
|
|
||||||
dest.write_str(" ")?;
|
|
||||||
symbols.to_css(dest)?;
|
|
||||||
dest.write_str(")")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A settings tag, defined by a four-character tag and a setting value
|
/// A settings tag, defined by a four-character tag and a setting value
|
||||||
///
|
///
|
||||||
/// For font-feature-settings, this is a tag and an integer,
|
/// For font-feature-settings, this is a tag and an integer,
|
||||||
|
|
|
@ -25,7 +25,7 @@ pub fn derive_to_computed_value(stream: TokenStream) -> TokenStream {
|
||||||
to_computed_value::derive(input).to_string().parse().unwrap()
|
to_computed_value::derive(input).to_string().parse().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_derive(ToCss)]
|
#[proc_macro_derive(ToCss, attributes(css))]
|
||||||
pub fn derive_to_css(stream: TokenStream) -> TokenStream {
|
pub fn derive_to_css(stream: TokenStream) -> TokenStream {
|
||||||
let input = syn::parse_derive_input(&stream.to_string()).unwrap();
|
let input = syn::parse_derive_input(&stream.to_string()).unwrap();
|
||||||
to_css::derive(input).to_string().parse().unwrap()
|
to_css::derive(input).to_string().parse().unwrap()
|
||||||
|
|
|
@ -16,24 +16,61 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
||||||
|
|
||||||
let style = synstructure::BindStyle::Ref.into();
|
let style = synstructure::BindStyle::Ref.into();
|
||||||
let match_body = synstructure::each_variant(&input, &style, |bindings, variant| {
|
let match_body = synstructure::each_variant(&input, &style, |bindings, variant| {
|
||||||
if bindings.is_empty() {
|
let mut identifier = to_css_identifier(variant.ident.as_ref());
|
||||||
let identifier = to_css_identifier(variant.ident.as_ref());
|
let mut expr = if bindings.is_empty() {
|
||||||
return Some(quote! {
|
quote! {
|
||||||
::std::fmt::Write::write_str(dest, #identifier)
|
::std::fmt::Write::write_str(dest, #identifier)
|
||||||
});
|
}
|
||||||
}
|
} else {
|
||||||
let (first, rest) = bindings.split_first().expect("unit variants are not yet supported");
|
let (first, rest) = bindings.split_first().expect("unit variants are not yet supported");
|
||||||
where_clause.predicates.push(where_predicate(first.field.ty.clone()));
|
where_clause.predicates.push(where_predicate(first.field.ty.clone()));
|
||||||
let mut expr = quote! {
|
let mut expr = quote! {
|
||||||
::style_traits::ToCss::to_css(#first, dest)
|
::style_traits::ToCss::to_css(#first, dest)
|
||||||
};
|
|
||||||
for binding in rest {
|
|
||||||
where_clause.predicates.push(where_predicate(binding.field.ty.clone()));
|
|
||||||
expr = quote! {
|
|
||||||
#expr?;
|
|
||||||
::std::fmt::Write::write_str(dest, " ")?;
|
|
||||||
::style_traits::ToCss::to_css(#binding, dest)
|
|
||||||
};
|
};
|
||||||
|
for binding in rest {
|
||||||
|
where_clause.predicates.push(where_predicate(binding.field.ty.clone()));
|
||||||
|
expr = quote! {
|
||||||
|
#expr?;
|
||||||
|
::std::fmt::Write::write_str(dest, " ")?;
|
||||||
|
::style_traits::ToCss::to_css(#binding, dest)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
expr
|
||||||
|
};
|
||||||
|
let mut css_attrs = variant.attrs.iter().filter(|attr| attr.name() == "css");
|
||||||
|
let is_function = css_attrs.next().map_or(false, |attr| {
|
||||||
|
match attr.value {
|
||||||
|
syn::MetaItem::List(ref ident, ref items) if ident.as_ref() == "css" => {
|
||||||
|
let mut nested = items.iter();
|
||||||
|
let is_function = nested.next().map_or(false, |attr| {
|
||||||
|
match *attr {
|
||||||
|
syn::NestedMetaItem::MetaItem(syn::MetaItem::Word(ref ident)) => {
|
||||||
|
if ident.as_ref() != "function" {
|
||||||
|
panic!("only `#[css(function)]` is supported for now")
|
||||||
|
}
|
||||||
|
true
|
||||||
|
},
|
||||||
|
_ => 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
|
||||||
|
},
|
||||||
|
_ => panic!("only `#[css(...)]` is supported for now"),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if css_attrs.next().is_some() {
|
||||||
|
panic!("only a single `#[css(...)]` attribute is supported for now");
|
||||||
|
}
|
||||||
|
if is_function {
|
||||||
|
identifier.push_str("(");
|
||||||
|
expr = quote! {
|
||||||
|
::std::fmt::Write::write_str(dest, #identifier)?;
|
||||||
|
#expr?;
|
||||||
|
::std::fmt::Write::write_str(dest, ")")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Some(expr)
|
Some(expr)
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue