mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
style: Introduce css(parse_condition).
This will allow us to add a pref for this, and to parse it only on chrome easily. Bug: 1288572 Reviewed-by: xidorn MozReview-Commit-ID: L1rsyc2A2hu
This commit is contained in:
parent
ce5a85d6a1
commit
1da798e65b
3 changed files with 50 additions and 8 deletions
|
@ -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
|
/// A trait to abstract parsing of a specified value given a `ParserContext` and
|
||||||
/// CSS input.
|
/// 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 {
|
pub trait Parse: Sized {
|
||||||
/// Parse a value of this type.
|
/// Parse a value of this type.
|
||||||
///
|
///
|
||||||
|
|
|
@ -12,6 +12,7 @@ pub fn derive(input: DeriveInput) -> Tokens {
|
||||||
let name = &input.ident;
|
let name = &input.ident;
|
||||||
let s = synstructure::Structure::new(&input);
|
let s = synstructure::Structure::new(&input);
|
||||||
|
|
||||||
|
let mut saw_condition = false;
|
||||||
let match_body = s.variants().iter().fold(quote!(), |match_body, variant| {
|
let match_body = s.variants().iter().fold(quote!(), |match_body, variant| {
|
||||||
let bindings = variant.bindings();
|
let bindings = variant.bindings();
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -29,11 +30,16 @@ pub fn derive(input: DeriveInput) -> Tokens {
|
||||||
);
|
);
|
||||||
let ident = &variant.ast().ident;
|
let ident = &variant.ast().ident;
|
||||||
|
|
||||||
let mut body = quote! {
|
saw_condition |= variant_attrs.parse_condition.is_some();
|
||||||
#match_body
|
let condition = match variant_attrs.parse_condition {
|
||||||
#identifier => Ok(#name::#ident),
|
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 variant_attrs.aliases {
|
||||||
Some(aliases) => aliases,
|
Some(aliases) => aliases,
|
||||||
|
@ -43,25 +49,51 @@ pub fn derive(input: DeriveInput) -> Tokens {
|
||||||
for alias in aliases.split(",") {
|
for alias in aliases.split(",") {
|
||||||
body = quote! {
|
body = quote! {
|
||||||
#body
|
#body
|
||||||
#alias => Ok(#name::#ident),
|
#alias #condition => Ok(#name::#ident),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
body
|
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! {
|
let parse_trait_impl = quote! {
|
||||||
impl ::parser::Parse for #name {
|
impl ::parser::Parse for #name {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn parse<'i, 't>(
|
fn parse<'i, 't>(
|
||||||
_: &::parser::ParserContext,
|
#context_ident: &::parser::ParserContext,
|
||||||
input: &mut ::cssparser::Parser<'i, 't>,
|
input: &mut ::cssparser::Parser<'i, 't>,
|
||||||
) -> Result<Self, ::style_traits::ParseError<'i>> {
|
) -> 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
|
// TODO(emilio): It'd be nice to get rid of these, but that makes the
|
||||||
// conversion harder...
|
// conversion harder...
|
||||||
let methods_impl = quote! {
|
let methods_impl = quote! {
|
||||||
|
|
|
@ -235,6 +235,7 @@ pub struct CssVariantAttrs {
|
||||||
pub dimension: bool,
|
pub dimension: bool,
|
||||||
pub keyword: Option<String>,
|
pub keyword: Option<String>,
|
||||||
pub aliases: Option<String>,
|
pub aliases: Option<String>,
|
||||||
|
pub parse_condition: Option<Path>,
|
||||||
pub skip: bool,
|
pub skip: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue