Unnamed repository; edit this file 'description' to name the repository.
feat: hint at unterminated strings in unknown prefix errors
When encountering 'unknown literal prefix' errors, check for unbalanced quotes in recent code and suggest checking for unterminated string literals.
Ralf Anton Beier 8 months ago
parent 92ba1cc · commit e7c3fe1
-rw-r--r--crates/parser/src/lexed_str.rs30
-rw-r--r--crates/parser/test_data/lexer/err/unterminated_string_unknown_prefix.rast15
-rw-r--r--crates/parser/test_data/lexer/err/unterminated_string_unknown_prefix.rs5
3 files changed, 49 insertions, 1 deletions
diff --git a/crates/parser/src/lexed_str.rs b/crates/parser/src/lexed_str.rs
index 8fff1c3db7..dcf397142c 100644
--- a/crates/parser/src/lexed_str.rs
+++ b/crates/parser/src/lexed_str.rs
@@ -149,6 +149,24 @@ impl<'a> Converter<'a> {
}
}
+ /// Check for likely unterminated string by analyzing STRING token content
+ fn has_likely_unterminated_string(&self) -> bool {
+ let Some(last_idx) = self.res.kind.len().checked_sub(1) else { return false };
+
+ for i in (0..=last_idx).rev().take(5) {
+ if self.res.kind[i] == STRING {
+ let start = self.res.start[i] as usize;
+ let end = self.res.start.get(i + 1).map(|&s| s as usize).unwrap_or(self.offset);
+ let content = &self.res.text[start..end];
+
+ if content.contains('(') && (content.contains("//") || content.contains(";\n")) {
+ return true;
+ }
+ }
+ }
+ false
+ }
+
fn finalize_with_eof(mut self) -> LexedStr<'a> {
self.res.push(EOF, self.offset);
self.res
@@ -267,7 +285,17 @@ impl<'a> Converter<'a> {
rustc_lexer::TokenKind::Unknown => ERROR,
rustc_lexer::TokenKind::UnknownPrefix if token_text == "builtin" => IDENT,
rustc_lexer::TokenKind::UnknownPrefix => {
- errors.push("unknown literal prefix".into());
+ let has_unterminated = self.has_likely_unterminated_string();
+
+ let error_msg = if has_unterminated {
+ format!(
+ "unknown literal prefix `{}` (note: check for unterminated string literal)",
+ token_text
+ )
+ } else {
+ "unknown literal prefix".to_owned()
+ };
+ errors.push(error_msg);
IDENT
}
rustc_lexer::TokenKind::Eof => EOF,
diff --git a/crates/parser/test_data/lexer/err/unterminated_string_unknown_prefix.rast b/crates/parser/test_data/lexer/err/unterminated_string_unknown_prefix.rast
new file mode 100644
index 0000000000..f7f24ca3f8
--- /dev/null
+++ b/crates/parser/test_data/lexer/err/unterminated_string_unknown_prefix.rast
@@ -0,0 +1,15 @@
+FN_KW "fn"
+WHITESPACE " "
+IDENT "main"
+L_PAREN "("
+R_PAREN ")"
+WHITESPACE " "
+L_CURLY "{"
+WHITESPACE "\n "
+IDENT "hello"
+L_PAREN "("
+STRING "\"world);\n // a bunch of code was here\n env(\"FLAGS"
+STRING "\", \""
+MINUS "-"
+IDENT "help" error: unknown literal prefix `help` (note: check for unterminated string literal)
+STRING "\")\n}" error: Missing trailing `"` symbol to terminate the string literal
diff --git a/crates/parser/test_data/lexer/err/unterminated_string_unknown_prefix.rs b/crates/parser/test_data/lexer/err/unterminated_string_unknown_prefix.rs
new file mode 100644
index 0000000000..338b958260
--- /dev/null
+++ b/crates/parser/test_data/lexer/err/unterminated_string_unknown_prefix.rs
@@ -0,0 +1,5 @@
+fn main() {
+ hello("world);
+ // a bunch of code was here
+ env("FLAGS", "-help")
+} \ No newline at end of file