diff --git a/components/style/gecko/values.rs b/components/style/gecko/values.rs index f2a92e1ec89..041387dd54c 100644 --- a/components/style/gecko/values.rs +++ b/components/style/gecko/values.rs @@ -401,7 +401,7 @@ impl CounterStyleOrNone { use gecko_bindings::bindings::Gecko_SetCounterStyleToName as set_name; use gecko_bindings::bindings::Gecko_SetCounterStyleToSymbols as set_symbols; match self { - CounterStyleOrNone::None_ => unsafe { + CounterStyleOrNone::None => unsafe { set_name(gecko_value, atom!("none").into_addrefed()); }, CounterStyleOrNone::Name(name) => unsafe { diff --git a/components/style/properties/longhand/list.mako.rs b/components/style/properties/longhand/list.mako.rs index 6f25334698e..7b5b2879dd9 100644 --- a/components/style/properties/longhand/list.mako.rs +++ b/components/style/properties/longhand/list.mako.rs @@ -63,7 +63,7 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu pub fn from_gecko_keyword(value: u32) -> Self { use gecko_bindings::structs; SpecifiedValue::CounterStyle(if value == structs::NS_STYLE_LIST_STYLE_NONE { - CounterStyleOrNone::None_ + CounterStyleOrNone::None } else { <% values = """disc circle square decimal lower-roman diff --git a/components/style/properties/shorthand/list.mako.rs b/components/style/properties/shorthand/list.mako.rs index 4ea2647e141..8f591760ec7 100644 --- a/components/style/properties/shorthand/list.mako.rs +++ b/components/style/properties/shorthand/list.mako.rs @@ -62,7 +62,7 @@ list_style_type::SpecifiedValue::none % else: use values::generics::CounterStyleOrNone; - list_style_type::SpecifiedValue::CounterStyle(CounterStyleOrNone::None_) + list_style_type::SpecifiedValue::CounterStyle(CounterStyleOrNone::None) % endif } diff --git a/components/style/values/generics/gecko.rs b/components/style/values/generics/gecko.rs index 52c7b130992..31c62078861 100644 --- a/components/style/values/generics/gecko.rs +++ b/components/style/values/generics/gecko.rs @@ -5,15 +5,13 @@ //! Generic types for legacy Gecko-only properties that should probably be //! unshipped at some point in the future. -use std::fmt; -use style_traits::ToCss; - /// 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 { /// `none` None, /// `repeat()` + #[css(function)] Repeat(LengthOrPercentage) } @@ -33,22 +31,3 @@ impl ScrollSnapPoint { } } } - -impl ToCss for ScrollSnapPoint -where - L: ToCss, -{ - fn to_css(&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(")") - }, - } - } -} diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs index 4d0a3315560..3d218b0bdf5 100644 --- a/components/style/values/generics/mod.rs +++ b/components/style/values/generics/mod.rs @@ -54,13 +54,14 @@ impl SymbolsType { /// /// Since wherever is used, 'none' is a valid value as /// 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 { - /// none - None_, - /// + /// `none` + None, + /// `` Name(CustomIdent), - /// symbols() + /// `symbols()` + #[css(function)] Symbols(SymbolsType, Symbols), } @@ -84,7 +85,7 @@ impl Parse for CounterStyleOrNone { return Ok(CounterStyleOrNone::Name(name)); } 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() { return input.parse_nested_block(|input| { @@ -108,23 +109,6 @@ impl Parse for CounterStyleOrNone { } } -impl ToCss for CounterStyleOrNone { - #[inline] - fn to_css(&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 /// /// For font-feature-settings, this is a tag and an integer, diff --git a/components/style_derive/lib.rs b/components/style_derive/lib.rs index 0f39a7deca1..6264e8186e1 100644 --- a/components/style_derive/lib.rs +++ b/components/style_derive/lib.rs @@ -25,7 +25,7 @@ pub fn derive_to_computed_value(stream: TokenStream) -> TokenStream { 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 { let input = syn::parse_derive_input(&stream.to_string()).unwrap(); to_css::derive(input).to_string().parse().unwrap() diff --git a/components/style_derive/to_css.rs b/components/style_derive/to_css.rs index f85fe1ce418..8531b39ab46 100644 --- a/components/style_derive/to_css.rs +++ b/components/style_derive/to_css.rs @@ -16,24 +16,61 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens { let style = synstructure::BindStyle::Ref.into(); let match_body = synstructure::each_variant(&input, &style, |bindings, variant| { - if bindings.is_empty() { - let identifier = to_css_identifier(variant.ident.as_ref()); - return Some(quote! { + let mut identifier = to_css_identifier(variant.ident.as_ref()); + let mut expr = if bindings.is_empty() { + quote! { ::std::fmt::Write::write_str(dest, #identifier) - }); - } - let (first, rest) = bindings.split_first().expect("unit variants are not yet supported"); - where_clause.predicates.push(where_predicate(first.field.ty.clone())); - let mut expr = quote! { - ::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) + } + } else { + let (first, rest) = bindings.split_first().expect("unit variants are not yet supported"); + where_clause.predicates.push(where_predicate(first.field.ty.clone())); + let mut expr = quote! { + ::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) + }; + } + 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()]` is supported for now"), + } + }); + if nested.next().is_some() { + panic!("only `#[css()]` or `#[css()]` 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) });