Skip to content

Commit 1cd5223

Browse files
committed
refactor(frontmatter): Track spans for errors
1 parent 4334574 commit 1cd5223

File tree

2 files changed

+47
-22
lines changed

2 files changed

+47
-22
lines changed

src/cargo/util/frontmatter.rs

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,21 @@ impl<'s> ScriptSource<'s> {
6868
}
6969
1 | 2 => {
7070
// either not a frontmatter or invalid frontmatter opening
71-
return Err(FrontmatterError::new(format!(
72-
"found {fence_length} `{FENCE_CHAR}` in rust frontmatter, expected at least 3"
73-
)));
71+
return Err(FrontmatterError::new(
72+
format!(
73+
"found {fence_length} `{FENCE_CHAR}` in rust frontmatter, expected at least 3"
74+
),
75+
open_start..open_end,
76+
));
7477
}
7578
_ => {}
7679
}
7780
source.open = Some(open_start..open_end);
7881
let Some(info_nl) = input.find_slice("\n") else {
79-
return Err(FrontmatterError::new(format!(
80-
"no closing `{fence_pattern}` found for frontmatter"
81-
)));
82+
return Err(FrontmatterError::new(
83+
format!("no closing `{fence_pattern}` found for frontmatter"),
84+
open_start..open_end,
85+
));
8286
};
8387
let info = input.next_slice(info_nl.start);
8488
let info = info.trim_matches(is_whitespace);
@@ -91,9 +95,10 @@ impl<'s> ScriptSource<'s> {
9195
// Ends with a line that starts with a matching number of `-` only followed by whitespace
9296
let nl_fence_pattern = format!("\n{fence_pattern}");
9397
let Some(frontmatter_nl) = input.find_slice(nl_fence_pattern.as_str()) else {
94-
return Err(FrontmatterError::new(format!(
95-
"no closing `{fence_pattern}` found for frontmatter"
96-
)));
98+
return Err(FrontmatterError::new(
99+
format!("no closing `{fence_pattern}` found for frontmatter"),
100+
open_start..open_end,
101+
));
97102
};
98103
let frontmatter_start = input.current_token_start() + 1; // skip nl from infostring
99104
let _ = input.next_slice(frontmatter_nl.start + 1);
@@ -113,9 +118,10 @@ impl<'s> ScriptSource<'s> {
113118
let after_closing_fence = after_closing_fence.trim_matches(is_whitespace);
114119
if !after_closing_fence.is_empty() {
115120
// extra characters beyond the original fence pattern, even if they are extra `-`
116-
return Err(FrontmatterError::new(format!(
117-
"trailing characters found after frontmatter close"
118-
)));
121+
return Err(FrontmatterError::new(
122+
format!("trailing characters found after frontmatter close"),
123+
close_end..content_start,
124+
));
119125
}
120126

121127
source.content = content_start..content_end;
@@ -129,9 +135,12 @@ impl<'s> ScriptSource<'s> {
129135
.find_map(|(i, c)| (c != FENCE_CHAR).then_some(i))
130136
.unwrap_or_else(|| input.eof_offset());
131137
if 0 < fence_length {
132-
return Err(FrontmatterError::new(format!(
133-
"only one frontmatter is supported"
134-
)));
138+
let fence_start = input.current_token_start();
139+
let fence_end = fence_start + fence_length;
140+
return Err(FrontmatterError::new(
141+
format!("only one frontmatter is supported"),
142+
fence_start..fence_end,
143+
));
135144
}
136145

137146
Ok(source)
@@ -248,14 +257,24 @@ fn is_whitespace(c: char) -> bool {
248257
#[derive(Debug)]
249258
pub struct FrontmatterError {
250259
message: String,
260+
span: Span,
251261
}
252262

253263
impl FrontmatterError {
254-
pub fn new(message: impl Into<String>) -> Self {
264+
pub fn new(message: impl Into<String>, span: Span) -> Self {
255265
Self {
256266
message: message.into(),
267+
span,
257268
}
258269
}
270+
271+
pub fn message(&self) -> &str {
272+
self.message.as_str()
273+
}
274+
275+
pub fn span(&self) -> Span {
276+
self.span.clone()
277+
}
259278
}
260279

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

src/cargo/util/toml/embedded.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,19 @@ pub(super) fn expand_manifest(content: &str) -> Result<String, FrontmatterError>
1111
Some("cargo") | None => {}
1212
Some(other) => {
1313
if let Some(remainder) = other.strip_prefix("cargo,") {
14-
return Err(FrontmatterError::new(format!(
15-
"cargo does not support frontmatter infostring attributes like `{remainder}` at this time"
16-
)));
14+
return Err(FrontmatterError::new(
15+
format!(
16+
"cargo does not support frontmatter infostring attributes like `{remainder}` at this time"
17+
),
18+
source.info_span().unwrap(),
19+
));
1720
} else {
18-
return Err(FrontmatterError::new(format!(
19-
"frontmatter infostring `{other}` is unsupported by cargo; specify `cargo` for embedding a manifest"
20-
)));
21+
return Err(FrontmatterError::new(
22+
format!(
23+
"frontmatter infostring `{other}` is unsupported by cargo; specify `cargo` for embedding a manifest"
24+
),
25+
source.info_span().unwrap(),
26+
));
2127
}
2228
}
2329
}

0 commit comments

Comments
 (0)