aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/style/parser.rs13
-rw-r--r--components/style_derive/parse.rs42
-rw-r--r--components/style_derive/to_css.rs1
3 files changed, 49 insertions, 7 deletions
diff --git a/components/style/parser.rs b/components/style/parser.rs
index 26f4aeea071..1b7c65e2559 100644
--- a/components/style/parser.rs
+++ b/components/style/parser.rs
@@ -150,10 +150,19 @@ impl<'a> ParserContext<'a> {
}
}
-// XXXManishearth Replace all specified value parse impls with impls of this
-// trait. This will make it easy to write more generic values in the future.
/// 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
+/// 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
+/// `&ParserContext` reference.
pub trait Parse: Sized {
/// Parse a value of this type.
///
diff --git a/components/style_derive/parse.rs b/components/style_derive/parse.rs
index 7727d6b89bb..8b9044fb495 100644
--- a/components/style_derive/parse.rs
+++ b/components/style_derive/parse.rs
@@ -12,6 +12,7 @@ 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!(
@@ -29,12 +30,17 @@ pub fn derive(input: DeriveInput) -> Tokens {
);
let ident = &variant.ast().ident;
+ saw_condition |= variant_attrs.parse_condition.is_some();
+ let condition = match variant_attrs.parse_condition {
+ Some(ref p) => quote! { if #p(context) },
+ None => quote! { },
+ };
+
let mut body = quote! {
#match_body
- #identifier => Ok(#name::#ident),
+ #identifier #condition => Ok(#name::#ident),
};
-
let aliases = match variant_attrs.aliases {
Some(aliases) => aliases,
None => return body,
@@ -43,25 +49,51 @@ pub fn derive(input: DeriveInput) -> Tokens {
for alias in aliases.split(",") {
body = quote! {
#body
- #alias => Ok(#name::#ident),
+ #alias #condition => Ok(#name::#ident),
};
}
body
});
+ let context_ident = if saw_condition {
+ quote! { context }
+ } else {
+ quote! { _ }
+ };
+
+ let parse_body = if saw_condition {
+ quote! {
+ let location = input.current_source_location();
+ let ident = input.expect_ident()?;
+ match_ignore_ascii_case! { &ident,
+ #match_body
+ _ => Err(location.new_unexpected_token_error(
+ ::cssparser::Token::Ident(ident.clone())
+ ))
+ }
+ }
+ } else {
+ quote! { Self::parse(input) }
+ };
+
+
let parse_trait_impl = quote! {
impl ::parser::Parse for #name {
#[inline]
fn parse<'i, 't>(
- _: &::parser::ParserContext,
+ #context_ident: &::parser::ParserContext,
input: &mut ::cssparser::Parser<'i, 't>,
) -> Result<Self, ::style_traits::ParseError<'i>> {
- Self::parse(input)
+ #parse_body
}
}
};
+ if saw_condition {
+ return parse_trait_impl;
+ }
+
// TODO(emilio): It'd be nice to get rid of these, but that makes the
// conversion harder...
let methods_impl = quote! {
diff --git a/components/style_derive/to_css.rs b/components/style_derive/to_css.rs
index 0caef8b01a7..4853f41ee53 100644
--- a/components/style_derive/to_css.rs
+++ b/components/style_derive/to_css.rs
@@ -235,6 +235,7 @@ pub struct CssVariantAttrs {
pub dimension: bool,
pub keyword: Option<String>,
pub aliases: Option<String>,
+ pub parse_condition: Option<Path>,
pub skip: bool,
}