stylo: Add parsing support for functional non-ts pseudoclasses, add stub -moz-system-metric pseudo

MozReview-Commit-ID: KADDH6adZqR
This commit is contained in:
Manish Goregaokar 2017-03-15 16:44:07 -07:00 committed by Manish Goregaokar
parent 261a51a13a
commit b37f991cb8
3 changed files with 79 additions and 32 deletions

View file

@ -11,18 +11,18 @@
* *
* Expected usage is as follows: * Expected usage is as follows:
* ``` * ```
* fn use_pseudo_class() { * macro_rules! pseudo_class_macro{
* macro_rules! use_pseudo_class_list { * (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
* ( $( * string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => {
* ($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt), * // do stuff
* )* ) => {
* // Do stuff.
* }
* } * }
* apply_non_ts_list!(use_pseudo_class_list)
* } * }
* apply_non_ts_list!(pseudo_class_macro)
* ``` * ```
* *
* The string variables will be applied to pseudoclasses that are of the form
* of a function with a string argument.
*
* $gecko_type can be either "_" or an ident in Gecko's CSSPseudoClassType. * $gecko_type can be either "_" or an ident in Gecko's CSSPseudoClassType.
* $state can be either "_" or an expression of type ElementState. * $state can be either "_" or an expression of type ElementState.
* $flags can be either "_" or an expression of type NonTSPseudoClassFlag, * $flags can be either "_" or an expression of type NonTSPseudoClassFlag,
@ -32,22 +32,27 @@
macro_rules! apply_non_ts_list { macro_rules! apply_non_ts_list {
($apply_macro:ident) => { ($apply_macro:ident) => {
$apply_macro! { $apply_macro! {
("any-link", AnyLink, anyLink, _, _), bare: [
("link", Link, link, _, _), ("any-link", AnyLink, anyLink, _, _),
("visited", Visited, visited, _, _), ("link", Link, link, _, _),
("active", Active, active, IN_ACTIVE_STATE, _), ("visited", Visited, visited, _, _),
("focus", Focus, focus, IN_FOCUS_STATE, _), ("active", Active, active, IN_ACTIVE_STATE, _),
("fullscreen", Fullscreen, fullscreen, IN_FULLSCREEN_STATE, _), ("focus", Focus, focus, IN_FOCUS_STATE, _),
("hover", Hover, hover, IN_HOVER_STATE, _), ("fullscreen", Fullscreen, fullscreen, IN_FULLSCREEN_STATE, _),
("enabled", Enabled, enabled, IN_ENABLED_STATE, _), ("hover", Hover, hover, IN_HOVER_STATE, _),
("disabled", Disabled, disabled, IN_DISABLED_STATE, _), ("enabled", Enabled, enabled, IN_ENABLED_STATE, _),
("checked", Checked, checked, IN_CHECKED_STATE, _), ("disabled", Disabled, disabled, IN_DISABLED_STATE, _),
("indeterminate", Indeterminate, indeterminate, IN_INDETERMINATE_STATE, _), ("checked", Checked, checked, IN_CHECKED_STATE, _),
("read-write", ReadWrite, _, IN_READ_WRITE_STATE, _), ("indeterminate", Indeterminate, indeterminate, IN_INDETERMINATE_STATE, _),
("read-only", ReadOnly, _, IN_READ_WRITE_STATE, _), ("read-write", ReadWrite, _, IN_READ_WRITE_STATE, _),
("read-only", ReadOnly, _, IN_READ_WRITE_STATE, _),
("-moz-browser-frame", MozBrowserFrame, mozBrowserFrame, _, PSEUDO_CLASS_INTERNAL), ("-moz-browser-frame", MozBrowserFrame, mozBrowserFrame, _, PSEUDO_CLASS_INTERNAL),
("-moz-table-border-nonzero", MozTableBorderNonzero, mozTableBorderNonzero, _, PSEUDO_CLASS_INTERNAL), ("-moz-table-border-nonzero", MozTableBorderNonzero, mozTableBorderNonzero, _, PSEUDO_CLASS_INTERNAL),
],
string: [
("-moz-system-metric", MozSystemMetric, mozSystemMetric, _, PSEUDO_CLASS_INTERNAL),
]
} }
} }
} }

View file

@ -4,7 +4,7 @@
//! Gecko-specific bits for selector-parsing. //! Gecko-specific bits for selector-parsing.
use cssparser::ToCss; use cssparser::{Parser, ToCss};
use element_state::ElementState; use element_state::ElementState;
use gecko_bindings::structs::CSSPseudoClassType; use gecko_bindings::structs::CSSPseudoClassType;
use gecko_bindings::structs::nsIAtom; use gecko_bindings::structs::nsIAtom;
@ -139,7 +139,8 @@ bitflags! {
} }
macro_rules! pseudo_class_name { macro_rules! pseudo_class_name {
($(($css:expr, $name:ident, $_gecko_type:tt, $_state:tt, $_flags:tt),)*) => { (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => {
#[doc = "Our representation of a non tree-structural pseudo-class."] #[doc = "Our representation of a non tree-structural pseudo-class."]
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum NonTSPseudoClass { pub enum NonTSPseudoClass {
@ -147,6 +148,10 @@ macro_rules! pseudo_class_name {
#[doc = $css] #[doc = $css]
$name, $name,
)* )*
$(
#[doc = $s_css]
$s_name(Box<str>),
)*
} }
} }
} }
@ -155,13 +160,18 @@ apply_non_ts_list!(pseudo_class_name);
impl ToCss for NonTSPseudoClass { impl ToCss for NonTSPseudoClass {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
macro_rules! pseudo_class_serialize { macro_rules! pseudo_class_serialize {
($(($css:expr, $name:ident, $_gecko_type:tt, $_state:tt, $_flags:tt),)*) => { (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => {
match *self { match *self {
$(NonTSPseudoClass::$name => concat!(":", $css),)* $(NonTSPseudoClass::$name => concat!(":", $css),)*
$(NonTSPseudoClass::$s_name(ref s) => {
return dest.write_str(&format!(":{}({})", $s_css, s))
}, )*
} }
} }
} }
dest.write_str(apply_non_ts_list!(pseudo_class_serialize)) let ser = apply_non_ts_list!(pseudo_class_serialize);
dest.write_str(ser)
} }
} }
@ -174,9 +184,11 @@ impl NonTSPseudoClass {
($flags:expr) => ($flags.contains(PSEUDO_CLASS_INTERNAL)); ($flags:expr) => ($flags.contains(PSEUDO_CLASS_INTERNAL));
} }
macro_rules! pseudo_class_check_internal { macro_rules! pseudo_class_check_internal {
($(($_css:expr, $name:ident, $_gecko_type:tt, $_state:tt, $flags:tt),)*) => { (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => {
match *self { match *self {
$(NonTSPseudoClass::$name => check_flag!($flags),)* $(NonTSPseudoClass::$name => check_flag!($flags),)*
$(NonTSPseudoClass::$s_name(..) => check_flag!($s_flags),)*
} }
} }
} }
@ -190,9 +202,11 @@ impl NonTSPseudoClass {
($state:ident) => (::element_state::$state); ($state:ident) => (::element_state::$state);
} }
macro_rules! pseudo_class_state { macro_rules! pseudo_class_state {
($(($_css:expr, $name:ident, $_gecko_type:tt, $state:tt, $_flags:tt),)*) => { (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => {
match *self { match *self {
$(NonTSPseudoClass::$name => flag!($state),)* $(NonTSPseudoClass::$name => flag!($state),)*
$(NonTSPseudoClass::$s_name(..) => flag!($s_state),)*
} }
} }
} }
@ -207,9 +221,11 @@ impl NonTSPseudoClass {
(Some(::gecko_bindings::structs::CSSPseudoClassType::$gecko_type)); (Some(::gecko_bindings::structs::CSSPseudoClassType::$gecko_type));
} }
macro_rules! pseudo_class_geckotype { macro_rules! pseudo_class_geckotype {
($(($_css:expr, $name:ident, $gecko_type:tt, $_state:tt, $_flags:tt),)*) => { (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => {
match *self { match *self {
$(NonTSPseudoClass::$name => gecko_type!($gecko_type),)* $(NonTSPseudoClass::$name => gecko_type!($gecko_type),)*
$(NonTSPseudoClass::$s_name(..) => gecko_type!($s_gecko_type),)*
} }
} }
} }
@ -249,7 +265,8 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
fn parse_non_ts_pseudo_class(&self, name: Cow<str>) -> Result<NonTSPseudoClass, ()> { fn parse_non_ts_pseudo_class(&self, name: Cow<str>) -> Result<NonTSPseudoClass, ()> {
macro_rules! pseudo_class_parse { macro_rules! pseudo_class_parse {
($(($css:expr, $name:ident, $_gecko_type:tt, $_state:tt, $_flags:tt),)*) => { (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => {
match_ignore_ascii_case! { &name, match_ignore_ascii_case! { &name,
$($css => NonTSPseudoClass::$name,)* $($css => NonTSPseudoClass::$name,)*
_ => return Err(()) _ => return Err(())
@ -264,6 +281,30 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
} }
} }
fn parse_non_ts_functional_pseudo_class(&self,
name: Cow<str>,
parser: &mut Parser)
-> Result<NonTSPseudoClass, ()> {
macro_rules! pseudo_class_string_parse {
(bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => {
match_ignore_ascii_case! { &name,
$($s_css => {
let name = String::from(parser.expect_ident_or_string()?).into_boxed_str();
NonTSPseudoClass::$s_name(name)
}, )*
_ => return Err(())
}
}
}
let pseudo_class = apply_non_ts_list!(pseudo_class_string_parse);
if !pseudo_class.is_internal() || self.in_user_agent_stylesheet() {
Ok(pseudo_class)
} else {
Err(())
}
}
fn parse_pseudo_element(&self, name: Cow<str>) -> Result<PseudoElement, ()> { fn parse_pseudo_element(&self, name: Cow<str>) -> Result<PseudoElement, ()> {
match PseudoElement::from_slice(&name, self.in_user_agent_stylesheet()) { match PseudoElement::from_slice(&name, self.in_user_agent_stylesheet()) {
Some(pseudo) => Ok(pseudo), Some(pseudo) => Ok(pseudo),

View file

@ -661,7 +661,8 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
NonTSPseudoClass::MozTableBorderNonzero | NonTSPseudoClass::MozTableBorderNonzero |
NonTSPseudoClass::MozBrowserFrame => unsafe { NonTSPseudoClass::MozBrowserFrame => unsafe {
Gecko_MatchesElement(pseudo_class.to_gecko_pseudoclasstype().unwrap(), self.0) Gecko_MatchesElement(pseudo_class.to_gecko_pseudoclasstype().unwrap(), self.0)
} },
_ => false
} }
} }