Skip to content

Commit ebfcffd

Browse files
authored
Improve error message for missing delimiter at EOF (#1590)
* Improve error message for missing delimiter at EOF Due to the way source maps worked the span would point to the wrong file if the marker was pointing at the end of a file. While this still isn't necessarily a perfect error message it should be a significant improvement over before by actually pointing to the incorrect file. Closes #1583 * Update test expectation * Fix span calculation for eof * Re-bless test output
1 parent 7a7815f commit ebfcffd

File tree

5 files changed

+35
-10
lines changed

5 files changed

+35
-10
lines changed

crates/wit-parser/src/ast.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,10 +1385,7 @@ fn err_expected(
13851385
format!("expected {}, found {}", expected, token.describe()),
13861386
),
13871387
None => Error::new(
1388-
Span {
1389-
start: u32::try_from(tokens.input().len()).unwrap(),
1390-
end: u32::try_from(tokens.input().len()).unwrap(),
1391-
},
1388+
tokens.eof_span(),
13921389
format!("expected {}, found eof", expected),
13931390
),
13941391
}
@@ -1519,7 +1516,13 @@ impl SourceMap {
15191516
/// interfaces and worlds defined together. Note that each file has its own
15201517
/// personal namespace, however, for top-level `use` and such.
15211518
pub fn push(&mut self, path: &Path, contents: impl Into<String>) {
1522-
let contents = contents.into();
1519+
let mut contents = contents.into();
1520+
// Guarantee that there's at least one character in these contents by
1521+
// appending a single newline to the end. This is excluded from
1522+
// tokenization below so it's only here to ensure that spans which point
1523+
// one byte beyond the end of a file (eof) point to the same original
1524+
// file.
1525+
contents.push('\n');
15231526
let new_offset = self.offset + u32::try_from(contents.len()).unwrap();
15241527
self.sources.push(Source {
15251528
offset: self.offset,
@@ -1537,7 +1540,9 @@ impl SourceMap {
15371540
srcs.sort_by_key(|src| &src.path);
15381541
for src in srcs {
15391542
let mut tokens = Tokenizer::new(
1540-
&src.contents,
1543+
// chop off the forcibly appended `\n` character when
1544+
// passing through the source to get tokenized.
1545+
&src.contents[..src.contents.len() - 1],
15411546
src.offset,
15421547
self.require_semicolons,
15431548
self.require_f32_f64,

crates/wit-parser/src/ast/lex.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,10 +162,6 @@ impl<'a> Tokenizer<'a> {
162162
Ok(())
163163
}
164164

165-
pub fn input(&self) -> &'a str {
166-
self.input
167-
}
168-
169165
pub fn get_span(&self, span: Span) -> &'a str {
170166
let start = usize::try_from(span.start - self.span_offset).unwrap();
171167
let end = usize::try_from(span.end - self.span_offset).unwrap();
@@ -395,6 +391,11 @@ impl<'a> Tokenizer<'a> {
395391
_ => false,
396392
}
397393
}
394+
395+
pub fn eof_span(&self) -> Span {
396+
let end = self.span_offset + u32::try_from(self.input.len()).unwrap();
397+
Span { start: end, end }
398+
}
398399
}
399400

400401
impl<'a> Iterator for CrlfFold<'a> {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
failed to resolve directory while parsing WIT for path [tests/ui/parse-fail/multi-file-missing-delimiter]
2+
3+
Caused by:
4+
0: failed to parse package: tests/ui/parse-fail/multi-file-missing-delimiter
5+
1: expected `type`, `resource` or `func`, found eof
6+
--> tests/ui/parse-fail/multi-file-missing-delimiter/observe.wit:6:1
7+
|
8+
6 |
9+
| ^
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
interface observe {
2+
record bar {
3+
a : string,
4+
}
5+
// NB: intentionally missing a delimiter at the end of the file
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package qux:qaz@2.0.0;
2+
3+
world platform {
4+
import observe;
5+
}

0 commit comments

Comments
 (0)