fix: add better errors for missing commas in arrays and objects (#5210)

* fix: add better errors for missing commas in arrays and objects

* chore: add object prop shorthand missing comma test

* fix: wording on unexpected character in arrays and objects

* fix: don't eagerly evaluate whether there is a closing brace/bracket

* feat: exit early when detecting missing commas if encountering invalid tokens

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* fix: updated reserved word in test to replace removed one

---------

Co-authored-by: Tom Pridham <pridham.tom@gmail.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Jonathan Tran
2025-03-14 12:52:10 -04:00
committed by GitHub
parent 9e37e13b6b
commit 0229105158
3 changed files with 257 additions and 29 deletions

View File

@ -24,7 +24,6 @@ use crate::{
mod tokeniser;
#[cfg(test)]
pub(crate) use tokeniser::RESERVED_WORDS;
// Note the ordering, it's important that `m` comes after `mm` and `cm`.
@ -162,7 +161,9 @@ impl IntoIterator for TokenStream {
#[derive(Debug, Clone)]
pub(crate) struct TokenSlice<'a> {
stream: &'a TokenStream,
/// Current position of the leading Token in the stream
start: usize,
/// The number of total Tokens in the stream
end: usize,
}
@ -190,6 +191,21 @@ impl<'a> TokenSlice<'a> {
stream: self.stream,
}
}
pub fn as_source_range(&self) -> SourceRange {
let stream_len = self.stream.tokens.len();
let first_token = if stream_len == self.start {
&self.stream.tokens[self.start - 1]
} else {
self.token(0)
};
let last_token = if stream_len == self.end {
&self.stream.tokens[stream_len - 1]
} else {
self.token(self.end - self.start)
};
SourceRange::new(first_token.start, last_token.end, last_token.module_id)
}
}
impl<'a> IntoIterator for TokenSlice<'a> {
@ -294,6 +310,14 @@ impl<'a> winnow::stream::StreamIsPartial for TokenSlice<'a> {
}
}
impl<'a> winnow::stream::FindSlice<&str> for TokenSlice<'a> {
fn find_slice(&self, substr: &str) -> Option<std::ops::Range<usize>> {
self.iter()
.enumerate()
.find_map(|(i, b)| if b.value == substr { Some(i..self.end) } else { None })
}
}
#[derive(Clone, Debug)]
pub struct Checkpoint(usize, usize);