allow multiline comments in more contexts

This commit is contained in:
Connor Skees 2020-08-07 11:39:14 -04:00
parent 484409761d
commit d5b2410a8c
15 changed files with 84 additions and 30 deletions

View File

@ -155,8 +155,7 @@ impl<'a> Parser<'a> {
}
pub(super) fn parse_for(&mut self) -> SassResult<Vec<Stmt>> {
// todo: whitespace or comment
self.whitespace();
self.whitespace_or_comment();
// todo: test for error here
self.expect_char('$')?;
@ -164,7 +163,7 @@ impl<'a> Parser<'a> {
.parse_identifier_no_interpolation(false)?
.map_node(|n| n.into());
self.whitespace();
self.whitespace_or_comment();
self.span_before = match self.toks.peek() {
Some(tok) => tok.pos,
None => return Err(("Expected \"from\".", var.span).into()),
@ -172,7 +171,7 @@ impl<'a> Parser<'a> {
if self.parse_identifier()?.node.to_ascii_lowercase() != "from" {
return Err(("Expected \"from\".", var.span).into());
}
self.whitespace();
self.whitespace_or_comment();
let mut from_toks = Vec::new();
let mut through = 0;
while let Some(tok) = self.toks.peek().cloned() {
@ -234,7 +233,7 @@ impl<'a> Parser<'a> {
}
}
}
self.whitespace();
self.whitespace_or_comment();
let from_val = self.parse_value_from_vec(from_toks, true)?;
let from = match from_val.node {
Value::Dimension(Some(n), ..) => match n.to_integer().to_isize() {
@ -272,8 +271,6 @@ impl<'a> Parser<'a> {
let body = read_until_closing_curly_brace(self.toks)?;
self.toks.next();
self.whitespace();
let (mut x, mut y);
// we can't use an inclusive range here
#[allow(clippy::range_plus_one)]
@ -348,7 +345,10 @@ impl<'a> Parser<'a> {
}
pub(super) fn parse_while(&mut self) -> SassResult<Vec<Stmt>> {
self.whitespace();
// technically not necessary to eat whitespace here, but since we
// operate on raw tokens rather than an AST, it potentially saves a lot of
// time in re-parsing
self.whitespace_or_comment();
let cond = read_until_open_curly_brace(self.toks)?;
if cond.is_empty() {
@ -364,8 +364,6 @@ impl<'a> Parser<'a> {
None => return Err(("expected \"}\".", self.span_before).into()),
});
self.whitespace();
let mut stmts = Vec::new();
let mut val = self.parse_value_from_vec(cond.clone(), true)?;
self.scopes.enter_new_scope();
@ -424,16 +422,15 @@ impl<'a> Parser<'a> {
}
pub(super) fn parse_each(&mut self) -> SassResult<Vec<Stmt>> {
self.whitespace();
let mut vars: Vec<Spanned<Identifier>> = Vec::new();
self.whitespace_or_comment();
loop {
self.expect_char('$')?;
vars.push(self.parse_identifier()?.map_node(|i| i.into()));
// todo: whitespace or comment
self.whitespace();
self.whitespace_or_comment();
if self
.toks
.peek()
@ -442,7 +439,7 @@ impl<'a> Parser<'a> {
== ','
{
self.toks.next();
self.whitespace();
self.whitespace_or_comment();
} else {
break;
}
@ -451,7 +448,7 @@ impl<'a> Parser<'a> {
if i.node.to_ascii_lowercase() != "in" {
return Err(("Expected \"in\".", i.span).into());
}
self.whitespace();
self.whitespace_or_comment();
let iter_val_toks = read_until_open_curly_brace(self.toks)?;
let iter = self
.parse_value_from_vec(iter_val_toks, true)?

View File

@ -121,7 +121,7 @@ impl<'a> Parser<'a> {
return Err(("This at-rule is not allowed here.", self.span_before).into());
}
self.whitespace();
self.whitespace_or_comment();
match self.toks.peek() {
Some(Token { kind: '\'', .. })

View File

@ -35,6 +35,7 @@ impl<'a> Parser<'a> {
false
}
// todo: replace with predicate
pub fn expression_until_comparison(&mut self) -> SassResult<Cow<'static, str>> {
let mut toks = Vec::new();
while let Some(tok) = self.toks.peek().cloned() {
@ -71,7 +72,7 @@ impl<'a> Parser<'a> {
pub(super) fn parse_media_query_list(&mut self) -> SassResult<String> {
let mut buf = String::new();
loop {
self.whitespace();
self.whitespace_or_comment();
buf.push_str(&self.parse_single_media_query()?);
if !self.scan_char(',') {
break;
@ -94,13 +95,13 @@ impl<'a> Parser<'a> {
let mut buf = String::with_capacity(2);
self.expect_char('(')?;
buf.push('(');
self.whitespace();
self.whitespace_or_comment();
buf.push_str(&self.expression_until_comparison()?);
if let Some(Token { kind: ':', .. }) = self.toks.peek() {
self.toks.next();
self.whitespace();
self.whitespace_or_comment();
buf.push(':');
buf.push(' ');
@ -112,7 +113,7 @@ impl<'a> Parser<'a> {
}
buf.push_str(&self.parse_value_as_string_from_vec(toks, true)?);
self.whitespace();
self.whitespace_or_comment();
buf.push(')');
return Ok(buf);
} else {
@ -127,14 +128,14 @@ impl<'a> Parser<'a> {
}
buf.push(' ');
self.whitespace();
self.whitespace_or_comment();
buf.push_str(&self.expression_until_comparison()?);
}
}
self.expect_char(')')?;
self.whitespace();
self.whitespace_or_comment();
buf.push(')');
Ok(buf)
}
@ -145,7 +146,7 @@ impl<'a> Parser<'a> {
if !matches!(self.toks.peek(), Some(Token { kind: '(', .. })) {
buf.push_str(&self.parse_identifier()?);
self.whitespace();
self.whitespace_or_comment();
if let Some(tok) = self.toks.peek() {
if !is_name_start(tok.kind) {
@ -156,7 +157,7 @@ impl<'a> Parser<'a> {
buf.push(' ');
let ident = self.parse_identifier()?;
self.whitespace();
self.whitespace_or_comment();
if ident.to_ascii_lowercase() == "and" {
buf.push_str("and ");
@ -164,7 +165,7 @@ impl<'a> Parser<'a> {
buf.push_str(&ident);
if self.scan_identifier("and")? {
self.whitespace();
self.whitespace_or_comment();
buf.push_str(" and ");
} else {
return Ok(buf);
@ -173,9 +174,9 @@ impl<'a> Parser<'a> {
}
loop {
self.whitespace();
self.whitespace_or_comment();
buf.push_str(&self.parse_media_feature()?);
self.whitespace();
self.whitespace_or_comment();
if !self.scan_identifier("and")? {
break;
}

View File

@ -616,7 +616,7 @@ impl<'a> Parser<'a> {
}
let mut params = String::new();
self.whitespace();
self.whitespace_or_comment();
if let Some(Token { kind: ';', .. }) | None = self.toks.peek() {
self.toks.next();
return Ok(Stmt::UnknownAtRule(Box::new(UnknownAtRule {

View File

@ -109,7 +109,7 @@ impl<'a> Parser<'a> {
}
let mut property = self.parse_identifier()?.node;
let whitespace_after_property = self.whitespace();
let whitespace_after_property = self.whitespace_or_comment();
match self.toks.peek() {
Some(Token { kind: ':', .. }) => {

View File

@ -28,7 +28,7 @@ impl<'a> Parser<'a> {
pub(super) fn parse_variable_declaration(&mut self) -> SassResult<()> {
assert!(matches!(self.toks.next(), Some(Token { kind: '$', .. })));
let ident: Identifier = self.parse_identifier_no_interpolation(false)?.node.into();
self.whitespace();
self.whitespace_or_comment();
self.expect_char(':')?;

View File

@ -77,6 +77,17 @@ test!(
}",
"a {\n color: a;\n color: b;\n color: 1;\n color: b;\n}\n"
);
// todo: newlines are not correct
test!(
multiline_comments_everywhere,
" /**/ @each /**/ $a /**/ , /**/ $b /**/ in /**/ ( /**/ a /**/ , /**/ b /**/ ) /**/ { /**/
a {
color: $a;
color: $b;
}
} /**/ ",
"/**/\n/**/\na {\n color: a;\n}\n/**/\n\na {\n color: b;\n}\n/**/\n"
);
error!(
list_of_single_map,
"a {

View File

@ -113,3 +113,8 @@ test!(
}",
"a {\n color: 1;\n color: 2;\n color: 1;\n color: 2;\n}\n"
);
test!(
multiline_comments_everywhere,
" /**/ @for /**/ $i /**/ from /**/ 0 /**/ to /**/ 2 /**/ {} /**/ ",
"/**/\n/**/\n"
);

View File

@ -163,6 +163,16 @@ test!(
}",
"a {\n a: \\}}}{{{#;\n b: \\}}}{{{#;\n c: \\}}}{{{#;\n}\n"
);
test!(
multiline_comments_everywhere,
" /**/ @if /**/ false /**/ {} /**/
/**/
/**/ @else /**/ if /**/ false /**/ {} /**/
/**/
/**/ @else /**/ {} /**/
/**/ ",
"/**/\n/**/\n/**/\n"
);
error!(
nothing_after_escape,
"@if \\", "Error: Expected expression."

View File

@ -188,6 +188,11 @@ test!(
"@import url(#{1+1}..);",
"@import url(2..);\n"
);
test!(
import_multiline_comments_everywhere,
" /**/ @import /**/ url(foo) /**/ ;",
"/**/\n@import url(foo);\n"
);
// todo: test for calling paths, e.g. `grass b\index.scss`
// todo: test for absolute paths (how?)

View File

@ -63,3 +63,12 @@ test!(
}",
"@media screen and (:) {\n a {\n color: red;\n }\n}\n"
);
test!(
multiline_comments_everywhere,
"@media/**/foo/**/and/**/(/**/bar/**/)/**/{
a {
color: red;
}
}",
"@media foo and (bar) {\n a {\n color: red;\n }\n}\n"
);

View File

@ -170,3 +170,8 @@ test!(
"a {\n color: unquote(\"foo \");\n}\n",
"a {\n color: foo ;\n}\n"
);
test!(
multiline_comment_after_style_property,
"a {\n color /**/ : red;\n}\n",
"a {\n color: red;\n}\n"
);

View File

@ -29,3 +29,4 @@ test!(
}",
"@foo (a: b) {\n a {\n color: red;\n }\n}\na {\n color: green;\n}\n"
);
test!(contains_multiline_comment, "@foo /**/;\n", "@foo;\n");

View File

@ -149,6 +149,11 @@ test!(
}",
"a {\n color: red;\n}\n"
);
test!(
multiline_comments_everywhere,
" /**/ $a /**/ : /**/ red /**/ ; /**/ ",
"/**/\n/**/\n"
);
// https://github.com/Kixiron/lasso/issues/7
test!(
regression_test_for_lasso_0_3_0,

View File

@ -125,6 +125,11 @@ test!(
}",
"a {\n color: red;\n}\n\na {\n color: blue;\n}\n"
);
test!(
multiline_comments_everywhere,
" /**/ @while /**/ false /**/ {} /**/ ",
"/**/\n/**/\n"
);
error!(
missing_closing_curly_brace,
"@while true {", "Error: expected \"}\"."