servo/components/selectors/visitor.rs
Martin Robinson 2fa76916d3
Revert as many changes to selectors from upstream as possible (#31365)
This is part of the preparation for splitting stylo into a separate
crate. We have made various changes to selectors includings:

 1. Bumping the rust edition
 2. Fixing typos and updating links

In addition to reverting those changes, this PR pulls in some changes to
selectors we seem to have missed in the process of updates.
2024-02-20 06:57:10 +00:00

111 lines
3.6 KiB
Rust

/* 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 https://mozilla.org/MPL/2.0/. */
//! Visitor traits for selectors.
#![deny(missing_docs)]
use crate::attr::NamespaceConstraint;
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: Sized {
/// The selector implementation this visitor wants to visit.
type Impl: SelectorImpl;
/// Visit an attribute selector that may match (there are other selectors
/// that may never match, like those containing whitespace or the empty
/// string).
fn visit_attribute_selector(
&mut self,
_namespace: &NamespaceConstraint<&<Self::Impl as SelectorImpl>::NamespaceUrl>,
_local_name: &<Self::Impl as SelectorImpl>::LocalName,
_local_name_lower: &<Self::Impl as SelectorImpl>::LocalName,
) -> bool {
true
}
/// Visit a simple selector.
fn visit_simple_selector(&mut self, _: &Component<Self::Impl>) -> bool {
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_kind: SelectorListKind,
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
/// selector is the rightmost one.
fn visit_complex_selector(&mut self, _combinator_to_right: Option<Combinator>) -> bool {
true
}
}
bitflags! {
/// The kinds of components the visitor is visiting the selector list of, if any
#[derive(Default)]
pub struct SelectorListKind: u8 {
/// The visitor is inside :not(..)
const NEGATION = 1 << 0;
/// The visitor is inside :is(..)
const IS = 1 << 1;
/// The visitor is inside :where(..)
const WHERE = 1 << 2;
/// The visitor is inside :nth-child(.. of <selector list>) or
/// :nth-last-child(.. of <selector list>)
const NTH_OF = 1 << 3;
}
}
impl SelectorListKind {
/// Construct a SelectorListKind for the corresponding component.
pub fn from_component<Impl: SelectorImpl>(component: &Component<Impl>) -> Self {
match component {
Component::Negation(_) => SelectorListKind::NEGATION,
Component::Is(_) => SelectorListKind::IS,
Component::Where(_) => SelectorListKind::WHERE,
Component::NthOf(_) => SelectorListKind::NTH_OF,
_ => SelectorListKind::empty(),
}
}
/// Whether the visitor is inside :not(..)
pub fn in_negation(&self) -> bool {
self.intersects(SelectorListKind::NEGATION)
}
/// Whether the visitor is inside :is(..)
pub fn in_is(&self) -> bool {
self.intersects(SelectorListKind::IS)
}
/// Whether the visitor is inside :where(..)
pub fn in_where(&self) -> bool {
self.intersects(SelectorListKind::WHERE)
}
/// Whether the visitor is inside :nth-child(.. of <selector list>) or
/// :nth-last-child(.. of <selector list>)
pub fn in_nth_of(&self) -> bool {
self.intersects(SelectorListKind::NTH_OF)
}
}