diff --git a/src/parse/media.rs b/src/parse/media.rs index ac173d1..cbe2092 100644 --- a/src/parse/media.rs +++ b/src/parse/media.rs @@ -7,7 +7,7 @@ use crate::{ use super::Parser; impl<'a> Parser<'a> { - pub fn scan_identifier(&mut self, ident: &str) -> SassResult { + pub fn scan_identifier(&mut self, ident: &'static str) -> SassResult { let peeked_identifier = match peek_ident_no_interpolation(self.toks, false, self.span_before) { Ok(v) => v.node, diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 36d50d1..fe12241 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -17,10 +17,7 @@ use crate::{ ComplexSelectorComponent, ExtendRule, ExtendedSelector, Extender, Selector, SelectorParser, }, style::Style, - utils::{ - peek_ident_no_interpolation, read_until_closing_curly_brace, - read_until_semicolon_or_closing_curly_brace, - }, + utils::{read_until_closing_curly_brace, read_until_semicolon_or_closing_curly_brace}, value::Value, Options, {Cow, Token}, }; @@ -134,6 +131,16 @@ impl<'a> Parser<'a> { false } + pub fn expect_identifier(&mut self, ident: &'static str) -> SassResult<()> { + let this_ident = self.parse_identifier_no_interpolation(false)?; + self.span_before = this_ident.span; + if this_ident.node == ident { + return Ok(()); + } + + Err((format!("Expected \"{}\".", ident), self.span_before).into()) + } + fn parse_stmt(&mut self) -> SassResult> { let mut stmts = Vec::new(); while let Some(Token { kind, pos }) = self.toks.peek() { @@ -420,13 +427,11 @@ impl<'a> Parser<'a> { } } '!' => { - if peek_ident_no_interpolation(self.toks, false, self.span_before)?.node - == "optional" - { - self.toks.truncate_iterator_to_cursor(); + if from_fn { + self.expect_identifier("optional")?; optional = true; } else { - string.push('!'); + return Err(("expected \"{\".", tok.pos).into()); } } c => string.push(c), diff --git a/tests/extend.rs b/tests/extend.rs index 47d0ab1..2e162d0 100644 --- a/tests/extend.rs +++ b/tests/extend.rs @@ -1882,6 +1882,13 @@ test!( }", ":has(a >) b, :has(a >) :has(a >) :has(a >) b, :has(a >) :has(a >) :has(a >) b {\n color: red;\n}\n" ); +error!( + extend_optional_keyword_not_complete, + "a { + @extend a !opt; + }", + "Error: Expected \"optional\"." +); // todo: extend_loop (massive test) // todo: extend tests in folders diff --git a/tests/selectors.rs b/tests/selectors.rs index 64fb23d..e4a4dc5 100644 --- a/tests/selectors.rs +++ b/tests/selectors.rs @@ -712,3 +712,7 @@ error!( toplevel_parent_selector_after_element, "a&{}", "Error: \"&\" may only used at the beginning of a compound selector." ); +error!( + denies_optional_in_selector, + "a !optional {}", "Error: expected \"{\"." +);