refactor how & is handled in values

This commit is contained in:
ConnorSkees 2020-04-26 13:07:44 -04:00
parent 690c8a1f89
commit f6fd0e9af5
4 changed files with 129 additions and 21 deletions

View File

@ -2,12 +2,14 @@ use std::fmt::{self, Display, Write};
use peekmore::{PeekMore, PeekMoreIterator}; use peekmore::{PeekMore, PeekMoreIterator};
use crate::common::{Brackets, ListSeparator, QuoteKind};
use crate::error::SassResult; use crate::error::SassResult;
use crate::scope::Scope; use crate::scope::Scope;
use crate::utils::{ use crate::utils::{
devour_whitespace, eat_comment, eat_ident_no_interpolation, parse_interpolation, devour_whitespace, eat_comment, eat_ident_no_interpolation, parse_interpolation,
read_until_closing_paren, read_until_newline, IsWhitespace, read_until_closing_paren, read_until_newline, IsWhitespace,
}; };
use crate::value::Value;
use crate::Token; use crate::Token;
use attribute::Attribute; use attribute::Attribute;
@ -25,6 +27,44 @@ struct SelectorPart {
pub contains_super_selector: bool, pub contains_super_selector: bool,
} }
impl SelectorPart {
pub fn into_value(&self) -> Value {
let mut kinds = Vec::new();
let mut this_kind = Vec::new();
for kind in &self.inner {
match kind {
SelectorKind::Whitespace => {
if !this_kind.is_empty() {
kinds.push(SelectorPart {
inner: std::mem::take(&mut this_kind),
is_invisible: false,
has_newline: false,
contains_super_selector: false,
});
}
}
v => this_kind.push(v.clone()),
}
}
if !this_kind.is_empty() {
kinds.push(SelectorPart {
inner: std::mem::take(&mut this_kind),
is_invisible: false,
has_newline: false,
contains_super_selector: false,
});
}
Value::List(
kinds
.iter()
.map(|s| Value::Ident(s.to_string(), QuoteKind::None))
.collect(),
ListSeparator::Space,
Brackets::None,
)
}
}
impl Display for SelectorPart { impl Display for SelectorPart {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut iter = self.inner.iter().peekmore(); let mut iter = self.inner.iter().peekmore();
@ -562,4 +602,12 @@ impl Selector {
pub fn contains_super_selector(&self) -> bool { pub fn contains_super_selector(&self) -> bool {
self.0.iter().any(|s| s.contains_super_selector) self.0.iter().any(|s| s.contains_super_selector)
} }
pub fn into_value(&self) -> Value {
Value::List(
self.0.iter().map(SelectorPart::into_value).collect(),
ListSeparator::Comma,
Brackets::None,
)
}
} }

View File

@ -670,7 +670,7 @@ impl Value {
'&' => { '&' => {
let span = toks.next().unwrap().pos(); let span = toks.next().unwrap().pos();
Ok(IntermediateValue::Value(Spanned { Ok(IntermediateValue::Value(Spanned {
node: Value::Ident(super_selector.to_string(), QuoteKind::None), node: super_selector.into_value(),
span, span,
})) }))
} }

View File

@ -427,3 +427,83 @@ test!(
":not(%b) {x: y}", ":not(%b) {x: y}",
"* {\n x: y;\n}\n" "* {\n x: y;\n}\n"
); );
test!(
interpolated_super_selector_in_style,
"a {\n color: #{&};\n}\n",
"a {\n color: a;\n}\n"
);
test!(
interpolated_super_selector_in_style_symbols,
"* .a #b:foo() {\n color: #{&};\n}\n",
"* .a #b:foo() {\n color: * .a #b:foo();\n}\n"
);
test!(
uninterpolated_super_selector,
"* .a #b:foo() {\n color: &;\n}\n",
"* .a #b:foo() {\n color: * .a #b:foo();\n}\n"
);
test!(
interpolated_super_selector_in_selector_and_style,
"a {\n b #{&} {\n color: &;\n }\n}\n",
"a b a {\n color: a b a;\n}\n"
);
test!(
super_selector_treated_as_list,
"a, b {\n color: type-of(&);\n}\n",
"a, b {\n color: list;\n}\n"
);
test!(
length_of_comma_separated_super_selector,
"a, b {\n color: length(&);\n}\n",
"a, b {\n color: 2;\n}\n"
);
test!(
nth_1_of_comma_separated_super_selector,
"a, b {\n color: nth(&, 1);\n}\n",
"a, b {\n color: a;\n}\n"
);
test!(
nth_2_of_comma_separated_super_selector,
"a, b {\n color: nth(&, 2);\n}\n",
"a, b {\n color: b;\n}\n"
);
test!(
length_of_space_separated_super_selector,
"a b {\n color: length(&);\n}\n",
"a b {\n color: 1;\n}\n"
);
test!(
nth_1_of_space_separated_super_selector,
"a b {\n color: nth(&, 1);\n}\n",
"a b {\n color: a b;\n}\n"
);
test!(
length_of_comma_separated_super_selector_has_compound,
"a:foo, b {\n color: length(&);\n}\n",
"a:foo, b {\n color: 2;\n}\n"
);
test!(
nth_1_of_comma_separated_super_selector_has_compound,
"a:foo, b {\n color: nth(&, 1);\n}\n",
"a:foo, b {\n color: a:foo;\n}\n"
);
test!(
length_of_space_separated_super_selector_has_compound,
"a:foo b {\n color: length(&);\n}\n",
"a:foo b {\n color: 1;\n}\n"
);
test!(
nth_1_of_space_separated_super_selector_has_compound,
"a:foo b {\n color: nth(&, 1);\n}\n",
"a:foo b {\n color: a:foo b;\n}\n"
);
test!(
length_super_selector_placeholder,
"a, %b {\n color: length(&);\n}\n",
"a {\n color: 2;\n}\n"
);
test!(
nth_2_super_selector_placeholder,
"a, %b {\n color: nth(&, 2);\n}\n",
"a {\n color: %b;\n}\n"
);

View File

@ -155,26 +155,6 @@ test!(
styles_after_quoted, styles_after_quoted,
"a {\n color: \"red\";\n color: blue;\n}\n" "a {\n color: \"red\";\n color: blue;\n}\n"
); );
test!(
interpolated_super_selector_in_style,
"a {\n color: #{&};\n}\n",
"a {\n color: a;\n}\n"
);
test!(
interpolated_super_selector_in_style_symbols,
"* .a #b:foo() {\n color: #{&};\n}\n",
"* .a #b:foo() {\n color: * .a #b:foo();\n}\n"
);
test!(
uninterpolated_super_selector,
"* .a #b:foo() {\n color: &;\n}\n",
"* .a #b:foo() {\n color: * .a #b:foo();\n}\n"
);
test!(
interpolated_super_selector_in_selector_and_style,
"a {\n b #{&} {\n color: &;\n }\n}\n",
"a b a {\n color: a b a;\n}\n"
);
test!( test!(
emits_leading_whitespace, emits_leading_whitespace,
"a {\n color: unquote(\" foo\");\n}\n", "a {\n color: unquote(\" foo\");\n}\n",