add more tests for malformed @for

test for capitalization of keywords, error messages, and regression
tests for integer overflows resulting when `from` or `to` ==
`std::i32::MAX`
This commit is contained in:
Connor Skees 2020-08-07 16:21:15 -04:00
parent 38a37a3997
commit f33739aa0f
3 changed files with 99 additions and 11 deletions

View File

@ -156,7 +156,6 @@ impl<'a> Parser<'a> {
pub(super) fn parse_for(&mut self) -> SassResult<Vec<Stmt>> {
self.whitespace_or_comment();
// todo: test for error here
self.expect_char('$')?;
let var = self
@ -236,14 +235,16 @@ impl<'a> Parser<'a> {
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() {
Value::Dimension(Some(n), ..) => match n.to_i32() {
Some(std::i32::MAX) | None => {
return Err((format!("{} is not an int.", n), from_val.span).into())
}
Some(v) => v,
None => return Err((format!("{} is not a int.", n), from_val.span).into()),
},
Value::Dimension(None, ..) => todo!(),
Value::Dimension(None, ..) => return Err(("NaN is not an int.", from_val.span).into()),
v => {
return Err((
format!("{} is not an integer.", v.inspect(from_val.span)?),
format!("{} is not a number.", v.inspect(from_val.span)?),
from_val.span,
)
.into())
@ -252,14 +253,16 @@ impl<'a> Parser<'a> {
let to_val = self.parse_value(true, &|_| false)?;
let to = match to_val.node {
Value::Dimension(Some(n), ..) => match n.to_integer().to_isize() {
Value::Dimension(Some(n), ..) => match n.to_i32() {
Some(std::i32::MAX) | None => {
return Err((format!("{} is not an int.", n), to_val.span).into())
}
Some(v) => v,
None => return Err((format!("{} is not a int.", n), to_val.span).into()),
},
Value::Dimension(None, ..) => todo!(),
Value::Dimension(None, ..) => return Err(("NaN is not an int.", from_val.span).into()),
v => {
return Err((
format!("{} is not an integer.", v.to_css_string(to_val.span)?),
format!("{} is not a number.", v.to_css_string(to_val.span)?),
to_val.span,
)
.into())
@ -269,12 +272,13 @@ impl<'a> Parser<'a> {
self.expect_char('{')?;
let body = read_until_closing_curly_brace(self.toks)?;
self.toks.next();
self.expect_char('}')?;
let (mut x, mut y);
// we can't use an inclusive range here
#[allow(clippy::range_plus_one)]
let iter: &mut dyn Iterator<Item = isize> = if from < to {
let iter: &mut dyn Iterator<Item = i32> = if from < to {
x = from..(to + through);
&mut x
} else {

View File

@ -318,6 +318,42 @@ impl fmt::Debug for Number {
}
}
impl ToPrimitive for Number {
fn to_u64(&self) -> Option<u64> {
match self {
Self::Small(n) => {
if !n.denom().is_one() {
return None;
}
n.to_u64()
}
Self::Big(n) => {
if !n.denom().is_one() {
return None;
}
n.to_u64()
}
}
}
fn to_i64(&self) -> Option<i64> {
match self {
Self::Small(n) => {
if !n.denom().is_one() {
return None;
}
n.to_i64()
}
Self::Big(n) => {
if !n.denom().is_one() {
return None;
}
n.to_i64()
}
}
}
}
impl Display for Number {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut whole = self.to_integer().abs();

View File

@ -118,3 +118,51 @@ test!(
" /**/ @for /**/ $i /**/ from /**/ 0 /**/ to /**/ 2 /**/ {} /**/ ",
"/**/\n/**/\n"
);
test!(
uppercase_keywords,
"@for $i FROM 0 TO 2 {
@foo;
}",
"@foo;\n@foo;\n"
);
error!(
missing_keyword_from,
"@for $i fro", "Error: Expected \"from\"."
);
error!(missing_dollar_sign, "@for", "Error: expected \"$\".");
error!(
variable_missing_identifier,
"@for $", "Error: Expected identifier."
);
error!(
from_value_is_decimal,
"@for $i from 0.5 to 2 {}", "Error: 0.5 is not an int."
);
error!(
to_value_is_decimal,
"@for $i from 0 to 1.5 {}", "Error: 1.5 is not an int."
);
error!(
from_value_is_non_numeric,
"@for $i from red to 2 {}", "Error: red is not a number."
);
error!(
to_value_is_non_numeric,
"@for $i from 0 to red {}", "Error: red is not a number."
);
error!(
through_i32_max,
"@for $i from 0 through 2147483647 {}", "Error: 2147483647 is not an int."
);
error!(
from_i32_max,
"@for $i from 2147483647 through 0 {}", "Error: 2147483647 is not an int."
);
error!(
from_nan,
"@for $i from (0/0) through 0 {}", "Error: NaN is not an int."
);
error!(
to_nan,
"@for $i from 0 through (0/0) {}", "Error: NaN is not an int."
);