remove most remaining unwraps
This commit is contained in:
parent
de8e7048d8
commit
5fc3748472
@ -15,7 +15,10 @@ use super::Parser;
|
||||
impl<'a> Parser<'a> {
|
||||
pub(super) fn parse_func_args(&mut self) -> SassResult<FuncArgs> {
|
||||
let mut args: Vec<FuncArg> = Vec::new();
|
||||
let mut close_paren_span: Span = self.toks.peek().unwrap().pos();
|
||||
let mut close_paren_span: Span = match self.toks.peek() {
|
||||
Some(Token { pos, .. }) => *pos,
|
||||
None => return Err(("expected \")\".", self.span_before).into()),
|
||||
};
|
||||
|
||||
self.whitespace();
|
||||
while let Some(Token { kind, pos }) = self.toks.next() {
|
||||
@ -130,9 +133,10 @@ impl<'a> Parser<'a> {
|
||||
.ok_or(("expected \")\".", self.span_before))?
|
||||
.pos();
|
||||
loop {
|
||||
match self.toks.peek() {
|
||||
Some(Token { kind: '$', .. }) => {
|
||||
let Token { pos, .. } = self.toks.next().unwrap();
|
||||
match self.toks.peek().cloned() {
|
||||
Some(Token { kind: '$', pos }) => {
|
||||
span = span.merge(pos);
|
||||
self.toks.next();
|
||||
let v = self.parse_identifier_no_interpolation(false)?;
|
||||
let whitespace = self.whitespace_or_comment();
|
||||
if let Some(Token { kind: ':', .. }) = self.toks.peek() {
|
||||
|
@ -35,7 +35,10 @@ impl<'a> Parser<'a> {
|
||||
self.whitespace();
|
||||
|
||||
let mut body = read_until_closing_curly_brace(self.toks)?;
|
||||
body.push(self.toks.next().unwrap());
|
||||
body.push(match self.toks.next() {
|
||||
Some(tok) => tok,
|
||||
None => return Err(("expected \"}\".", self.span_before).into()),
|
||||
});
|
||||
self.whitespace();
|
||||
|
||||
let function = Function::new(self.scopes.last().clone(), args, body, span);
|
||||
|
@ -29,7 +29,10 @@ impl<'a> Parser<'a> {
|
||||
self.whitespace();
|
||||
|
||||
let mut body = read_until_closing_curly_brace(self.toks)?;
|
||||
body.push(self.toks.next().unwrap());
|
||||
body.push(match self.toks.next() {
|
||||
Some(tok) => tok,
|
||||
None => return Err(("expected \"}\".", self.span_before).into()),
|
||||
});
|
||||
|
||||
// todo: `@include` can only give content when `@content` is present within the body
|
||||
// if `@content` is *not* present and `@include` attempts to give a body, we throw an error
|
||||
|
@ -171,8 +171,9 @@ impl<'a> Parser<'a> {
|
||||
span,
|
||||
} = self.parse_value_from_vec(toks)?;
|
||||
span.merge(kind_string.span);
|
||||
if let Some(Token { kind: ';', .. }) = self.toks.peek() {
|
||||
kind_string.span.merge(self.toks.next().unwrap().pos());
|
||||
if let Some(Token { kind: ';', pos }) = self.toks.peek() {
|
||||
kind_string.span.merge(*pos);
|
||||
self.toks.next();
|
||||
}
|
||||
self.warn(&Spanned {
|
||||
node: message.to_css_string(span)?,
|
||||
@ -186,8 +187,9 @@ impl<'a> Parser<'a> {
|
||||
span,
|
||||
} = self.parse_value_from_vec(toks)?;
|
||||
span.merge(kind_string.span);
|
||||
if let Some(Token { kind: ';', .. }) = self.toks.peek() {
|
||||
kind_string.span.merge(self.toks.next().unwrap().pos());
|
||||
if let Some(Token { kind: ';', pos }) = self.toks.peek() {
|
||||
kind_string.span.merge(*pos);
|
||||
self.toks.next();
|
||||
}
|
||||
self.debug(&Spanned {
|
||||
node: message.inspect(span)?,
|
||||
@ -529,7 +531,11 @@ impl<'a> Parser<'a> {
|
||||
if let Some(tok) = self.toks.next() {
|
||||
self.whitespace();
|
||||
match tok.kind.to_ascii_lowercase() {
|
||||
'i' if self.toks.next().unwrap().kind.to_ascii_lowercase() == 'f' => {
|
||||
'i' if matches!(
|
||||
self.toks.peek(),
|
||||
Some(Token { kind: 'f', .. }) | Some(Token { kind: 'F', .. })
|
||||
) =>
|
||||
{
|
||||
self.toks.next();
|
||||
let cond = read_until_open_curly_brace(self.toks)?;
|
||||
self.toks.next();
|
||||
@ -610,10 +616,10 @@ impl<'a> Parser<'a> {
|
||||
_ => return Err(("expected \"$\".", self.span_before).into()),
|
||||
};
|
||||
self.whitespace();
|
||||
if self.toks.peek().is_none() {
|
||||
return Err(("Expected \"from\".", var.span).into());
|
||||
}
|
||||
self.span_before = self.toks.peek().unwrap().pos;
|
||||
self.span_before = match self.toks.peek() {
|
||||
Some(tok) => tok.pos,
|
||||
None => return Err(("Expected \"from\".", var.span).into()),
|
||||
};
|
||||
if self.parse_identifier()?.node.to_ascii_lowercase() != "from" {
|
||||
return Err(("Expected \"from\".", var.span).into());
|
||||
}
|
||||
@ -644,7 +650,10 @@ impl<'a> Parser<'a> {
|
||||
'{' => {
|
||||
return Err(("Expected \"to\" or \"through\".", tok.pos()).into());
|
||||
}
|
||||
_ => from_toks.push(self.toks.next().unwrap()),
|
||||
_ => {
|
||||
from_toks.push(tok);
|
||||
self.toks.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
self.whitespace();
|
||||
@ -766,7 +775,10 @@ impl<'a> Parser<'a> {
|
||||
|
||||
let mut body = read_until_closing_curly_brace(self.toks)?;
|
||||
|
||||
body.push(self.toks.next().unwrap());
|
||||
body.push(match self.toks.next() {
|
||||
Some(tok) => tok,
|
||||
None => return Err(("expected \"}\".", self.span_before).into()),
|
||||
});
|
||||
|
||||
self.whitespace();
|
||||
|
||||
@ -860,7 +872,10 @@ impl<'a> Parser<'a> {
|
||||
self.toks.next();
|
||||
self.whitespace();
|
||||
let mut body = read_until_closing_curly_brace(self.toks)?;
|
||||
body.push(self.toks.next().unwrap());
|
||||
body.push(match self.toks.next() {
|
||||
Some(tok) => tok,
|
||||
None => return Err(("expected \"}\".", self.span_before).into()),
|
||||
});
|
||||
self.whitespace();
|
||||
|
||||
let mut stmts = Vec::new();
|
||||
@ -1102,7 +1117,10 @@ impl<'a> Parser<'a> {
|
||||
self.whitespace();
|
||||
|
||||
let mut body = read_until_closing_curly_brace(self.toks)?;
|
||||
body.push(self.toks.next().unwrap());
|
||||
body.push(match self.toks.next() {
|
||||
Some(tok) => tok,
|
||||
None => return Err(("expected \"}\".", self.span_before).into()),
|
||||
});
|
||||
|
||||
self.whitespace();
|
||||
|
||||
|
@ -710,7 +710,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
fn peek_interpolation(&mut self) -> SassResult<(Spanned<Value>, usize)> {
|
||||
let vec = peek_until_closing_curly_brace(self.toks);
|
||||
let vec = peek_until_closing_curly_brace(self.toks)?;
|
||||
let peek_counter = vec.len();
|
||||
self.toks.move_forward(1);
|
||||
let val = self.parse_value_from_vec(vec)?;
|
||||
|
@ -51,11 +51,7 @@ pub(crate) fn eat_number<I: Iterator<Item = Token>>(
|
||||
) -> SassResult<Spanned<ParsedNumber>> {
|
||||
let mut whole = String::with_capacity(1);
|
||||
// TODO: merge this span with chars
|
||||
let span = if let Some(tok) = toks.peek() {
|
||||
tok.pos()
|
||||
} else {
|
||||
todo!()
|
||||
};
|
||||
let span = toks.peek().unwrap().pos;
|
||||
eat_whole_number(toks, &mut whole);
|
||||
|
||||
if toks.peek().is_none() {
|
||||
|
@ -8,19 +8,19 @@ use super::{as_hex, hex_char_for, is_name, is_name_start, IsWhitespace};
|
||||
|
||||
pub(crate) fn peek_until_closing_curly_brace<I: Iterator<Item = Token>>(
|
||||
toks: &mut PeekMoreIterator<I>,
|
||||
) -> Vec<Token> {
|
||||
) -> SassResult<Vec<Token>> {
|
||||
let mut t = Vec::new();
|
||||
let mut nesting = 0;
|
||||
while let Some(tok) = toks.peek() {
|
||||
while let Some(tok) = toks.peek().cloned() {
|
||||
match tok.kind {
|
||||
q @ '"' | q @ '\'' => {
|
||||
t.push(*toks.peek().unwrap());
|
||||
t.push(tok);
|
||||
toks.move_forward(1);
|
||||
t.extend(peek_until_closing_quote(toks, q));
|
||||
t.extend(peek_until_closing_quote(toks, q)?);
|
||||
}
|
||||
'{' => {
|
||||
nesting += 1;
|
||||
t.push(*toks.peek().unwrap());
|
||||
t.push(tok);
|
||||
toks.move_forward(1);
|
||||
}
|
||||
'}' => {
|
||||
@ -28,62 +28,71 @@ pub(crate) fn peek_until_closing_curly_brace<I: Iterator<Item = Token>>(
|
||||
break;
|
||||
} else {
|
||||
nesting -= 1;
|
||||
t.push(*toks.peek().unwrap());
|
||||
t.push(tok);
|
||||
toks.move_forward(1);
|
||||
}
|
||||
}
|
||||
'/' => {
|
||||
let next = *toks.peek_forward(1).unwrap();
|
||||
match toks.peek().unwrap().kind {
|
||||
'/' => peek_until_newline(toks),
|
||||
let next = *toks
|
||||
.peek_forward(1)
|
||||
.ok_or(("Expected expression.", tok.pos))?;
|
||||
match toks.peek() {
|
||||
Some(Token { kind: '/', .. }) => peek_until_newline(toks),
|
||||
_ => t.push(next),
|
||||
};
|
||||
continue;
|
||||
}
|
||||
_ => {
|
||||
t.push(*toks.peek().unwrap());
|
||||
t.push(tok);
|
||||
toks.move_forward(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
peek_whitespace(toks);
|
||||
t
|
||||
Ok(t)
|
||||
}
|
||||
|
||||
fn peek_until_closing_quote<I: Iterator<Item = Token>>(
|
||||
toks: &mut PeekMoreIterator<I>,
|
||||
q: char,
|
||||
) -> Vec<Token> {
|
||||
) -> SassResult<Vec<Token>> {
|
||||
let mut t = Vec::new();
|
||||
while let Some(tok) = toks.peek() {
|
||||
while let Some(tok) = toks.peek().cloned() {
|
||||
match tok.kind {
|
||||
'"' if q == '"' => {
|
||||
t.push(*tok);
|
||||
t.push(tok);
|
||||
toks.move_forward(1);
|
||||
break;
|
||||
}
|
||||
'\'' if q == '\'' => {
|
||||
t.push(*tok);
|
||||
t.push(tok);
|
||||
toks.move_forward(1);
|
||||
break;
|
||||
}
|
||||
'\\' => {
|
||||
t.push(*tok);
|
||||
t.push(*toks.peek_forward(1).unwrap());
|
||||
t.push(tok);
|
||||
t.push(match toks.peek_forward(1) {
|
||||
Some(tok) => *tok,
|
||||
None => return Err((format!("Expected {}.", q), tok.pos).into()),
|
||||
});
|
||||
}
|
||||
'#' => {
|
||||
t.push(*tok);
|
||||
let next = toks.peek().unwrap();
|
||||
t.push(tok);
|
||||
let next = match toks.peek() {
|
||||
Some(tok) => tok,
|
||||
None => return Err((format!("Expected {}.", q), tok.pos).into()),
|
||||
};
|
||||
if next.kind == '{' {
|
||||
t.push(*toks.peek_forward(1).unwrap());
|
||||
t.append(&mut peek_until_closing_curly_brace(toks));
|
||||
t.push(*next);
|
||||
toks.peek_forward(1);
|
||||
t.append(&mut peek_until_closing_curly_brace(toks)?);
|
||||
}
|
||||
}
|
||||
_ => t.push(*tok),
|
||||
_ => t.push(tok),
|
||||
}
|
||||
toks.move_forward(1);
|
||||
}
|
||||
t
|
||||
Ok(t)
|
||||
}
|
||||
|
||||
fn peek_until_newline<I: Iterator<Item = Token>>(toks: &mut PeekMoreIterator<I>) {
|
||||
@ -166,13 +175,13 @@ pub(crate) fn peek_ident_no_interpolation<I: Iterator<Item = Token>>(
|
||||
.ok_or(("Expected identifier.", span_before))?
|
||||
.pos();
|
||||
let mut text = String::new();
|
||||
if toks.peek().unwrap().kind == '-' {
|
||||
if let Some(Token { kind: '-', .. }) = toks.peek() {
|
||||
toks.peek_forward(1);
|
||||
text.push('-');
|
||||
if toks.peek().is_none() {
|
||||
return Ok(Spanned { node: text, span });
|
||||
}
|
||||
if toks.peek().unwrap().kind == '-' {
|
||||
if let Some(Token { kind: '-', .. }) = toks.peek() {
|
||||
toks.peek_forward(1);
|
||||
text.push('-');
|
||||
text.push_str(&peek_ident_body_no_interpolation(toks, unit, span)?.node);
|
||||
|
@ -28,10 +28,10 @@ pub(crate) fn read_until_open_curly_brace<I: Iterator<Item = Token>>(
|
||||
}
|
||||
'\\' => {
|
||||
t.push(toks.next().unwrap());
|
||||
if toks.peek().is_some() {
|
||||
t.push(toks.next().unwrap());
|
||||
}
|
||||
continue;
|
||||
t.push(match toks.next() {
|
||||
Some(tok) => tok,
|
||||
None => continue,
|
||||
});
|
||||
}
|
||||
q @ '"' | q @ '\'' => {
|
||||
t.push(toks.next().unwrap());
|
||||
@ -89,9 +89,10 @@ pub(crate) fn read_until_closing_curly_brace<I: Iterator<Item = Token>>(
|
||||
}
|
||||
'\\' => {
|
||||
t.push(toks.next().unwrap());
|
||||
if toks.peek().is_some() {
|
||||
t.push(toks.next().unwrap());
|
||||
}
|
||||
t.push(match toks.next() {
|
||||
Some(tok) => tok,
|
||||
None => continue,
|
||||
});
|
||||
}
|
||||
_ => t.push(toks.next().unwrap()),
|
||||
}
|
||||
@ -120,16 +121,21 @@ pub(crate) fn read_until_closing_quote<I: Iterator<Item = Token>>(
|
||||
}
|
||||
'\\' => {
|
||||
t.push(tok);
|
||||
if toks.peek().is_some() {
|
||||
t.push(toks.next().unwrap());
|
||||
}
|
||||
t.push(match toks.next() {
|
||||
Some(tok) => tok,
|
||||
None => return Err((format!("Expected {}.", q), tok.pos).into()),
|
||||
});
|
||||
}
|
||||
'#' => {
|
||||
t.push(tok);
|
||||
let next = toks.peek().unwrap();
|
||||
if next.kind == '{' {
|
||||
t.push(toks.next().unwrap());
|
||||
t.append(&mut read_until_closing_curly_brace(toks)?);
|
||||
match toks.peek() {
|
||||
Some(tok @ Token { kind: '{', .. }) => {
|
||||
t.push(*tok);
|
||||
toks.next();
|
||||
t.append(&mut read_until_closing_curly_brace(toks)?);
|
||||
}
|
||||
Some(..) => continue,
|
||||
None => return Err((format!("Expected {}.", q), tok.pos).into()),
|
||||
}
|
||||
}
|
||||
_ => t.push(tok),
|
||||
@ -156,9 +162,10 @@ pub(crate) fn read_until_semicolon_or_closing_curly_brace<I: Iterator<Item = Tok
|
||||
}
|
||||
'\\' => {
|
||||
t.push(toks.next().unwrap());
|
||||
if toks.peek().is_some() {
|
||||
t.push(toks.next().unwrap());
|
||||
}
|
||||
t.push(match toks.next() {
|
||||
Some(tok) => tok,
|
||||
None => continue,
|
||||
});
|
||||
}
|
||||
'"' | '\'' => {
|
||||
let quote = toks.next().unwrap();
|
||||
@ -217,11 +224,11 @@ pub(crate) fn read_until_closing_paren<I: Iterator<Item = Token>>(
|
||||
continue;
|
||||
}
|
||||
'\\' => {
|
||||
t.push(tok);
|
||||
if toks.peek().is_some() {
|
||||
t.push(toks.next().unwrap());
|
||||
}
|
||||
continue;
|
||||
t.push(toks.next().unwrap());
|
||||
t.push(match toks.next() {
|
||||
Some(tok) => tok,
|
||||
None => continue,
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@ -253,10 +260,11 @@ pub(crate) fn read_until_closing_square_brace<I: Iterator<Item = Token>>(
|
||||
continue;
|
||||
}
|
||||
'\\' => {
|
||||
t.push(tok);
|
||||
if toks.peek().is_some() {
|
||||
t.push(toks.next().unwrap());
|
||||
}
|
||||
t.push(toks.next().unwrap());
|
||||
t.push(match toks.next() {
|
||||
Some(tok) => tok,
|
||||
None => continue,
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ impl Value {
|
||||
Self::List(vals, sep, brackets) => match brackets {
|
||||
Brackets::None => Cow::owned(
|
||||
vals.iter()
|
||||
.filter(|x| !x.clone().is_null(span).unwrap_or(false))
|
||||
.filter(|x| !x.is_null(span).unwrap_or(false))
|
||||
.map(|x| x.to_css_string(span))
|
||||
.collect::<SassResult<Vec<Cow<'static, str>>>>()?
|
||||
.join(sep.as_str()),
|
||||
|
@ -46,7 +46,11 @@ test!(
|
||||
"a {\n color: 2;\n}\n"
|
||||
);
|
||||
error!(
|
||||
#[ignore = "does not fail"]
|
||||
#[ignore = "expects incorrect char, '{'"]
|
||||
nothing_after_open,
|
||||
"a { color:rgb(; }", "Error: expected \")\"."
|
||||
);
|
||||
error!(
|
||||
nothing_after_open_paren_in_fn_args,
|
||||
"@function foo(", "Error: expected \")\"."
|
||||
);
|
||||
|
@ -68,3 +68,7 @@ test!(
|
||||
"a {}\n\n@at-root {\n @-ms-viewport { width: device-width; }\n}\n",
|
||||
"@-ms-viewport {\n width: device-width;\n}\n"
|
||||
);
|
||||
error!(
|
||||
missing_closing_curly_brace,
|
||||
"@at-root {", "Error: expected \"}\"."
|
||||
);
|
||||
|
@ -48,3 +48,7 @@ test!(
|
||||
"a {\n @each $i in 1 2 3 {\n color: type-of($i);\n }\n}\n",
|
||||
"a {\n color: number;\n color: number;\n color: number;\n}\n"
|
||||
);
|
||||
error!(
|
||||
missing_closing_curly_brace,
|
||||
"@each $i in 1 {", "Error: expected \"}\"."
|
||||
);
|
||||
|
@ -95,3 +95,7 @@ error!(
|
||||
double_comma_args,
|
||||
"@function foo($a,$b,,) {}", "Error: expected \")\"."
|
||||
);
|
||||
error!(
|
||||
body_missing_closing_curly_brace,
|
||||
"@function foo() {", "Error: expected \"}\"."
|
||||
);
|
||||
|
@ -149,3 +149,7 @@ error!(unclosed_sgl_quote, "@if true ' {}", "Error: Expected '.");
|
||||
error!(unclosed_call_args, "@if a({}", "Error: expected \")\".");
|
||||
error!(nothing_after_div, "@if a/", "Error: Expected expression.");
|
||||
error!(multiline_error, "@if \"\n\"{}", "Error: Expected \".");
|
||||
error!(
|
||||
nothing_after_i_after_else,
|
||||
"@if true {} @else i", "Error: expected \"{\"."
|
||||
);
|
||||
|
@ -233,6 +233,10 @@ error!(
|
||||
undefined_mixin,
|
||||
"a {@include foo;}", "Error: Undefined mixin."
|
||||
);
|
||||
error!(
|
||||
body_missing_closing_curly_brace,
|
||||
"@mixin foo() {", "Error: expected \"}\"."
|
||||
);
|
||||
test!(
|
||||
include_empty_args_no_semicolon,
|
||||
"@mixin c {}\n\na {\n @include c()\n}\n",
|
||||
|
12
tests/url.rs
12
tests/url.rs
@ -134,3 +134,15 @@ test!(
|
||||
"a {\n color: UrL(http://foo);\n}\n",
|
||||
"a {\n color: url(http://foo);\n}\n"
|
||||
);
|
||||
error!(
|
||||
url_nothing_after_forward_slash_in_interpolation,
|
||||
"a { color: url(#{/", "Error: Expected expression."
|
||||
);
|
||||
error!(
|
||||
url_nothing_after_backslash_in_interpolation_in_quote,
|
||||
"a { color: url(#{\"\\", "Error: Expected \"."
|
||||
);
|
||||
error!(
|
||||
url_nothing_after_hash_in_interpolation_in_quote,
|
||||
"a { color: url(#{\"#", "Error: Expected \"."
|
||||
);
|
||||
|
@ -107,7 +107,6 @@ test!(
|
||||
}",
|
||||
"result {\n root_default: initial;\n root_implicit: inner;\n root_explicit: inner;\n}\n"
|
||||
);
|
||||
|
||||
test!(
|
||||
if_inside_while,
|
||||
"$continue_outer: true;
|
||||
@ -126,3 +125,7 @@ test!(
|
||||
}",
|
||||
"a {\n color: red;\n}\n\na {\n color: blue;\n}\n"
|
||||
);
|
||||
error!(
|
||||
missing_closing_curly_brace,
|
||||
"@while true {", "Error: expected \"}\"."
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user