increase selector code coverage

This commit is contained in:
connorskees 2023-01-20 22:59:27 +00:00
parent d0d9459d8e
commit 5889859968
12 changed files with 83 additions and 5 deletions

View File

@ -119,6 +119,7 @@ pub(crate) struct TokenLexer<'a> {
cursor: u32, cursor: u32,
} }
// todo: maybe char indices?
impl<'a> TokenLexer<'a> { impl<'a> TokenLexer<'a> {
pub fn new(buf: Peekable<Chars<'a>>) -> TokenLexer<'a> { pub fn new(buf: Peekable<Chars<'a>>) -> TokenLexer<'a> {
Self { buf, cursor: 0 } Self { buf, cursor: 0 }

View File

@ -5,6 +5,8 @@ use std::{
sync::atomic::{AtomicU32, Ordering as AtomicOrdering}, sync::atomic::{AtomicU32, Ordering as AtomicOrdering},
}; };
use codemap::Span;
use crate::error::SassResult; use crate::error::SassResult;
use super::{CompoundSelector, Pseudo, SelectorList, SimpleSelector, Specificity}; use super::{CompoundSelector, Pseudo, SelectorList, SimpleSelector, Specificity};
@ -323,10 +325,11 @@ impl ComplexSelectorComponent {
pub fn resolve_parent_selectors( pub fn resolve_parent_selectors(
self, self,
span: Span,
parent: SelectorList, parent: SelectorList,
) -> SassResult<Option<Vec<ComplexSelector>>> { ) -> SassResult<Option<Vec<ComplexSelector>>> {
match self { match self {
Self::Compound(c) => c.resolve_parent_selectors(parent), Self::Compound(c) => c.resolve_parent_selectors(span, parent),
Self::Combinator(..) => todo!(), Self::Combinator(..) => todo!(),
} }
} }

View File

@ -1,5 +1,7 @@
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use codemap::Span;
use crate::error::SassResult; use crate::error::SassResult;
use super::{ use super::{
@ -106,6 +108,7 @@ impl CompoundSelector {
/// Returns `None` if `compound` doesn't contain any `SimpleSelector::Parent`s. /// Returns `None` if `compound` doesn't contain any `SimpleSelector::Parent`s.
pub fn resolve_parent_selectors( pub fn resolve_parent_selectors(
self, self,
span: Span,
parent: SelectorList, parent: SelectorList,
) -> SassResult<Option<Vec<ComplexSelector>>> { ) -> SassResult<Option<Vec<ComplexSelector>>> {
let contains_selector_pseudo = self.components.iter().any(|simple| { let contains_selector_pseudo = self.components.iter().any(|simple| {
@ -163,7 +166,7 @@ impl CompoundSelector {
)])); )]));
} }
let span = parent.span; let parent_span = parent.span;
Ok(Some( Ok(Some(
parent parent
@ -185,7 +188,7 @@ impl CompoundSelector {
if let Some(SimpleSelector::Parent(Some(suffix))) = self.components.first() { if let Some(SimpleSelector::Parent(Some(suffix))) = self.components.first() {
let mut end = components.pop().unwrap(); let mut end = components.pop().unwrap();
end.add_suffix(suffix, span)?; end.add_suffix(suffix, parent_span)?;
components.push(end); components.push(end);
} }

View File

@ -206,7 +206,7 @@ impl SelectorList {
if component.is_compound() { if component.is_compound() {
let resolved = match component let resolved = match component
.clone() .clone()
.resolve_parent_selectors(parent.clone())? .resolve_parent_selectors(self.span, parent.clone())?
{ {
Some(r) => r, Some(r) => r,
None => { None => {

View File

@ -469,6 +469,11 @@ test!(
"a {\n color: is-superselector(\"::-pfx-slotted(c d, e f)\", \"::-pfx-slotted(c d, e f)\");\n}\n", "a {\n color: is-superselector(\"::-pfx-slotted(c d, e f)\", \"::-pfx-slotted(c d, e f)\");\n}\n",
"a {\n color: true;\n}\n" "a {\n color: true;\n}\n"
); );
test!(
other_complex_ends_in_combinator,
"a {\n color: is-superselector(\"a > b\", \"a >\");\n}\n",
"a {\n color: false;\n}\n"
);
// todo: /spec/core_functions/selector/is_superselector/simple/pseudo/selector_arg/ // todo: /spec/core_functions/selector/is_superselector/simple/pseudo/selector_arg/
// :not, :matches, :nth-child, :nth-last-child // :not, :matches, :nth-child, :nth-last-child

View File

@ -478,6 +478,22 @@ test!(
}", }",
"a {\n color: true;\n}\n" "a {\n color: true;\n}\n"
); );
test!(
list_separator_slash,
"@use 'sass:list';
a {
color: list-separator(list.slash(a, b));
}",
"a {\n color: slash;\n}\n"
);
test!(
list_slash,
"@use 'sass:list';
a {
color: list.slash(a, b, c);
}",
"a {\n color: a / b / c;\n}\n"
);
error!( error!(
nth_list_index_0, nth_list_index_0,
"a {\n color: nth(a b c, 0);\n}\n", "Error: $n: List index may not be 0." "a {\n color: nth(a b c, 0);\n}\n", "Error: $n: List index may not be 0."

View File

@ -195,6 +195,14 @@ error!(
"Error: Interpolation isn't allowed in plain CSS.", "Error: Interpolation isn't allowed in plain CSS.",
grass::Options::default().input_syntax(InputSyntax::Css) grass::Options::default().input_syntax(InputSyntax::Css)
); );
error!(
disallows_placeholder_selector,
"%a {
color: red;
}",
"Error: Placeholder selectors aren't allowed here.",
grass::Options::default().input_syntax(InputSyntax::Css)
);
test!( test!(
allows_rgb_function, allows_rgb_function,
"a { "a {

View File

@ -74,3 +74,7 @@ error!(
"a {\n color: selector-append();\n}\n", "a {\n color: selector-append();\n}\n",
"Error: $selectors: At least one selector must be passed." "Error: $selectors: At least one selector must be passed."
); );
error!(
append_two_type_selectors_with_namespace,
"a {\n color: selector-append(\"a|a\", \"a|a\");\n}\n", "Error: Can't append a|a to a|a."
);

View File

@ -131,6 +131,16 @@ test!(
"a {\n color: selector-nest(\"c\", (d, e f));\n}\n", "a {\n color: selector-nest(\"c\", (d, e f));\n}\n",
"a {\n color: c d, c e f;\n}\n" "a {\n color: c d, c e f;\n}\n"
); );
test!(
double_nested_parent_selector_inside_psuedo_class,
"a {\n color: selector-nest(\"a\", \":matches(&:not(&))\");\n}\n",
"a {\n color: :matches(a:not(a));\n}\n"
);
test!(
double_nested_parent_selector_inside_psuedo_class_as_part_of_complex,
"a {\n color: selector-nest(\"a\", \":not(&):matches(:not(a))\");\n}\n",
"a {\n color: :not(a):matches(:not(a));\n}\n"
);
error!( error!(
#[ignore = "https://github.com/sass/dart-sass/issues/966"] #[ignore = "https://github.com/sass/dart-sass/issues/966"]
disallows_parent_selector_as_first_arg, disallows_parent_selector_as_first_arg,
@ -169,3 +179,8 @@ error!(
"a {\n color: selector-nest();\n}\n", "a {\n color: selector-nest();\n}\n",
"Error: $selectors: At least one selector must be passed." "Error: $selectors: At least one selector must be passed."
); );
error!(
parent_ends_with_combinator_and_child_has_parent_selector_as_pseudo_element,
"a {\n color: selector-nest(\"a >\", \":matches(&c)\");\n}\n",
"Error: Parent \"a >\" is incompatible with this selector."
);

View File

@ -101,6 +101,11 @@ test!(
"a {\n color: selector-parse(\"b c, d e, f g\");\n}\n", "a {\n color: selector-parse(\"b c, d e, f g\");\n}\n",
"a {\n color: b c, d e, f g;\n}\n" "a {\n color: b c, d e, f g;\n}\n"
); );
test!(
not_pseudo_invisible,
"a {\n color: selector-parse(\":not(%a)\");\n}\n",
"a {\n color: *;\n}\n"
);
error!( error!(
invalid_selector, invalid_selector,
"a {\n color: selector-parse(\"!!!!!!!!\");\n}\n", "Error: $selector: expected selector." "a {\n color: selector-parse(\"!!!!!!!!\");\n}\n", "Error: $selector: expected selector."

View File

@ -678,3 +678,13 @@ test!(
"a {\n color: selector-unify(\":is(.c)\", \":is(.d)\");\n}\n", "a {\n color: selector-unify(\":is(.c)\", \":is(.d)\");\n}\n",
"a {\n color: :is(.c):is(.d);\n}\n" "a {\n color: :is(.c):is(.d);\n}\n"
); );
test!(
universal_and_class,
"a {\n color: selector-unify(\"*\", \".a\");\n}\n",
"a {\n color: .a;\n}\n"
);
test!(
universal_and_psuedo,
"a {\n color: selector-unify(\"*\", \":a\");\n}\n",
"a {\n color: :a;\n}\n"
);

View File

@ -971,9 +971,17 @@ error!(
":nth-child(even#) {\n color: &;\n}\n", "Error: expected \")\"." ":nth-child(even#) {\n color: &;\n}\n", "Error: expected \")\"."
); );
error!( error!(
a_n_plus_b_n_nothing_after_plus, a_n_plus_b_n_double_nothing_after_plus,
":nth-child:nth-child(n+{}", "Error: Expected a number." ":nth-child:nth-child(n+{}", "Error: Expected a number."
); );
error!(
a_n_plus_b_n_nothing_after_plus,
":nth-child(n+{}", "Error: Expected a number."
);
error!(
a_n_plus_b_n_non_numeric_after_plus,
":nth-child(n+b) {}", "Error: Expected a number."
);
error!(nothing_after_period, ". {}", "Error: Expected identifier."); error!(nothing_after_period, ". {}", "Error: Expected identifier.");
error!(nothing_after_hash, "# {}", "Error: Expected identifier."); error!(nothing_after_hash, "# {}", "Error: Expected identifier.");
error!(nothing_after_percent, "% {}", "Error: Expected identifier."); error!(nothing_after_percent, "% {}", "Error: Expected identifier.");