Bug 1457635: Move represents_keyword to the css attributes. r=xidorn
authorEmilio Cobos Álvarez <emilio@crisal.io>
Sun, 29 Apr 2018 04:48:47 +0200
changeset 472334 bfee15c5c84566738fc99380e55cb9de56d619ba
parent 472333 54a4ed5b619b646d63b3d7b5b04411d8ea0d151a
child 472335 3eb5075978e313bc6980a44a615863e479b68c05
push id1728
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:12:27 +0000
treeherdermozilla-release@c296fde26f5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersxidorn
bugs1457635
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1457635: Move represents_keyword to the css attributes. r=xidorn MozReview-Commit-ID: 21yuU4h34AQ
servo/components/style/values/generics/border.rs
servo/components/style/values/generics/effects.rs
servo/components/style/values/specified/font.rs
servo/components/style/values/specified/position.rs
servo/components/style_derive/specified_value_info.rs
servo/components/style_derive/to_css.rs
servo/components/style_traits/specified_value_info.rs
servo/components/style_traits/values.rs
--- a/servo/components/style/values/generics/border.rs
+++ b/servo/components/style/values/generics/border.rs
@@ -18,22 +18,23 @@ pub enum BorderImageSideWidth<LengthOrPe
     /// `<number>`
     Number(Number),
     /// `auto`
     Auto,
 }
 
 /// A generic value for the `border-image-slice` property.
 #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
-         ToComputedValue)]
+         ToComputedValue, ToCss)]
 pub struct BorderImageSlice<NumberOrPercentage> {
     /// The offsets.
+    #[css(field_bound)]
     pub offsets: Rect<NumberOrPercentage>,
     /// Whether to fill the middle part.
-    #[value_info(represents_keyword)]
+    #[css(represents_keyword)]
     pub fill: bool,
 }
 
 /// A generic value for the `border-*-radius` longhand properties.
 #[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
          PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
 pub struct BorderCornerRadius<L>(#[css(field_bound)] pub Size<L>);
 
@@ -81,32 +82,16 @@ where
     fn from(value: N) -> Self {
         Self {
             offsets: Rect::all(value),
             fill: false,
         }
     }
 }
 
-impl<N> ToCss for BorderImageSlice<N>
-where
-    N: PartialEq + ToCss,
-{
-    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
-    where
-        W: Write,
-    {
-        self.offsets.to_css(dest)?;
-        if self.fill {
-            dest.write_str(" fill")?;
-        }
-        Ok(())
-    }
-}
-
 impl<L> BorderRadius<L> {
     /// Returns a new `BorderRadius<L>`.
     #[inline]
     pub fn new(
         tl: BorderCornerRadius<L>,
         tr: BorderCornerRadius<L>,
         br: BorderCornerRadius<L>,
         bl: BorderCornerRadius<L>,
--- a/servo/components/style/values/generics/effects.rs
+++ b/servo/components/style/values/generics/effects.rs
@@ -1,30 +1,28 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
 //! Generic types for CSS values related to effects.
 
-use std::fmt::{self, Write};
-use style_traits::values::{CssWriter, SequenceWriter, ToCss};
 #[cfg(feature = "gecko")]
 use values::specified::url::SpecifiedUrl;
 
 /// A generic value for a single `box-shadow`.
 #[derive(Animate, Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
-         ToAnimatedValue, ToAnimatedZero)]
+         ToAnimatedValue, ToAnimatedZero, ToCss)]
 pub struct BoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> {
     /// The base shadow.
     pub base: SimpleShadow<Color, SizeLength, BlurShapeLength>,
     /// The spread radius.
     pub spread: ShapeLength,
     /// Whether this is an inset box shadow.
     #[animation(constant)]
-    #[value_info(represents_keyword)]
+    #[css(represents_keyword)]
     pub inset: bool,
 }
 
 /// A generic value for a single `filter`.
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
 #[derive(Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq,
          SpecifiedValueInfo, ToAnimatedValue, ToComputedValue, ToCss)]
 pub enum Filter<Angle, Factor, Length, DropShadow> {
@@ -75,32 +73,8 @@ pub struct SimpleShadow<Color, SizeLengt
     pub color: Color,
     /// Horizontal radius.
     pub horizontal: SizeLength,
     /// Vertical radius.
     pub vertical: SizeLength,
     /// Blur radius.
     pub blur: ShapeLength,
 }
-
-impl<Color, SizeLength, BlurShapeLength, ShapeLength> ToCss
-    for BoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength>
-where
-    Color: ToCss,
-    SizeLength: ToCss,
-    BlurShapeLength: ToCss,
-    ShapeLength: ToCss,
-{
-    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
-    where
-        W: Write,
-    {
-        {
-            let mut writer = SequenceWriter::new(&mut *dest, " ");
-            writer.item(&self.base)?;
-            writer.item(&self.spread)?;
-        }
-        if self.inset {
-            dest.write_str(" inset")?;
-        }
-        Ok(())
-    }
-}
--- a/servo/components/style/values/specified/font.rs
+++ b/servo/components/style/values/specified/font.rs
@@ -1942,21 +1942,21 @@ impl Parse for FontFeatureSettings {
 #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
          ToComputedValue)]
 /// Whether user agents are allowed to synthesize bold or oblique font faces
 /// when a font family lacks bold or italic faces
 pub struct FontSynthesis {
     /// If a `font-weight` is requested that the font family does not contain,
     /// the user agent may synthesize the requested weight from the weights
     /// that do exist in the font family.
-    #[value_info(represents_keyword)]
+    #[css(represents_keyword)]
     pub weight: bool,
     /// If a font-style is requested that the font family does not contain,
     /// the user agent may synthesize the requested style from the normal face in the font family.
-    #[value_info(represents_keyword)]
+    #[css(represents_keyword)]
     pub style: bool,
 }
 
 impl FontSynthesis {
     #[inline]
     /// Get the default value of font-synthesis
     pub fn get_initial_value() -> Self {
         FontSynthesis {
--- a/servo/components/style/values/specified/position.rs
+++ b/servo/components/style/values/specified/position.rs
@@ -419,52 +419,38 @@ pub enum AutoFlow {
     /// adding new rows as necessary.
     Row,
     /// The auto-placement algorithm places items by filling each column in turn,
     /// adding new columns as necessary.
     Column,
 }
 
 #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
-         ToComputedValue)]
+         ToComputedValue, ToCss)]
 /// Controls how the auto-placement algorithm works
 /// specifying exactly how auto-placed items get flowed into the grid
 pub struct GridAutoFlow {
     /// Specifiy how auto-placement algorithm fills each `row` or `column` in turn
     pub autoflow: AutoFlow,
     /// Specify use `dense` packing algorithm or not
-    #[value_info(represents_keyword)]
+    #[css(represents_keyword)]
     pub dense: bool,
 }
 
 impl GridAutoFlow {
     #[inline]
     /// Get default `grid-auto-flow` as `row`
     pub fn row() -> GridAutoFlow {
         GridAutoFlow {
             autoflow: AutoFlow::Row,
             dense: false,
         }
     }
 }
 
-impl ToCss for GridAutoFlow {
-    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
-    where
-        W: Write,
-    {
-        self.autoflow.to_css(dest)?;
-
-        if self.dense {
-            dest.write_str(" dense")?;
-        }
-        Ok(())
-    }
-}
-
 impl Parse for GridAutoFlow {
     /// [ row | column ] || dense
     fn parse<'i, 't>(
         _context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<GridAutoFlow, ParseError<'i>> {
         let mut value = None;
         let mut dense = false;
--- a/servo/components/style_derive/specified_value_info.rs
+++ b/servo/components/style_derive/specified_value_info.rs
@@ -135,23 +135,23 @@ fn derive_struct_fields<'a>(
     };
     types.extend(fields.filter_map(|field| {
         let info_attrs = cg::parse_field_attrs::<ValueInfoFieldAttrs>(field);
         if let Some(other_values) = info_attrs.other_values {
             for value in other_values.split(",") {
                 values.push(value.to_string());
             }
         }
-        if info_attrs.represents_keyword {
+        let css_attrs = cg::parse_field_attrs::<CssFieldAttrs>(field);
+        if css_attrs.represents_keyword {
             let ident = field.ident.as_ref()
                 .expect("only named field should use represents_keyword");
             values.push(cg::to_css_identifier(ident.as_ref()));
             return None;
         }
-        let css_attrs = cg::parse_field_attrs::<CssFieldAttrs>(field);
         if let Some(if_empty) = css_attrs.if_empty {
             values.push(if_empty);
         }
         if !css_attrs.skip {
             Some(&field.ty)
         } else {
             None
         }
@@ -171,11 +171,10 @@ struct ValueInfoInputAttrs {
 struct ValueInfoVariantAttrs {
     starts_with_keyword: bool,
     other_values: Option<String>,
 }
 
 #[darling(attributes(value_info), default)]
 #[derive(Default, FromField)]
 struct ValueInfoFieldAttrs {
-    represents_keyword: bool,
     other_values: Option<String>,
 }
--- a/servo/components/style_derive/to_css.rs
+++ b/servo/components/style_derive/to_css.rs
@@ -184,16 +184,25 @@ fn derive_single_field_expr(
                 }
             };
         }
         quote! {
             for item in #field.iter() {
                 writer.item(&item)?;
             }
         }
+    } else if attrs.represents_keyword {
+        let ident =
+            field.ast().ident.as_ref().expect("Unnamed field with represents_keyword?");
+        let ident = cg::to_css_identifier(ident.as_ref());
+        quote! {
+            if *#field {
+                writer.raw_item(#ident)?;
+            }
+        }
     } else {
         if attrs.field_bound {
             let ty = &field.ast().ty;
             cg::add_predicate(where_clause, parse_quote!(#ty: ::style_traits::ToCss));
         }
         quote! { writer.item(#field)?; }
     };
 
@@ -231,10 +240,11 @@ pub struct CssVariantAttrs {
 
 #[darling(attributes(css), default)]
 #[derive(Default, FromField)]
 pub struct CssFieldAttrs {
     pub if_empty: Option<String>,
     pub field_bound: bool,
     pub iterable: bool,
     pub skip: bool,
+    pub represents_keyword: bool,
     pub skip_if: Option<Path>,
 }
--- a/servo/components/style_traits/specified_value_info.rs
+++ b/servo/components/style_traits/specified_value_info.rs
@@ -51,18 +51,16 @@ pub type KeywordsCollectFn<'a> = &'a mut
 /// * `#[value_info(ty = "TYPE")]` can be used to specify a constant
 ///   from `CssType` to `SUPPORTED_TYPES`.
 /// * `#[value_info(other_values = "value1,value2")]` can be used to
 ///   add other values related to a field, variant, or the type itself
 ///   into `collect_completion_keywords`.
 /// * `#[value_info(starts_with_keyword)]` can be used on variants to
 ///   add the name of a non-unit variant (serialized like `ToCss`) into
 ///   `collect_completion_keywords`.
-/// * `#[value_info(represents_keyword)]` can be used on fields into
-///   `collect_completion_keywords`.
 pub trait SpecifiedValueInfo {
     /// Supported CssTypes by the given value type.
     ///
     /// XXX This should be typed CssType when that becomes a bitflags.
     /// Currently we cannot do so since bitflags cannot be used in constant.
     const SUPPORTED_TYPES: u8 = 0;
 
     /// Collect value starting words for the given specified value type.
--- a/servo/components/style_traits/values.rs
+++ b/servo/components/style_traits/values.rs
@@ -32,16 +32,19 @@ use std::fmt::{self, Write};
 /// * if `#[css(dimension)]` is found on a variant, that variant needs
 ///   to have a single member. The variant would be serialized as a CSS
 ///   dimension token, like: <member><identifier>;
 /// * if `#[css(skip)]` is found on a field, the `ToCss` call for that field
 ///   is skipped;
 /// * if `#[css(skip_if = "function")]` is found on a field, the `ToCss` call
 ///   for that field is skipped if `function` returns true. This function is
 ///   provided the field as an argument;
+/// * `#[css(represents_keyword)]` can be used on bool fields in order to
+///   serialize the field name if the field is true, or nothing otherwise.  It
+///   also collects those keywords for `SpecifiedValueInfo`.
 /// * finally, one can put `#[css(derive_debug)]` on the whole type, to
 ///   implement `Debug` by a single call to `ToCss::to_css`.
 pub trait ToCss {
     /// Serialize `self` in CSS syntax, writing to `dest`.
     fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: Write;
 
     /// Serialize `self` in CSS syntax and return a string.
     ///