style: Implement parsing / selector-matching for :is() and :where().

This implements the easy / straight-forward parts of the :where / :is
selectors.

The biggest missing piece is to handle properly invalidation when there
are combinators present inside the :where. That's the hard part of this,
actually.

But this is probably worth landing in the interim. This fixes some of
the visitors that were easy to fix.

Differential Revision: https://phabricator.services.mozilla.com/D70788
This commit is contained in:
Emilio Cobos Álvarez 2020-04-17 13:37:59 +00:00
parent 66f14773c6
commit 83ea321096
10 changed files with 338 additions and 223 deletions

View file

@ -7,13 +7,13 @@
#![deny(missing_docs)]
use crate::attr::NamespaceConstraint;
use crate::parser::{Combinator, Component, SelectorImpl};
use crate::parser::{Combinator, Component, Selector, SelectorImpl};
/// A trait to visit selector properties.
///
/// All the `visit_foo` methods return a boolean indicating whether the
/// traversal should continue or not.
pub trait SelectorVisitor {
pub trait SelectorVisitor: Sized {
/// The selector implementation this visitor wants to visit.
type Impl: SelectorImpl;
@ -34,6 +34,19 @@ pub trait SelectorVisitor {
true
}
/// Visit a nested selector list. The caller is responsible to call visit
/// into the internal selectors if / as needed.
///
/// The default implementation does this.
fn visit_selector_list(&mut self, list: &[Selector<Self::Impl>]) -> bool {
for nested in list {
if !nested.visit(self) {
return false;
}
}
true
}
/// Visits a complex selector.
///
/// Gets the combinator to the right of the selector, or `None` if the
@ -42,31 +55,3 @@ pub trait SelectorVisitor {
true
}
}
/// Enables traversing selector components stored in various types
pub trait Visit {
/// The type parameter of selector component types.
type Impl: SelectorImpl;
/// Traverse selector components inside `self`.
///
/// Implementations of this method should call `SelectorVisitor` methods
/// or other impls of `Visit` as appropriate based on the fields of `Self`.
///
/// A return value of `false` indicates terminating the traversal.
/// It should be propagated with an early return.
/// On the contrary, `true` indicates that all fields of `self` have been traversed:
///
/// ```rust,ignore
/// if !visitor.visit_simple_selector(&self.some_simple_selector) {
/// return false;
/// }
/// if !self.some_component.visit(visitor) {
/// return false;
/// }
/// true
/// ```
fn visit<V>(&self, visitor: &mut V) -> bool
where
V: SelectorVisitor<Impl = Self::Impl>;
}