Bug 1466609: #[parse(..)]. r?xidorn
I need to admit I'm ambivalent about this one :).
MozReview-Commit-ID: F1jlfnQKXwo
--- a/servo/components/style/parser.rs
+++ b/servo/components/style/parser.rs
@@ -152,21 +152,21 @@ impl<'a> ParserContext<'a> {
/// A trait to abstract parsing of a specified value given a `ParserContext` and
/// CSS input.
///
/// This can be derived on keywords with `#[derive(Parse)]`.
///
/// The derive code understands the following attributes on each of the variants:
///
-/// * `#[css(aliases = "foo,bar")]` can be used to alias a value with another
+/// * `#[parse(aliases = "foo,bar")]` can be used to alias a value with another
/// at parse-time.
///
-/// * `#[css(parse_condition = "function")]` can be used to make the parsing of
-/// the value conditional on `function`, which will be invoked with a
+/// * `#[parse(condition = "function")]` can be used to make the parsing of the
+/// value conditional on `function`, which will be invoked with a
/// `&ParserContext` reference.
pub trait Parse: Sized {
/// Parse a value of this type.
///
/// Returns an error on failure.
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
--- a/servo/components/style/properties/helpers.mako.rs
+++ b/servo/components/style/properties/helpers.mako.rs
@@ -589,17 +589,17 @@
% if include_aliases:
<%
aliases = []
for alias, v in keyword.aliases_for(product).iteritems():
if variant == v:
aliases.append(alias)
%>
% if aliases:
- #[css(aliases = "${','.join(aliases)}")]
+ #[parse(aliases = "${','.join(aliases)}")]
% endif
% endif
${to_camel_case(variant)},
% endfor
</%def>
% if extra_specified:
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq,
--- a/servo/components/style/values/specified/box.rs
+++ b/servo/components/style/values/specified/box.rs
@@ -48,19 +48,19 @@ pub enum Display {
TableFooterGroup,
TableRow,
TableColumnGroup,
TableColumn,
TableCell,
TableCaption,
ListItem,
None,
- #[css(aliases = "-webkit-flex")]
+ #[parse(aliases = "-webkit-flex")]
Flex,
- #[css(aliases = "-webkit-inline-flex")]
+ #[parse(aliases = "-webkit-inline-flex")]
InlineFlex,
#[cfg(feature = "gecko")]
Grid,
#[cfg(feature = "gecko")]
InlineGrid,
#[cfg(feature = "gecko")]
Ruby,
#[cfg(feature = "gecko")]
@@ -79,41 +79,41 @@ pub enum Display {
WebkitBox,
#[cfg(feature = "gecko")]
WebkitInlineBox,
#[cfg(feature = "gecko")]
MozBox,
#[cfg(feature = "gecko")]
MozInlineBox,
#[cfg(feature = "gecko")]
- #[css(parse_condition = "moz_display_values_enabled")]
+ #[parse(condition = "moz_display_values_enabled")]
MozGrid,
#[cfg(feature = "gecko")]
- #[css(parse_condition = "moz_display_values_enabled")]
+ #[parse(condition = "moz_display_values_enabled")]
MozInlineGrid,
#[cfg(feature = "gecko")]
- #[css(parse_condition = "moz_display_values_enabled")]
+ #[parse(condition = "moz_display_values_enabled")]
MozGridGroup,
#[cfg(feature = "gecko")]
- #[css(parse_condition = "moz_display_values_enabled")]
+ #[parse(condition = "moz_display_values_enabled")]
MozGridLine,
#[cfg(feature = "gecko")]
- #[css(parse_condition = "moz_display_values_enabled")]
+ #[parse(condition = "moz_display_values_enabled")]
MozStack,
#[cfg(feature = "gecko")]
- #[css(parse_condition = "moz_display_values_enabled")]
+ #[parse(condition = "moz_display_values_enabled")]
MozInlineStack,
#[cfg(feature = "gecko")]
- #[css(parse_condition = "moz_display_values_enabled")]
+ #[parse(condition = "moz_display_values_enabled")]
MozDeck,
#[cfg(feature = "gecko")]
- #[css(parse_condition = "moz_display_values_enabled")]
+ #[parse(condition = "moz_display_values_enabled")]
MozPopup,
#[cfg(feature = "gecko")]
- #[css(parse_condition = "moz_display_values_enabled")]
+ #[parse(condition = "moz_display_values_enabled")]
MozGroupbox,
}
impl Display {
/// The initial display value.
#[inline]
pub fn inline() -> Self {
Display::Inline
--- a/servo/components/style_derive/lib.rs
+++ b/servo/components/style_derive/lib.rs
@@ -35,17 +35,17 @@ pub fn derive_compute_squared_distance(s
}
#[proc_macro_derive(ToAnimatedValue)]
pub fn derive_to_animated_value(stream: TokenStream) -> TokenStream {
let input = syn::parse(stream).unwrap();
to_animated_value::derive(input).into()
}
-#[proc_macro_derive(Parse, attributes(css))]
+#[proc_macro_derive(Parse, attributes(css, parse))]
pub fn derive_parse(stream: TokenStream) -> TokenStream {
let input = syn::parse(stream).unwrap();
parse::derive(input).into()
}
#[proc_macro_derive(ToAnimatedZero, attributes(animation, zero))]
pub fn derive_to_animated_zero(stream: TokenStream) -> TokenStream {
let input = syn::parse(stream).unwrap();
@@ -59,13 +59,13 @@ pub fn derive_to_computed_value(stream:
}
#[proc_macro_derive(ToCss, attributes(css))]
pub fn derive_to_css(stream: TokenStream) -> TokenStream {
let input = syn::parse(stream).unwrap();
to_css::derive(input).into()
}
-#[proc_macro_derive(SpecifiedValueInfo, attributes(css, value_info))]
+#[proc_macro_derive(SpecifiedValueInfo, attributes(css, parse, value_info))]
pub fn derive_specified_value_info(stream: TokenStream) -> TokenStream {
let input = syn::parse(stream).unwrap();
specified_value_info::derive(input).into()
}
--- a/servo/components/style_derive/parse.rs
+++ b/servo/components/style_derive/parse.rs
@@ -1,52 +1,62 @@
/* 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/. */
use cg;
use quote::Tokens;
-use syn::DeriveInput;
+use syn::{DeriveInput, Path};
use synstructure;
use to_css::CssVariantAttrs;
+#[darling(attributes(parse), default)]
+#[derive(Default, FromVariant)]
+pub struct ParseVariantAttrs {
+ pub aliases: Option<String>,
+ pub condition: Option<Path>,
+}
+
pub fn derive(input: DeriveInput) -> Tokens {
let name = &input.ident;
let s = synstructure::Structure::new(&input);
let mut saw_condition = false;
let match_body = s.variants().iter().fold(quote!(), |match_body, variant| {
let bindings = variant.bindings();
assert!(
bindings.is_empty(),
"Parse is only supported for single-variant enums for now"
);
- let variant_attrs = cg::parse_variant_attrs_from_ast::<CssVariantAttrs>(&variant.ast());
- if variant_attrs.skip {
+ let css_variant_attrs =
+ cg::parse_variant_attrs_from_ast::<CssVariantAttrs>(&variant.ast());
+ let parse_attrs =
+ cg::parse_variant_attrs_from_ast::<ParseVariantAttrs>(&variant.ast());
+ if css_variant_attrs.skip {
return match_body;
}
let identifier = cg::to_css_identifier(
- &variant_attrs.keyword.unwrap_or(variant.ast().ident.as_ref().into()),
+ &css_variant_attrs.keyword.unwrap_or(variant.ast().ident.as_ref().into()),
);
let ident = &variant.ast().ident;
- saw_condition |= variant_attrs.parse_condition.is_some();
- let condition = match variant_attrs.parse_condition {
+ saw_condition |= parse_attrs.condition.is_some();
+ let condition = match parse_attrs.condition {
Some(ref p) => quote! { if #p(context) },
None => quote! { },
};
let mut body = quote! {
#match_body
#identifier #condition => Ok(#name::#ident),
};
- let aliases = match variant_attrs.aliases {
+ let aliases = match parse_attrs.aliases {
Some(aliases) => aliases,
None => return body,
};
for alias in aliases.split(",") {
body = quote! {
#body
#alias #condition => Ok(#name::#ident),
--- a/servo/components/style_derive/specified_value_info.rs
+++ b/servo/components/style_derive/specified_value_info.rs
@@ -1,16 +1,17 @@
/* 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/. */
use cg;
use quote::Tokens;
use syn::{Data, DeriveInput, Fields, Ident, Type};
use to_css::{CssFieldAttrs, CssInputAttrs, CssVariantAttrs};
+use parse::ParseVariantAttrs;
pub fn derive(mut input: DeriveInput) -> Tokens {
let css_attrs = cg::parse_input_attrs::<CssInputAttrs>(&input);
let mut types = vec![];
let mut values = vec![];
let input_ident = input.ident;
let input_name = || cg::to_css_identifier(input_ident.as_ref());
@@ -28,20 +29,21 @@ pub fn derive(mut input: DeriveInput) ->
}
input.generics.where_clause = where_clause;
match input.data {
Data::Enum(ref e) => {
for v in e.variants.iter() {
let css_attrs = cg::parse_variant_attrs::<CssVariantAttrs>(&v);
let info_attrs = cg::parse_variant_attrs::<ValueInfoVariantAttrs>(&v);
+ let parse_attrs = cg::parse_variant_attrs::<ParseVariantAttrs>(&v);
if css_attrs.skip {
continue;
}
- if let Some(aliases) = css_attrs.aliases {
+ if let Some(aliases) = parse_attrs.aliases {
for alias in aliases.split(",") {
values.push(alias.to_string());
}
}
if let Some(other_values) = info_attrs.other_values {
for value in other_values.split(",") {
values.push(value.to_string());
}
--- a/servo/components/style_derive/to_css.rs
+++ b/servo/components/style_derive/to_css.rs
@@ -229,18 +229,16 @@ pub struct CssInputAttrs {
#[darling(attributes(css), default)]
#[derive(Default, FromVariant)]
pub struct CssVariantAttrs {
pub function: Option<Override<String>>,
pub comma: bool,
pub dimension: bool,
pub keyword: Option<String>,
- pub aliases: Option<String>,
- pub parse_condition: Option<Path>,
pub skip: bool,
}
#[darling(attributes(css), default)]
#[derive(Default, FromField)]
pub struct CssFieldAttrs {
pub if_empty: Option<String>,
pub field_bound: bool,
--- a/servo/components/style_traits/specified_value_info.rs
+++ b/servo/components/style_traits/specified_value_info.rs
@@ -38,17 +38,17 @@ pub type KeywordsCollectFn<'a> = &'a mut
/// 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
+/// * Values listed in `#[css(if_empty)]`, `#[parse(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