From f69b863e3321c4e4bfd82a5b5fe9e124375b0f56 Mon Sep 17 00:00:00 2001 From: Connor Skees Date: Mon, 27 Jul 2020 22:09:38 -0400 Subject: [PATCH] better handle silent comments in maps and fn args --- src/parse/args.rs | 1 + src/parse/value/parse.rs | 16 ++++++++++++---- src/utils/chars.rs | 9 ++++++++- tests/args.rs | 13 +++++++++++++ tests/map.rs | 8 ++++++++ 5 files changed, 42 insertions(+), 5 deletions(-) diff --git a/src/parse/args.rs b/src/parse/args.rs index 053e160..d004121 100644 --- a/src/parse/args.rs +++ b/src/parse/args.rs @@ -48,6 +48,7 @@ impl<'a> Parser<'a> { match &tok.kind { ',' => { self.toks.next(); + self.whitespace_or_comment(); args.push(FuncArg { name: name.node.into(), default: Some(default), diff --git a/src/parse/value/parse.rs b/src/parse/value/parse.rs index f18976d..497a303 100644 --- a/src/parse/value/parse.rs +++ b/src/parse/value/parse.rs @@ -1062,9 +1062,16 @@ impl<'a, 'b: 'a> IntermediateValueIterator<'a, 'b> { let paren_toks = &mut t.node.into_iter().peekmore(); let mut map = SassMap::new(); - let key = self - .parser - .parse_value_from_vec(read_until_char(paren_toks, ':')?, true)?; + let key_toks = read_until_char(paren_toks, ':')?; + if key_toks.iter().all(|t| t.is_whitespace()) { + return Ok(Spanned { + node: HigherIntermediateValue::Paren(Box::new(HigherIntermediateValue::Literal( + Value::Map(map), + ))), + span: t.span, + }); + } + let key = self.parser.parse_value_from_vec(key_toks, true)?; if paren_toks.peek().is_none() { return Ok(Spanned { @@ -1096,13 +1103,14 @@ impl<'a, 'b: 'a> IntermediateValueIterator<'a, 'b> { let key = self .parser .parse_value_from_vec(read_until_char(paren_toks, ':')?, true)?; + devour_whitespace(paren_toks); let val = self .parser .parse_value_from_vec(read_until_char(paren_toks, ',')?, true)?; span = span.merge(val.span); devour_whitespace(paren_toks); - if map.insert(key.node, val.node) { + if map.insert(key.node.clone(), val.node) { return Err(("Duplicate key.", key.span).into()); } if paren_toks.peek().is_none() { diff --git a/src/utils/chars.rs b/src/utils/chars.rs index 68efb60..cb39bfa 100644 --- a/src/utils/chars.rs +++ b/src/utils/chars.rs @@ -4,7 +4,7 @@ use peekmore::PeekMoreIterator; use crate::{error::SassResult, Token}; -use super::{read_until_closing_paren, read_until_closing_quote}; +use super::{read_until_closing_paren, read_until_closing_quote, read_until_newline}; /// Reads until the char is found, consuming the char, /// or until the end of the iterator is hit pub(crate) fn read_until_char( @@ -24,6 +24,13 @@ pub(crate) fn read_until_char( v.extend(read_until_closing_paren(toks)?); continue; } + '/' => { + match toks.peek() { + Some(Token { kind: '/', .. }) => read_until_newline(toks), + _ => v.push(tok), + }; + continue; + } t if t == c => break, _ => {} } diff --git a/tests/args.rs b/tests/args.rs index 0afd994..90e3d1e 100644 --- a/tests/args.rs +++ b/tests/args.rs @@ -86,3 +86,16 @@ test!( }", "a {\n color: red;\n}\n" ); +test!( + comment_after_comma_in_func_args, + "@mixin a( + $foo,//foo + ) { + color: $foo; + } + + a { + @include a(red); + }", + "a {\n color: red;\n}\n" +); diff --git a/tests/map.rs b/tests/map.rs index 67d4c6d..65c5ac0 100644 --- a/tests/map.rs +++ b/tests/map.rs @@ -197,3 +197,11 @@ test!( "a {\n color: (a: b)==(a: c);\n}\n", "a {\n color: false;\n}\n" ); +test!( + empty_with_single_line_comments, + "$foo: (\n \n // :/a.b\n \n ); + a { + color: inspect($foo); + }", + "a {\n color: ();\n}\n" +);