mirror of
https://github.com/servo/servo.git
synced 2025-07-26 00:30:22 +01:00
style: Add some attributes for SpecifiedValueInfo to help deriving more from types.
Bug: 1434130 Reviewed-by: emilio MozReview-Commit-ID: IyohSTbUO31
This commit is contained in:
parent
0021c70c08
commit
0f7f9eebc0
17 changed files with 137 additions and 36 deletions
|
@ -69,6 +69,7 @@ pub enum BasicShape<H, V, LengthOrPercentage> {
|
||||||
|
|
||||||
/// <https://drafts.csswg.org/css-shapes/#funcdef-inset>
|
/// <https://drafts.csswg.org/css-shapes/#funcdef-inset>
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
|
#[css(function = "inset")]
|
||||||
#[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq,
|
#[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq,
|
||||||
SpecifiedValueInfo, ToComputedValue)]
|
SpecifiedValueInfo, ToComputedValue)]
|
||||||
pub struct InsetRect<LengthOrPercentage> {
|
pub struct InsetRect<LengthOrPercentage> {
|
||||||
|
@ -78,6 +79,7 @@ pub struct InsetRect<LengthOrPercentage> {
|
||||||
|
|
||||||
/// <https://drafts.csswg.org/css-shapes/#funcdef-circle>
|
/// <https://drafts.csswg.org/css-shapes/#funcdef-circle>
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
|
#[css(function)]
|
||||||
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
|
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
|
||||||
PartialEq, SpecifiedValueInfo, ToComputedValue)]
|
PartialEq, SpecifiedValueInfo, ToComputedValue)]
|
||||||
pub struct Circle<H, V, LengthOrPercentage> {
|
pub struct Circle<H, V, LengthOrPercentage> {
|
||||||
|
@ -87,6 +89,7 @@ pub struct Circle<H, V, LengthOrPercentage> {
|
||||||
|
|
||||||
/// <https://drafts.csswg.org/css-shapes/#funcdef-ellipse>
|
/// <https://drafts.csswg.org/css-shapes/#funcdef-ellipse>
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
|
#[css(function)]
|
||||||
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
|
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
|
||||||
PartialEq, SpecifiedValueInfo, ToComputedValue)]
|
PartialEq, SpecifiedValueInfo, ToComputedValue)]
|
||||||
pub struct Ellipse<H, V, LengthOrPercentage> {
|
pub struct Ellipse<H, V, LengthOrPercentage> {
|
||||||
|
@ -110,6 +113,7 @@ pub enum ShapeRadius<LengthOrPercentage> {
|
||||||
/// A generic type for representing the `polygon()` function
|
/// A generic type for representing the `polygon()` function
|
||||||
///
|
///
|
||||||
/// <https://drafts.csswg.org/css-shapes/#funcdef-polygon>
|
/// <https://drafts.csswg.org/css-shapes/#funcdef-polygon>
|
||||||
|
#[css(function)]
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
||||||
ToComputedValue)]
|
ToComputedValue)]
|
||||||
pub struct Polygon<LengthOrPercentage> {
|
pub struct Polygon<LengthOrPercentage> {
|
||||||
|
|
|
@ -28,6 +28,7 @@ pub struct BorderImageSlice<NumberOrPercentage> {
|
||||||
/// The offsets.
|
/// The offsets.
|
||||||
pub offsets: Rect<NumberOrPercentage>,
|
pub offsets: Rect<NumberOrPercentage>,
|
||||||
/// Whether to fill the middle part.
|
/// Whether to fill the middle part.
|
||||||
|
#[value_info(represents_keyword)]
|
||||||
pub fill: bool,
|
pub fill: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ impl<I> Deref for CounterReset<I> {
|
||||||
/// Keyword `none` is represented by an empty vector.
|
/// Keyword `none` is represented by an empty vector.
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
||||||
ToComputedValue)]
|
ToComputedValue)]
|
||||||
pub struct Counters<I>(Box<[(CustomIdent, I)]>);
|
pub struct Counters<I>(#[css(if_empty = "none")] Box<[(CustomIdent, I)]>);
|
||||||
|
|
||||||
impl<I> Default for Counters<I> {
|
impl<I> Default for Counters<I> {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -19,6 +19,7 @@ pub struct BoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> {
|
||||||
pub spread: ShapeLength,
|
pub spread: ShapeLength,
|
||||||
/// Whether this is an inset box shadow.
|
/// Whether this is an inset box shadow.
|
||||||
#[animation(constant)]
|
#[animation(constant)]
|
||||||
|
#[value_info(represents_keyword)]
|
||||||
pub inset: bool,
|
pub inset: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -198,10 +198,12 @@ pub enum TrackSize<L> {
|
||||||
/// and a flexible `<track-breadth>`
|
/// and a flexible `<track-breadth>`
|
||||||
///
|
///
|
||||||
/// <https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-minmax>
|
/// <https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-minmax>
|
||||||
|
#[css(function)]
|
||||||
Minmax(TrackBreadth<L>, TrackBreadth<L>),
|
Minmax(TrackBreadth<L>, TrackBreadth<L>),
|
||||||
/// A `fit-content` function.
|
/// A `fit-content` function.
|
||||||
///
|
///
|
||||||
/// <https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-fit-content>
|
/// <https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-fit-content>
|
||||||
|
#[css(function)]
|
||||||
FitContent(L),
|
FitContent(L),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,8 +348,7 @@ where
|
||||||
/// The initial argument of the `repeat` function.
|
/// The initial argument of the `repeat` function.
|
||||||
///
|
///
|
||||||
/// <https://drafts.csswg.org/css-grid/#typedef-track-repeat>
|
/// <https://drafts.csswg.org/css-grid/#typedef-track-repeat>
|
||||||
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
|
||||||
ToComputedValue, ToCss)]
|
|
||||||
pub enum RepeatCount<Integer> {
|
pub enum RepeatCount<Integer> {
|
||||||
/// A positive integer. This is allowed only for `<track-repeat>` and `<fixed-repeat>`
|
/// A positive integer. This is allowed only for `<track-repeat>` and `<fixed-repeat>`
|
||||||
Number(Integer),
|
Number(Integer),
|
||||||
|
@ -384,6 +385,7 @@ impl Parse for RepeatCount<specified::Integer> {
|
||||||
/// values in its computed form.
|
/// values in its computed form.
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
||||||
ToComputedValue)]
|
ToComputedValue)]
|
||||||
|
#[css(function = "repeat")]
|
||||||
pub struct TrackRepeat<L, I> {
|
pub struct TrackRepeat<L, I> {
|
||||||
/// The number of times for the value to be repeated (could also be `auto-fit` or `auto-fill`)
|
/// The number of times for the value to be repeated (could also be `auto-fit` or `auto-fill`)
|
||||||
pub count: RepeatCount<I>,
|
pub count: RepeatCount<I>,
|
||||||
|
@ -481,8 +483,7 @@ pub enum TrackListValue<LengthOrPercentage, Integer> {
|
||||||
/// The type of a `<track-list>` as determined during parsing.
|
/// The type of a `<track-list>` as determined during parsing.
|
||||||
///
|
///
|
||||||
/// <https://drafts.csswg.org/css-grid/#typedef-track-list>
|
/// <https://drafts.csswg.org/css-grid/#typedef-track-list>
|
||||||
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
|
||||||
ToComputedValue)]
|
|
||||||
pub enum TrackListType {
|
pub enum TrackListType {
|
||||||
/// [`<auto-track-list>`](https://drafts.csswg.org/css-grid/#typedef-auto-track-list)
|
/// [`<auto-track-list>`](https://drafts.csswg.org/css-grid/#typedef-auto-track-list)
|
||||||
///
|
///
|
||||||
|
@ -510,6 +511,7 @@ pub struct TrackList<LengthOrPercentage, Integer> {
|
||||||
///
|
///
|
||||||
/// In order to avoid parsing the same value multiple times, this does a single traversal
|
/// In order to avoid parsing the same value multiple times, this does a single traversal
|
||||||
/// and arrives at the type of value it has parsed (or bails out gracefully with an error).
|
/// and arrives at the type of value it has parsed (or bails out gracefully with an error).
|
||||||
|
#[css(skip)]
|
||||||
pub list_type: TrackListType,
|
pub list_type: TrackListType,
|
||||||
/// A vector of `<track-size> | <track-repeat>` values.
|
/// A vector of `<track-size> | <track-repeat>` values.
|
||||||
pub values: Vec<TrackListValue<LengthOrPercentage, Integer>>,
|
pub values: Vec<TrackListValue<LengthOrPercentage, Integer>>,
|
||||||
|
|
|
@ -26,6 +26,7 @@ pub enum Image<Gradient, MozImageRect, ImageUrl> {
|
||||||
/// A `-moz-image-rect` image. Also fairly large and rare.
|
/// A `-moz-image-rect` image. Also fairly large and rare.
|
||||||
Rect(Box<MozImageRect>),
|
Rect(Box<MozImageRect>),
|
||||||
/// A `-moz-element(# <element-id>)`
|
/// A `-moz-element(# <element-id>)`
|
||||||
|
#[css(function = "-moz-element")]
|
||||||
Element(Atom),
|
Element(Atom),
|
||||||
/// A paint worklet image.
|
/// A paint worklet image.
|
||||||
/// <https://drafts.css-houdini.org/css-paint-api/>
|
/// <https://drafts.css-houdini.org/css-paint-api/>
|
||||||
|
|
|
@ -80,7 +80,9 @@ pub struct TransformOrigin<H, V, Depth> {
|
||||||
/// A generic timing function.
|
/// A generic timing function.
|
||||||
///
|
///
|
||||||
/// <https://drafts.csswg.org/css-timing-1/#single-timing-function-production>
|
/// <https://drafts.csswg.org/css-timing-1/#single-timing-function-production>
|
||||||
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)]
|
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
||||||
|
ToCss)]
|
||||||
|
#[value_info(ty = "TIMING_FUNCTION")]
|
||||||
pub enum TimingFunction<Integer, Number> {
|
pub enum TimingFunction<Integer, Number> {
|
||||||
/// `linear | ease | ease-in | ease-out | ease-in-out`
|
/// `linear | ease | ease-in | ease-out | ease-in-out`
|
||||||
Keyword(TimingKeyword),
|
Keyword(TimingKeyword),
|
||||||
|
@ -95,6 +97,7 @@ pub enum TimingFunction<Integer, Number> {
|
||||||
},
|
},
|
||||||
/// `step-start | step-end | steps(<integer>, [ start | end ]?)`
|
/// `step-start | step-end | steps(<integer>, [ start | end ]?)`
|
||||||
#[css(comma, function)]
|
#[css(comma, function)]
|
||||||
|
#[value_info(other_values = "step-start,step-end")]
|
||||||
Steps(Integer, #[css(skip_if = "is_end")] StepPosition),
|
Steps(Integer, #[css(skip_if = "is_end")] StepPosition),
|
||||||
/// `frames(<integer>)`
|
/// `frames(<integer>)`
|
||||||
#[css(comma, function)]
|
#[css(comma, function)]
|
||||||
|
@ -103,7 +106,8 @@ pub enum TimingFunction<Integer, Number> {
|
||||||
|
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
|
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq,
|
||||||
|
SpecifiedValueInfo, ToComputedValue, ToCss)]
|
||||||
pub enum TimingKeyword {
|
pub enum TimingKeyword {
|
||||||
Linear,
|
Linear,
|
||||||
Ease,
|
Ease,
|
||||||
|
|
|
@ -9,7 +9,7 @@ use cssparser::Parser;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
use selectors::parser::SelectorParseErrorKind;
|
use selectors::parser::SelectorParseErrorKind;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use style_traits::{CssWriter, ParseError, SpecifiedValueInfo, StyleParseErrorKind, ToCss};
|
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
||||||
use values::{CustomIdent, KeyframesName};
|
use values::{CustomIdent, KeyframesName};
|
||||||
use values::generics::box_::AnimationIterationCount as GenericAnimationIterationCount;
|
use values::generics::box_::AnimationIterationCount as GenericAnimationIterationCount;
|
||||||
use values::generics::box_::Perspective as GenericPerspective;
|
use values::generics::box_::Perspective as GenericPerspective;
|
||||||
|
@ -298,6 +298,7 @@ impl AnimationIterationCount {
|
||||||
/// A value for the `animation-name` property.
|
/// A value for the `animation-name` property.
|
||||||
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
||||||
ToComputedValue)]
|
ToComputedValue)]
|
||||||
|
#[value_info(other_values = "none")]
|
||||||
pub struct AnimationName(pub Option<KeyframesName>);
|
pub struct AnimationName(pub Option<KeyframesName>);
|
||||||
|
|
||||||
impl AnimationName {
|
impl AnimationName {
|
||||||
|
@ -420,8 +421,9 @@ impl Parse for WillChange {
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||||
#[derive(ToComputedValue)]
|
#[derive(SpecifiedValueInfo, ToComputedValue)]
|
||||||
/// These constants match Gecko's `NS_STYLE_TOUCH_ACTION_*` constants.
|
/// These constants match Gecko's `NS_STYLE_TOUCH_ACTION_*` constants.
|
||||||
|
#[value_info(other_values = "auto,none,manipulation,pan-x,pan-y")]
|
||||||
pub struct TouchAction: u8 {
|
pub struct TouchAction: u8 {
|
||||||
/// `none` variant
|
/// `none` variant
|
||||||
const TOUCH_ACTION_NONE = 1 << 0;
|
const TOUCH_ACTION_NONE = 1 << 0;
|
||||||
|
@ -493,8 +495,6 @@ impl Parse for TouchAction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpecifiedValueInfo for TouchAction {}
|
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
impl_bitflags_conversions!(TouchAction);
|
impl_bitflags_conversions!(TouchAction);
|
||||||
|
|
||||||
|
@ -522,7 +522,8 @@ pub fn assert_touch_action_matches() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
#[derive(MallocSizeOf, ToComputedValue)]
|
#[derive(MallocSizeOf, ToComputedValue, SpecifiedValueInfo)]
|
||||||
|
#[value_info(other_values = "none,strict,layout,style,paint")]
|
||||||
/// Constants for contain: https://drafts.csswg.org/css-contain/#contain-property
|
/// Constants for contain: https://drafts.csswg.org/css-contain/#contain-property
|
||||||
pub struct Contain: u8 {
|
pub struct Contain: u8 {
|
||||||
/// `layout` variant, turns on layout containment
|
/// `layout` variant, turns on layout containment
|
||||||
|
@ -605,8 +606,6 @@ impl Parse for Contain {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpecifiedValueInfo for Contain {}
|
|
||||||
|
|
||||||
/// A specified value for the `perspective` property.
|
/// A specified value for the `perspective` property.
|
||||||
pub type Perspective = GenericPerspective<NonNegativeLength>;
|
pub type Perspective = GenericPerspective<NonNegativeLength>;
|
||||||
|
|
||||||
|
|
|
@ -1945,9 +1945,11 @@ pub struct FontSynthesis {
|
||||||
/// If a `font-weight` is requested that the font family does not contain,
|
/// If a `font-weight` is requested that the font family does not contain,
|
||||||
/// the user agent may synthesize the requested weight from the weights
|
/// the user agent may synthesize the requested weight from the weights
|
||||||
/// that do exist in the font family.
|
/// that do exist in the font family.
|
||||||
|
#[value_info(represents_keyword)]
|
||||||
pub weight: bool,
|
pub weight: bool,
|
||||||
/// If a font-style is requested that the font family does not contain,
|
/// 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.
|
/// the user agent may synthesize the requested style from the normal face in the font family.
|
||||||
|
#[value_info(represents_keyword)]
|
||||||
pub style: bool,
|
pub style: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ pub struct ImageOrientation {
|
||||||
pub angle: Option<Angle>,
|
pub angle: Option<Angle>,
|
||||||
|
|
||||||
/// Whether or not "flip" was specified
|
/// Whether or not "flip" was specified
|
||||||
|
#[value_info(other_values = "flip,from-image")]
|
||||||
pub flipped: bool,
|
pub flipped: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,9 +78,10 @@ impl Parse for ListStyleType {
|
||||||
///
|
///
|
||||||
/// FIXME(emilio): It's a shame that this allocates all the time it's computed,
|
/// FIXME(emilio): It's a shame that this allocates all the time it's computed,
|
||||||
/// probably should just be refcounted.
|
/// probably should just be refcounted.
|
||||||
|
/// FIXME This can probably derive ToCss.
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
||||||
ToComputedValue)]
|
ToComputedValue)]
|
||||||
pub struct Quotes(pub Box<[(Box<str>, Box<str>)]>);
|
pub struct Quotes(#[css(if_empty = "none")] pub Box<[(Box<str>, Box<str>)]>);
|
||||||
|
|
||||||
impl ToCss for Quotes {
|
impl ToCss for Quotes {
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||||
|
|
|
@ -570,6 +570,7 @@ pub type GridTemplateComponent = GenericGridTemplateComponent<LengthOrPercentage
|
||||||
|
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo)]
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo)]
|
||||||
/// rect(<top>, <left>, <bottom>, <right>) used by clip and image-region
|
/// rect(<top>, <left>, <bottom>, <right>) used by clip and image-region
|
||||||
|
#[css(function = "rect")]
|
||||||
pub struct ClipRect {
|
pub struct ClipRect {
|
||||||
/// <top> (<length> | <auto>)
|
/// <top> (<length> | <auto>)
|
||||||
pub top: Option<Length>,
|
pub top: Option<Length>,
|
||||||
|
@ -757,7 +758,9 @@ impl AllowQuirks {
|
||||||
/// An attr(...) rule
|
/// An attr(...) rule
|
||||||
///
|
///
|
||||||
/// `[namespace? `|`]? ident`
|
/// `[namespace? `|`]? ident`
|
||||||
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue)]
|
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
||||||
|
ToComputedValue)]
|
||||||
|
#[css(function)]
|
||||||
pub struct Attr {
|
pub struct Attr {
|
||||||
/// Optional namespace prefix and URL.
|
/// Optional namespace prefix and URL.
|
||||||
pub namespace: Option<(Prefix, Namespace)>,
|
pub namespace: Option<(Prefix, Namespace)>,
|
||||||
|
@ -852,5 +855,3 @@ impl ToCss for Attr {
|
||||||
dest.write_str(")")
|
dest.write_str(")")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpecifiedValueInfo for Attr {}
|
|
||||||
|
|
|
@ -431,6 +431,7 @@ pub struct GridAutoFlow {
|
||||||
/// Specifiy how auto-placement algorithm fills each `row` or `column` in turn
|
/// Specifiy how auto-placement algorithm fills each `row` or `column` in turn
|
||||||
pub autoflow: AutoFlow,
|
pub autoflow: AutoFlow,
|
||||||
/// Specify use `dense` packing algorithm or not
|
/// Specify use `dense` packing algorithm or not
|
||||||
|
#[value_info(represents_keyword)]
|
||||||
pub dense: bool,
|
pub dense: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
use selectors::parser::SelectorParseErrorKind;
|
use selectors::parser::SelectorParseErrorKind;
|
||||||
use style_traits::{CssType, ParseError, SpecifiedValueInfo, StyleParseErrorKind};
|
use style_traits::{ParseError, StyleParseErrorKind};
|
||||||
use values::computed::{Context, LengthOrPercentage as ComputedLengthOrPercentage};
|
use values::computed::{Context, LengthOrPercentage as ComputedLengthOrPercentage};
|
||||||
use values::computed::{Percentage as ComputedPercentage, ToComputedValue};
|
use values::computed::{Percentage as ComputedPercentage, ToComputedValue};
|
||||||
use values::computed::transform::TimingFunction as ComputedTimingFunction;
|
use values::computed::transform::TimingFunction as ComputedTimingFunction;
|
||||||
|
@ -246,10 +246,6 @@ pub enum OriginComponent<S> {
|
||||||
/// A specified timing function.
|
/// A specified timing function.
|
||||||
pub type TimingFunction = generic::TimingFunction<Integer, Number>;
|
pub type TimingFunction = generic::TimingFunction<Integer, Number>;
|
||||||
|
|
||||||
impl SpecifiedValueInfo for TimingFunction {
|
|
||||||
const SUPPORTED_TYPES: u8 = CssType::TIMING_FUNCTION;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Parse for TransformOrigin {
|
impl Parse for TransformOrigin {
|
||||||
fn parse<'i, 't>(
|
fn parse<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
|
|
|
@ -64,7 +64,7 @@ pub fn derive_to_css(stream: TokenStream) -> TokenStream {
|
||||||
to_css::derive(input).into()
|
to_css::derive(input).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_derive(SpecifiedValueInfo, attributes(css))]
|
#[proc_macro_derive(SpecifiedValueInfo, attributes(css, value_info))]
|
||||||
pub fn derive_specified_value_info(stream: TokenStream) -> TokenStream {
|
pub fn derive_specified_value_info(stream: TokenStream) -> TokenStream {
|
||||||
let input = syn::parse(stream).unwrap();
|
let input = syn::parse(stream).unwrap();
|
||||||
specified_value_info::derive(input).into()
|
specified_value_info::derive(input).into()
|
||||||
|
|
|
@ -4,17 +4,17 @@
|
||||||
|
|
||||||
use cg;
|
use cg;
|
||||||
use quote::Tokens;
|
use quote::Tokens;
|
||||||
use syn::{Data, DeriveInput, Fields, Type};
|
use syn::{Data, DeriveInput, Fields, Ident,Type};
|
||||||
use to_css::{CssFieldAttrs, CssInputAttrs, CssVariantAttrs};
|
use to_css::{CssFieldAttrs, CssInputAttrs, CssVariantAttrs};
|
||||||
|
|
||||||
pub fn derive(mut input: DeriveInput) -> Tokens {
|
pub fn derive(mut input: DeriveInput) -> Tokens {
|
||||||
let attrs = cg::parse_input_attrs::<CssInputAttrs>(&input);
|
let css_attrs = cg::parse_input_attrs::<CssInputAttrs>(&input);
|
||||||
let mut types = vec![];
|
let mut types = vec![];
|
||||||
let mut values = vec![];
|
let mut values = vec![];
|
||||||
|
|
||||||
let input_ident = input.ident;
|
let input_ident = input.ident;
|
||||||
let input_name = || cg::to_css_identifier(input_ident.as_ref());
|
let input_name = || cg::to_css_identifier(input_ident.as_ref());
|
||||||
if let Some(function) = attrs.function {
|
if let Some(function) = css_attrs.function {
|
||||||
values.push(function.explicit().unwrap_or_else(input_name));
|
values.push(function.explicit().unwrap_or_else(input_name));
|
||||||
// If the whole value is wrapped in a function, value types of
|
// If the whole value is wrapped in a function, value types of
|
||||||
// its fields should not be propagated.
|
// its fields should not be propagated.
|
||||||
|
@ -31,21 +31,32 @@ pub fn derive(mut input: DeriveInput) -> Tokens {
|
||||||
match input.data {
|
match input.data {
|
||||||
Data::Enum(ref e) => {
|
Data::Enum(ref e) => {
|
||||||
for v in e.variants.iter() {
|
for v in e.variants.iter() {
|
||||||
let attrs = cg::parse_variant_attrs::<CssVariantAttrs>(&v);
|
let css_attrs = cg::parse_variant_attrs::<CssVariantAttrs>(&v);
|
||||||
if attrs.skip {
|
let info_attrs = cg::parse_variant_attrs::<ValueInfoVariantAttrs>(&v);
|
||||||
|
if css_attrs.skip {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some(aliases) = attrs.aliases {
|
if let Some(aliases) = css_attrs.aliases {
|
||||||
for alias in aliases.split(",") {
|
for alias in aliases.split(",") {
|
||||||
values.push(alias.to_string());
|
values.push(alias.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(keyword) = attrs.keyword {
|
if let Some(other_values) = info_attrs.other_values {
|
||||||
|
for value in other_values.split(",") {
|
||||||
|
values.push(value.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let ident = &v.ident;
|
||||||
|
let variant_name = || cg::to_css_identifier(ident.as_ref());
|
||||||
|
if info_attrs.starts_with_keyword {
|
||||||
|
values.push(variant_name());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if let Some(keyword) = css_attrs.keyword {
|
||||||
values.push(keyword);
|
values.push(keyword);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let variant_name = || cg::to_css_identifier(v.ident.as_ref());
|
if let Some(function) = css_attrs.function {
|
||||||
if let Some(function) = attrs.function {
|
|
||||||
values.push(function.explicit().unwrap_or_else(variant_name));
|
values.push(function.explicit().unwrap_or_else(variant_name));
|
||||||
} else {
|
} else {
|
||||||
if !derive_struct_fields(&v.fields, &mut types, &mut values) {
|
if !derive_struct_fields(&v.fields, &mut types, &mut values) {
|
||||||
|
@ -63,6 +74,13 @@ pub fn derive(mut input: DeriveInput) -> Tokens {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let info_attrs = cg::parse_input_attrs::<ValueInfoInputAttrs>(&input);
|
||||||
|
if let Some(other_values) = info_attrs.other_values {
|
||||||
|
for value in other_values.split(",") {
|
||||||
|
values.push(value.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut types_value = quote!(0);
|
let mut types_value = quote!(0);
|
||||||
types_value.append_all(types.iter().map(|ty| quote! {
|
types_value.append_all(types.iter().map(|ty| quote! {
|
||||||
| <#ty as ::style_traits::SpecifiedValueInfo>::SUPPORTED_TYPES
|
| <#ty as ::style_traits::SpecifiedValueInfo>::SUPPORTED_TYPES
|
||||||
|
@ -73,6 +91,12 @@ pub fn derive(mut input: DeriveInput) -> Tokens {
|
||||||
<#ty as ::style_traits::SpecifiedValueInfo>::collect_completion_keywords(_f);
|
<#ty as ::style_traits::SpecifiedValueInfo>::collect_completion_keywords(_f);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
if let Some(ty) = info_attrs.ty {
|
||||||
|
types_value.append_all(quote! {
|
||||||
|
| ::style_traits::CssType::#ty
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let append_values = if values.is_empty() {
|
let append_values = if values.is_empty() {
|
||||||
quote!()
|
quote!()
|
||||||
} else {
|
} else {
|
||||||
|
@ -110,11 +134,23 @@ fn derive_struct_fields<'a>(
|
||||||
Fields::Unnamed(ref fields) => fields.unnamed.iter(),
|
Fields::Unnamed(ref fields) => fields.unnamed.iter(),
|
||||||
};
|
};
|
||||||
types.extend(fields.filter_map(|field| {
|
types.extend(fields.filter_map(|field| {
|
||||||
let attrs = cg::parse_field_attrs::<CssFieldAttrs>(field);
|
let info_attrs = cg::parse_field_attrs::<ValueInfoFieldAttrs>(field);
|
||||||
if let Some(if_empty) = attrs.if_empty {
|
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 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);
|
values.push(if_empty);
|
||||||
}
|
}
|
||||||
if !attrs.skip {
|
if !css_attrs.skip {
|
||||||
Some(&field.ty)
|
Some(&field.ty)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -122,3 +158,24 @@ fn derive_struct_fields<'a>(
|
||||||
}));
|
}));
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[darling(attributes(value_info), default)]
|
||||||
|
#[derive(Default, FromDeriveInput)]
|
||||||
|
struct ValueInfoInputAttrs {
|
||||||
|
ty: Option<Ident>,
|
||||||
|
other_values: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[darling(attributes(value_info), default)]
|
||||||
|
#[derive(Default, FromVariant)]
|
||||||
|
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>,
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,36 @@ pub mod CssType {
|
||||||
pub type KeywordsCollectFn<'a> = &'a mut FnMut(&[&'static str]);
|
pub type KeywordsCollectFn<'a> = &'a mut FnMut(&[&'static str]);
|
||||||
|
|
||||||
/// Information of values of a given specified value type.
|
/// Information of values of a given specified value type.
|
||||||
|
///
|
||||||
|
/// This trait is derivable with `#[derive(SpecifiedValueInfo)]`.
|
||||||
|
///
|
||||||
|
/// The algorithm traverses the type definition. For `SUPPORTED_TYPES`,
|
||||||
|
/// it puts an or'ed value of `SUPPORTED_TYPES` of all types it finds.
|
||||||
|
/// For `collect_completion_keywords`, it recursively invokes this
|
||||||
|
/// method on types found, and lists all keyword values and function
|
||||||
|
/// names following the same rule as `ToCss` in that method.
|
||||||
|
///
|
||||||
|
/// Some attributes of `ToCss` can affect the behavior, specifically:
|
||||||
|
/// * If `#[css(function)]` is found, the content inside the annotated
|
||||||
|
/// variant (or the whole type) isn't traversed, only the function
|
||||||
|
/// name is listed in `collect_completion_keywords`.
|
||||||
|
/// * If `#[css(skip)]` is found, the content inside the variant or
|
||||||
|
/// field is ignored.
|
||||||
|
/// * Values listed in `#[css(if_empty)]`, `#[css(aliases)]`, and
|
||||||
|
/// `#[css(keyword)]` are added into `collect_completion_keywords`.
|
||||||
|
///
|
||||||
|
/// In addition to `css` attributes, it also has `value_info` helper
|
||||||
|
/// attributes, including:
|
||||||
|
/// * `#[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 {
|
pub trait SpecifiedValueInfo {
|
||||||
/// Supported CssTypes by the given value type.
|
/// Supported CssTypes by the given value type.
|
||||||
///
|
///
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue