Skip to content

Commit 5b4d0cf

Browse files
committed
fix(frontmatter): Add more visible context to errors
1 parent 640e12c commit 5b4d0cf

18 files changed

+95
-37
lines changed

src/cargo/util/frontmatter.rs

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -72,17 +72,18 @@ impl<'s> ScriptSource<'s> {
7272
format!(
7373
"found {fence_length} `{FENCE_CHAR}` in rust frontmatter, expected at least 3"
7474
),
75-
open_start..open_end,
76-
));
75+
raw.len()..raw.len(),
76+
).push_visible_span(open_start..open_end));
7777
}
7878
_ => {}
7979
}
8080
source.open = Some(open_start..open_end);
8181
let Some(info_nl) = input.find_slice("\n") else {
8282
return Err(FrontmatterError::new(
8383
format!("unclosed frontmatter; expected `{fence_pattern}`"),
84-
open_start..open_end,
85-
));
84+
raw.len()..raw.len(),
85+
)
86+
.push_visible_span(open_start..open_end));
8687
};
8788
let info = input.next_slice(info_nl.start);
8889
let info = info.trim_matches(is_whitespace);
@@ -109,12 +110,14 @@ impl<'s> ScriptSource<'s> {
109110
"closing code fence has {fewer_dashes} less `-` than the opening fence"
110111
),
111112
close_start..close_end,
112-
));
113+
)
114+
.push_visible_span(open_start..open_end));
113115
}
114116
return Err(FrontmatterError::new(
115117
format!("unclosed frontmatter; expected `{fence_pattern}`"),
116-
open_start..open_end,
117-
));
118+
raw.len()..raw.len(),
119+
)
120+
.push_visible_span(open_start..open_end));
118121
};
119122
let frontmatter_start = input.current_token_start() + 1; // skip nl from infostring
120123
let _ = input.next_slice(frontmatter_nl.start + 1);
@@ -141,15 +144,17 @@ impl<'s> ScriptSource<'s> {
141144
return Err(FrontmatterError::new(
142145
format!("closing code fence has {extra_dashes} more `-` than the opening fence"),
143146
extra_start..extra_end,
144-
));
147+
)
148+
.push_visible_span(open_start..open_end));
145149
} else {
146150
let after_closing_fence = after_closing_fence.trim_matches(is_whitespace);
147151
if !after_closing_fence.is_empty() {
148152
// extra characters beyond the original fence pattern
149153
return Err(FrontmatterError::new(
150154
format!("unexpected characters after frontmatter close"),
151155
close_end..content_start,
152-
));
156+
)
157+
.push_visible_span(open_start..open_end));
153158
}
154159
}
155160

@@ -169,7 +174,9 @@ impl<'s> ScriptSource<'s> {
169174
return Err(FrontmatterError::new(
170175
format!("only one frontmatter is supported"),
171176
fence_start..fence_end,
172-
));
177+
)
178+
.push_visible_span(open_start..open_end)
179+
.push_visible_span(close_start..close_end));
173180
}
174181

175182
Ok(source)
@@ -287,23 +294,34 @@ fn is_whitespace(c: char) -> bool {
287294
pub struct FrontmatterError {
288295
message: String,
289296
primary_span: Span,
297+
visible_spans: Vec<Span>,
290298
}
291299

292300
impl FrontmatterError {
293301
pub fn new(message: impl Into<String>, span: Span) -> Self {
294302
Self {
295303
message: message.into(),
296304
primary_span: span,
305+
visible_spans: Vec::new(),
297306
}
298307
}
299308

309+
pub fn push_visible_span(mut self, span: Span) -> Self {
310+
self.visible_spans.push(span);
311+
self
312+
}
313+
300314
pub fn message(&self) -> &str {
301315
self.message.as_str()
302316
}
303317

304318
pub fn primary_span(&self) -> Span {
305319
self.primary_span.clone()
306320
}
321+
322+
pub fn visible_spans(&self) -> &[Span] {
323+
&self.visible_spans
324+
}
307325
}
308326

309327
impl std::fmt::Display for FrontmatterError {

src/cargo/util/toml/embedded.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,20 @@ pub(super) fn expand_manifest(content: &str) -> Result<String, FrontmatterError>
1111
Some("cargo") | None => {}
1212
Some(other) => {
1313
let info_span = source.info_span().unwrap();
14+
let close_span = source.close_span().unwrap();
1415
if let Some(remainder) = other.strip_prefix("cargo,") {
1516
return Err(FrontmatterError::new(
1617
format!("unsupported frontmatter infostring attributes: `{remainder}`"),
1718
info_span,
18-
));
19+
)
20+
.push_visible_span(close_span));
1921
} else {
2022
return Err(FrontmatterError::new(
2123
format!(
2224
"unsupported frontmatter infostring `{other}`; specify `cargo` for embedding a manifest"
2325
),
2426
info_span,
25-
));
27+
).push_visible_span(close_span));
2628
}
2729
}
2830
}

src/cargo/util/toml/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2793,7 +2793,12 @@ fn emit_frontmatter_diagnostic(
27932793
let group = Group::with_title(Level::ERROR.primary_title(e.message())).element(
27942794
Snippet::source(contents)
27952795
.path(manifest_path)
2796-
.annotation(AnnotationKind::Primary.span(primary_span)),
2796+
.annotation(AnnotationKind::Primary.span(primary_span))
2797+
.annotations(
2798+
e.visible_spans()
2799+
.iter()
2800+
.map(|s| AnnotationKind::Visible.span(s.clone())),
2801+
),
27972802
);
27982803

27992804
if let Err(err) = gctx.shell().print_report(&[group], true) {

tests/testsuite/script/rustc_fixtures/dot-in-infostring-leading.stderr

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@
33
|
44
1 | ---.toml
55
| ^^^^^
6+
2 | //~^ ERROR: invalid infostring for frontmatter
7+
3 | ---
8+
|

tests/testsuite/script/rustc_fixtures/dot-in-infostring-non-leading.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@
33
|
44
1 | ---Cargo.toml
55
| ^^^^^^^^^^
6+
2 | ---
7+
|

tests/testsuite/script/rustc_fixtures/extra-after-end.stderr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
[ERROR] unexpected characters after frontmatter close
22
--> script:2:4
33
|
4+
1 | ---
45
2 | ---cargo
56
| ____^
67
3 | | //~^ ERROR: extra characters after frontmatter close are not allowed
Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
[ERROR] unclosed frontmatter; expected `---`
2-
--> script:1:1
3-
|
4-
1 | ---cargo
5-
| ^^^
2+
--> script:14:56
3+
|
4+
1 | ---cargo
5+
...
6+
14 | // within them and get treated as a frontmatter close.
7+
| ^

tests/testsuite/script/rustc_fixtures/hyphen-in-infostring-leading.stderr

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@
33
|
44
1 | --- -toml
55
| ^^^^^
6+
2 | //~^ ERROR: invalid infostring for frontmatter
7+
3 | ---
8+
|

tests/testsuite/script/rustc_fixtures/hyphen-in-infostring-non-leading.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@
33
|
44
1 | --- Cargo-toml
55
| ^^^^^^^^^^
6+
2 | ---
7+
|

tests/testsuite/script/rustc_fixtures/infostring-fail.stderr

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@
33
|
44
1 | ---cargo,clippy
55
| ^^^^^^^^^^^^
6+
2 | //~^ ERROR: invalid infostring for frontmatter
7+
3 | ---
8+
|

0 commit comments

Comments
 (0)