Skip to content

Commit

Permalink
Cleanup.
Browse files Browse the repository at this point in the history
Remove remains of the old selector / logical selector divide.
  • Loading branch information
kaj committed Sep 9, 2024
1 parent 284d1cf commit 8ba98b7
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 76 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@ project adheres to

## Unreleased

(Nothing yet)
### Breaking changes:

* Replaced the css `Selector` implementation.
The new "logical" selector types that was used in selector
function in rsass 0.28 is now the only css selector implementation.
Most of the api to those types are private.
Some will probably be made public after some stabilization period.

## Release 0.28.10

Expand Down
2 changes: 1 addition & 1 deletion rsass/src/css/selectors/attribute.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{css::CssString, output::CssBuf};

/// A logical attribute selector.
/// An attribute selector.
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct Attribute {
/// The attribute name
Expand Down
5 changes: 5 additions & 0 deletions rsass/src/css/selectors/compound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ impl CompoundSelector {
pub(super) fn has_id(&self) -> bool {
self.id.is_some()
}
pub(super) fn cant_append(&self) -> bool {
self.is_empty()
|| self.element.as_ref().map_or(false, ElemType::cant_append)
}

pub(super) fn is_rootish(&self) -> bool {
self.pseudo.iter().any(Pseudo::is_rootish)
}
Expand Down
11 changes: 6 additions & 5 deletions rsass/src/css/selectors/elemtype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ impl ElemType {
pub fn is_any(&self) -> bool {
self.s == "*"
}
pub(super) fn cant_append(&self) -> bool {
self.s.starts_with('*') || self.s.starts_with('|')
}

pub fn is_superselector(&self, sub: &Self) -> bool {
let (e_ns, e_name) = self.split_ns();
Expand Down Expand Up @@ -48,11 +51,9 @@ impl ElemType {
}

fn split_ns(&self) -> (Option<&str>, &str) {
let mut e = self.s.splitn(2, '|');
match (e.next(), e.next()) {
(Some(ns), Some(elem)) => (Some(ns), elem),
(Some(elem), None) => (None, elem),
_ => unreachable!(),
match self.s.split_once('|') {
Some((ns, name)) => (Some(ns), name),
None => (None, &self.s),
}
}

Expand Down
3 changes: 2 additions & 1 deletion rsass/src/css/selectors/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ impl From<ParseError> for BadSelector0 {
}
}

/// The error when a [Value] cannot be converted to a [Selectors] or [Selector].
/// The error when a [`Value`] cannot be converted to a
/// [`SelectorSet`][super::SelectorSet] or [`Selector`][super::Selector].
#[derive(Debug)]
pub enum BadSelector {
/// The value was not the expected type of list or string.
Expand Down
6 changes: 3 additions & 3 deletions rsass/src/css/selectors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ mod context;
mod cssselectorset;
mod elemtype;
mod error;
mod logical;
mod opt;
mod pseudo;
mod selector;
mod selectorset;

use self::attribute::Attribute;
Expand All @@ -21,7 +21,7 @@ use self::pseudo::Pseudo;
pub use context::SelectorCtx;
pub(crate) use cssselectorset::CssSelectorSet;
pub use error::BadSelector;
pub use logical::Selector;
pub use selector::Selector;
pub use selectorset::SelectorSet;

pub(crate) mod parser {
Expand All @@ -30,7 +30,7 @@ pub(crate) mod parser {
pub(super) use super::elemtype::parser::{
elem_name, keyframe_stop, name_opt_ns,
};
pub(super) use super::logical::parser::selector;
pub(super) use super::pseudo::parser::pseudo;
pub(super) use super::selector::parser::selector;
pub(crate) use super::selectorset::parser::selector_set;
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
//! A logical selector is a css selector, but representend in a way
//! that I hope make implementing the sass selector functions easier.
//!
//! In the future, I might use this as the primary (only) css selector
//! implementation. But as that is a major breaking change, I keep
//! these types internal for now.
use super::compound::CompoundSelector;
use super::error::BadSelector0;
use super::parser::compound_selector;
use super::{BadSelector, CssSelectorSet, Opt, Pseudo, SelectorSet};
use super::{BadSelector, CssSelectorSet, Opt, SelectorSet};
use crate::css::Value;
use crate::output::CssBuf;
use crate::parser::input_span;
Expand All @@ -19,9 +13,9 @@ use std::iter::once;

type RelBox = Box<(RelKind, Selector)>;

/// A selector more aimed at making it easy to implement selector functions.
/// A css selector.
///
/// A logical selector is a sequence of compound selectors, joined by
/// A selector is a sequence of compound selectors, joined by
/// relational operators (where the "ancestor" relation is just
/// whitespace in the text representation).
#[derive(Default, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -80,27 +74,17 @@ impl Selector {
result.rel_of = Some(Box::new((rel.0, self.append(&rel.1)?)));
Ok(result)
} else {
let rel_of = self.rel_of.clone();
if result.is_local_empty() {
if result.compound.cant_append() {
return Err(AppendError::Sub);
}
let s = self.clone().last_compound_str();
let other = result.last_compound_str();
if other
.bytes()
.next()
.map_or(true, |c| c == b'*' || c == b'|')
{
return Err(AppendError::Sub);
}
let s = s + &other;
let span = input_span(s);
Ok(Self {
rel_of,
compound: ParseError::check(compound_selector(
span.borrow(),
))?,
})
let rel_of = self.rel_of.clone();
let mut s = CssBuf::new(Default::default());
self.compound.write_to(&mut s);
result.compound.write_to(&mut s);
let span = input_span(s.take());
let compound =
ParseError::check(compound_selector(span.borrow()))?;
Ok(Self { rel_of, compound })
}
}

Expand Down Expand Up @@ -170,7 +154,7 @@ impl Selector {
self = self.resolve_ref_in_pseudo(ctx);
let rel_of = self.rel_of.take();

let result = if self.compound.has_backref() {
let result = if self.compound.backref.is_some() {
self.compound.backref = None;
ctx.s
.s
Expand Down Expand Up @@ -446,34 +430,24 @@ impl Selector {
self.compound.write_to(buf)
}

pub(super) fn into_string_vec(mut self) -> Vec<String> {
let mut vec =
if let Some((kind, sel)) = self.rel_of.take().map(|b| *b) {
let mut vec = sel.into_string_vec();
if let Some(symbol) = kind.symbol() {
vec.push(symbol.to_string());
}
vec
} else {
Vec::new()
};
let last = self.last_compound_str();
if !last.is_empty() {
vec.push(last);
pub(super) fn into_string_vec(self) -> Vec<String> {
let mut vec = if let Some((kind, sel)) = self.rel_of.map(|b| *b) {
let mut vec = sel.into_string_vec();
if let Some(symbol) = kind.symbol() {
vec.push(symbol.to_string());
}
vec
} else {
Vec::new()
};
if !self.compound.is_empty() {
let mut buf = CssBuf::new(Default::default());
self.compound.write_to(&mut buf);
vec.push(String::from_utf8_lossy(&buf.take()).to_string());
}
vec
}

fn last_compound_str(self) -> String {
let mut buf = CssBuf::new(Default::default());
self.compound.write_to(&mut buf);
String::from_utf8_lossy(&buf.take()).to_string()
}

fn pseudo_element(&self) -> Option<&Pseudo> {
self.compound.pseudo_element()
}

/// Internal (the api is [`TryFrom`]).
pub(super) fn _try_from_value(v: &Value) -> Result<Self, BadSelector0> {
match v {
Expand Down Expand Up @@ -580,8 +554,7 @@ fn unify_relbox(a: RelBox, b: RelBox) -> Option<Vec<RelBox>> {
if b.is_local_superselector(&a) {
as_rel_vec(Ancestor, a._unify(b)?)
} else if a.is_local_superselector(&b)
|| have_same(&a.compound.id, &b.compound.id)
|| have_same(&a.pseudo_element(), &b.pseudo_element())
|| a.compound.must_not_inherit(&b.compound)
{
as_rel_vec(Ancestor, b._unify(a)?)
} else {
Expand All @@ -599,7 +572,7 @@ fn unify_relbox(a: RelBox, b: RelBox) -> Option<Vec<RelBox>> {
as_rel_vec(Sibling, once(b))
} else if b.is_superselector(&a) {
as_rel_vec(Sibling, once(a))
} else if !have_same(&a.compound.id, &b.compound.id) {
} else if !a.compound.must_not_inherit(&b.compound) {
as_rel_vec(
Sibling,
b.clone()
Expand All @@ -616,7 +589,7 @@ fn unify_relbox(a: RelBox, b: RelBox) -> Option<Vec<RelBox>> {
| ((Sibling, b_s), (a_k @ AdjacentSibling, a_s)) => {
if b_s.is_superselector(&a_s) {
as_rel_vec(a_k, once(a_s))
} else if a_s.compound.id.is_some() || b_s.compound.id.is_some() {
} else if a_s.compound.has_id() || b_s.compound.has_id() {
as_rel_vec(a_k, a_s.with_rel_of(Sibling, b_s))
} else {
as_rel_vec(
Expand All @@ -642,10 +615,6 @@ fn unify_relbox(a: RelBox, b: RelBox) -> Option<Vec<RelBox>> {
})
}

fn have_same<T: Eq>(one: &Option<T>, other: &Option<T>) -> bool {
one.is_some() && one == other
}

impl TryFrom<Value> for Selector {
type Error = BadSelector;

Expand Down
7 changes: 3 additions & 4 deletions rsass/src/sass/selectors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
//!
//! This _may_ change to a something like a tree of operators with
//! leafs of simple selectors in some future release.
use crate::css::parser::selector_set;
use crate::css::{self, SelectorSet};
use crate::css::{self, parser::selector_set};
use crate::parser::input_span;
use crate::sass::SassString;
use crate::{Error, ParseError, ScopeRef};
Expand Down Expand Up @@ -35,12 +34,12 @@ impl Selectors {
}

/// Evaluate any interpolation in these Selectors.
pub fn eval(&self, scope: ScopeRef) -> Result<SelectorSet, Error> {
pub fn eval(&self, scope: ScopeRef) -> Result<css::SelectorSet, Error> {
let mut s = Vec::new();
for sel in &self.s {
s.extend(sel.eval(scope.clone())?);
}
Ok(SelectorSet { s })
Ok(css::SelectorSet { s })
}
fn write_eval(
&self,
Expand Down

0 comments on commit 8ba98b7

Please sign in to comment.