mirror of
https://github.com/rust-lang/cargo.git
synced 2025-09-25 11:14:46 +00:00
fix(frontmatter): Improve error quality (#15972)
### What does this PR try to resolve? The wording for our errors was indirect and things weren't as clear without more context. ### How to test and review this PR? ### Notes Example of rustc's versions of these errors: 1 > ``` > error: unclosed frontmatter > --> $DIR/frontmatter-whitespace-2.rs:1:1 > | > LL | / ---cargo > ... | > LL | | > | |_^ > | > note: frontmatter opening here was not closed > --> $DIR/frontmatter-whitespace-2.rs:1:1 > | > LL | ---cargo > | ^^^ > ``` 2 > ``` > error: extra characters after frontmatter close are not allowed > --> $DIR/extra-after-end.rs:2:1 > | > LL | ---cargo > | ^^^^^^^^ > ``` 3 > ``` > error: frontmatter close does not match the opening > --> $DIR/mismatch-1.rs:1:1 > | > LL | ---cargo > | ^-- > | | > | _the opening here has 3 dashes... > | | > LL | | > LL | | ---- > | |_---^ > | | > | ...while the close has 4 dashes > ```
This commit is contained in:
commit
966f94733b
@ -72,17 +72,18 @@ impl<'s> ScriptSource<'s> {
|
||||
format!(
|
||||
"found {fence_length} `{FENCE_CHAR}` in rust frontmatter, expected at least 3"
|
||||
),
|
||||
open_start..open_end,
|
||||
));
|
||||
raw.len()..raw.len(),
|
||||
).push_visible_span(open_start..open_end));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
source.open = Some(open_start..open_end);
|
||||
let Some(info_nl) = input.find_slice("\n") else {
|
||||
return Err(FrontmatterError::new(
|
||||
format!("no closing `{fence_pattern}` found for frontmatter"),
|
||||
open_start..open_end,
|
||||
));
|
||||
format!("unclosed frontmatter; expected `{fence_pattern}`"),
|
||||
raw.len()..raw.len(),
|
||||
)
|
||||
.push_visible_span(open_start..open_end));
|
||||
};
|
||||
let info = input.next_slice(info_nl.start);
|
||||
let info = info.trim_matches(is_whitespace);
|
||||
@ -103,15 +104,20 @@ impl<'s> ScriptSource<'s> {
|
||||
let close_start = input.current_token_start();
|
||||
let _ = input.next_slice(len);
|
||||
let close_end = input.current_token_start();
|
||||
let fewer_dashes = fence_length - len;
|
||||
return Err(FrontmatterError::new(
|
||||
format!("closing code fence has too few `-`"),
|
||||
format!(
|
||||
"closing code fence has {fewer_dashes} less `-` than the opening fence"
|
||||
),
|
||||
close_start..close_end,
|
||||
));
|
||||
)
|
||||
.push_visible_span(open_start..open_end));
|
||||
}
|
||||
return Err(FrontmatterError::new(
|
||||
format!("no closing `{fence_pattern}` found for frontmatter"),
|
||||
open_start..open_end,
|
||||
));
|
||||
format!("unclosed frontmatter; expected `{fence_pattern}`"),
|
||||
raw.len()..raw.len(),
|
||||
)
|
||||
.push_visible_span(open_start..open_end));
|
||||
};
|
||||
let frontmatter_start = input.current_token_start() + 1; // skip nl from infostring
|
||||
let _ = input.next_slice(frontmatter_nl.start + 1);
|
||||
@ -128,13 +134,30 @@ impl<'s> ScriptSource<'s> {
|
||||
.unwrap_or_else(|| input.eof_offset()),
|
||||
);
|
||||
let content_start = input.current_token_start();
|
||||
let after_closing_fence = after_closing_fence.trim_matches(is_whitespace);
|
||||
if !after_closing_fence.is_empty() {
|
||||
// extra characters beyond the original fence pattern, even if they are extra `-`
|
||||
let extra_dashes = after_closing_fence
|
||||
.chars()
|
||||
.take_while(|b| *b == FENCE_CHAR)
|
||||
.count();
|
||||
if 0 < extra_dashes {
|
||||
let extra_start = close_end;
|
||||
let extra_end = extra_start + extra_dashes;
|
||||
return Err(FrontmatterError::new(
|
||||
format!("trailing characters found after frontmatter close"),
|
||||
close_end..content_start,
|
||||
));
|
||||
format!("closing code fence has {extra_dashes} more `-` than the opening fence"),
|
||||
extra_start..extra_end,
|
||||
)
|
||||
.push_visible_span(open_start..open_end));
|
||||
} else {
|
||||
let after_closing_fence = after_closing_fence.trim_matches(is_whitespace);
|
||||
if !after_closing_fence.is_empty() {
|
||||
// extra characters beyond the original fence pattern
|
||||
let after_start = after_closing_fence.offset_from(&raw);
|
||||
let after_end = after_start + after_closing_fence.len();
|
||||
return Err(FrontmatterError::new(
|
||||
format!("unexpected characters after frontmatter close"),
|
||||
after_start..after_end,
|
||||
)
|
||||
.push_visible_span(open_start..open_end));
|
||||
}
|
||||
}
|
||||
|
||||
source.content = content_start..content_end;
|
||||
@ -153,7 +176,9 @@ impl<'s> ScriptSource<'s> {
|
||||
return Err(FrontmatterError::new(
|
||||
format!("only one frontmatter is supported"),
|
||||
fence_start..fence_end,
|
||||
));
|
||||
)
|
||||
.push_visible_span(open_start..open_end)
|
||||
.push_visible_span(close_start..close_end));
|
||||
}
|
||||
|
||||
Ok(source)
|
||||
@ -270,23 +295,34 @@ fn is_whitespace(c: char) -> bool {
|
||||
#[derive(Debug)]
|
||||
pub struct FrontmatterError {
|
||||
message: String,
|
||||
span: Span,
|
||||
primary_span: Span,
|
||||
visible_spans: Vec<Span>,
|
||||
}
|
||||
|
||||
impl FrontmatterError {
|
||||
pub fn new(message: impl Into<String>, span: Span) -> Self {
|
||||
Self {
|
||||
message: message.into(),
|
||||
span,
|
||||
primary_span: span,
|
||||
visible_spans: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push_visible_span(mut self, span: Span) -> Self {
|
||||
self.visible_spans.push(span);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn message(&self) -> &str {
|
||||
self.message.as_str()
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Span {
|
||||
self.span.clone()
|
||||
pub fn primary_span(&self) -> Span {
|
||||
self.primary_span.clone()
|
||||
}
|
||||
|
||||
pub fn visible_spans(&self) -> &[Span] {
|
||||
&self.visible_spans
|
||||
}
|
||||
}
|
||||
|
||||
@ -584,7 +620,7 @@ content: "\nfn main() {}\n"
|
||||
fn main() {}
|
||||
"#,
|
||||
),
|
||||
str!["trailing characters found after frontmatter close"],
|
||||
str!["closing code fence has 2 more `-` than the opening fence"],
|
||||
);
|
||||
}
|
||||
|
||||
@ -621,7 +657,7 @@ time="0.1.25"
|
||||
fn main() {}
|
||||
"#,
|
||||
),
|
||||
str!["trailing characters found after frontmatter close"],
|
||||
str!["closing code fence has 1 more `-` than the opening fence"],
|
||||
);
|
||||
}
|
||||
|
||||
@ -636,7 +672,7 @@ time="0.1.25"
|
||||
fn main() {}
|
||||
"#,
|
||||
),
|
||||
str!["no closing `---` found for frontmatter"],
|
||||
str!["unclosed frontmatter; expected `---`"],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -10,20 +10,21 @@ pub(super) fn expand_manifest(content: &str) -> Result<String, FrontmatterError>
|
||||
match source.info() {
|
||||
Some("cargo") | None => {}
|
||||
Some(other) => {
|
||||
let info_span = source.info_span().unwrap();
|
||||
let close_span = source.close_span().unwrap();
|
||||
if let Some(remainder) = other.strip_prefix("cargo,") {
|
||||
return Err(FrontmatterError::new(
|
||||
format!(
|
||||
"cargo does not support frontmatter infostring attributes like `{remainder}` at this time"
|
||||
),
|
||||
source.info_span().unwrap(),
|
||||
));
|
||||
format!("unsupported frontmatter infostring attributes: `{remainder}`"),
|
||||
info_span,
|
||||
)
|
||||
.push_visible_span(close_span));
|
||||
} else {
|
||||
return Err(FrontmatterError::new(
|
||||
format!(
|
||||
"frontmatter infostring `{other}` is unsupported by cargo; specify `cargo` for embedding a manifest"
|
||||
"unsupported frontmatter infostring `{other}`; specify `cargo` for embedding a manifest"
|
||||
),
|
||||
source.info_span().unwrap(),
|
||||
));
|
||||
info_span,
|
||||
).push_visible_span(close_span));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2783,7 +2783,7 @@ fn emit_frontmatter_diagnostic(
|
||||
manifest_file: &Path,
|
||||
gctx: &GlobalContext,
|
||||
) -> anyhow::Error {
|
||||
let span = e.span();
|
||||
let primary_span = e.primary_span();
|
||||
|
||||
// Get the path to the manifest, relative to the cwd
|
||||
let manifest_path = diff_paths(manifest_file, gctx.cwd())
|
||||
@ -2793,7 +2793,12 @@ fn emit_frontmatter_diagnostic(
|
||||
let group = Group::with_title(Level::ERROR.primary_title(e.message())).element(
|
||||
Snippet::source(contents)
|
||||
.path(manifest_path)
|
||||
.annotation(AnnotationKind::Primary.span(span)),
|
||||
.annotation(AnnotationKind::Primary.span(primary_span))
|
||||
.annotations(
|
||||
e.visible_spans()
|
||||
.iter()
|
||||
.map(|s| AnnotationKind::Visible.span(s.clone())),
|
||||
),
|
||||
);
|
||||
|
||||
if let Err(err) = gctx.shell().print_report(&[group], true) {
|
||||
|
@ -1,5 +1,8 @@
|
||||
[ERROR] frontmatter infostring `.toml` is unsupported by cargo; specify `cargo` for embedding a manifest
|
||||
[ERROR] unsupported frontmatter infostring `.toml`; specify `cargo` for embedding a manifest
|
||||
--> script:1:4
|
||||
|
|
||||
1 | ---.toml
|
||||
| ^^^^^
|
||||
2 | //~^ ERROR: invalid infostring for frontmatter
|
||||
3 | ---
|
||||
|
|
||||
|
@ -1,5 +1,7 @@
|
||||
[ERROR] frontmatter infostring `Cargo.toml` is unsupported by cargo; specify `cargo` for embedding a manifest
|
||||
[ERROR] unsupported frontmatter infostring `Cargo.toml`; specify `cargo` for embedding a manifest
|
||||
--> script:1:4
|
||||
|
|
||||
1 | ---Cargo.toml
|
||||
| ^^^^^^^^^^
|
||||
2 | ---
|
||||
|
|
||||
|
@ -1,7 +1,6 @@
|
||||
[ERROR] trailing characters found after frontmatter close
|
||||
[ERROR] unexpected characters after frontmatter close
|
||||
--> script:2:4
|
||||
|
|
||||
2 | ---cargo
|
||||
| ____^
|
||||
3 | | //~^ ERROR: extra characters after frontmatter close are not allowed
|
||||
| |_^
|
||||
1 | ---
|
||||
2 | ---cargo
|
||||
| ^^^^^
|
||||
|
@ -1,5 +1,7 @@
|
||||
[ERROR] no closing `---` found for frontmatter
|
||||
--> script:1:1
|
||||
|
|
||||
1 | ---cargo
|
||||
| ^^^
|
||||
[ERROR] unclosed frontmatter; expected `---`
|
||||
--> script:14:56
|
||||
|
|
||||
1 | ---cargo
|
||||
...
|
||||
14 | // within them and get treated as a frontmatter close.
|
||||
| ^
|
||||
|
@ -1,5 +1,8 @@
|
||||
[ERROR] frontmatter infostring `-toml` is unsupported by cargo; specify `cargo` for embedding a manifest
|
||||
[ERROR] unsupported frontmatter infostring `-toml`; specify `cargo` for embedding a manifest
|
||||
--> script:1:5
|
||||
|
|
||||
1 | --- -toml
|
||||
| ^^^^^
|
||||
2 | //~^ ERROR: invalid infostring for frontmatter
|
||||
3 | ---
|
||||
|
|
||||
|
@ -1,5 +1,7 @@
|
||||
[ERROR] frontmatter infostring `Cargo-toml` is unsupported by cargo; specify `cargo` for embedding a manifest
|
||||
[ERROR] unsupported frontmatter infostring `Cargo-toml`; specify `cargo` for embedding a manifest
|
||||
--> script:1:5
|
||||
|
|
||||
1 | --- Cargo-toml
|
||||
| ^^^^^^^^^^
|
||||
2 | ---
|
||||
|
|
||||
|
@ -1,5 +1,8 @@
|
||||
[ERROR] cargo does not support frontmatter infostring attributes like `clippy` at this time
|
||||
[ERROR] unsupported frontmatter infostring attributes: `clippy`
|
||||
--> script:1:4
|
||||
|
|
||||
1 | ---cargo,clippy
|
||||
| ^^^^^^^^^^^^
|
||||
2 | //~^ ERROR: invalid infostring for frontmatter
|
||||
3 | ---
|
||||
|
|
||||
|
@ -1,7 +1,7 @@
|
||||
[ERROR] trailing characters found after frontmatter close
|
||||
[ERROR] closing code fence has 1 more `-` than the opening fence
|
||||
--> script:3:4
|
||||
|
|
||||
3 | ----
|
||||
| ____^
|
||||
4 | |
|
||||
| |_^
|
||||
1 | ---cargo
|
||||
2 | //~^ ERROR: frontmatter close does not match the opening
|
||||
3 | ----
|
||||
| ^
|
||||
|
@ -1,5 +1,7 @@
|
||||
[ERROR] closing code fence has too few `-`
|
||||
[ERROR] closing code fence has 1 less `-` than the opening fence
|
||||
--> script:3:1
|
||||
|
|
||||
1 | ----cargo
|
||||
2 | //~^ ERROR: frontmatter close does not match the opening
|
||||
3 | ---cargo
|
||||
| ^^^
|
||||
|
@ -1,5 +1,8 @@
|
||||
[ERROR] only one frontmatter is supported
|
||||
--> script:4:1
|
||||
|
|
||||
1 | ---
|
||||
2 | ---
|
||||
3 |
|
||||
4 | ---
|
||||
| ^^^
|
||||
|
@ -1,5 +1,7 @@
|
||||
[ERROR] no closing `----` found for frontmatter
|
||||
--> script:1:1
|
||||
|
|
||||
1 | ----cargo
|
||||
| ^^^^
|
||||
[ERROR] unclosed frontmatter; expected `----`
|
||||
--> script:10:14
|
||||
|
|
||||
1 | ----cargo
|
||||
...
|
||||
10 | fn main() {}
|
||||
| ^
|
||||
|
@ -1,5 +1,7 @@
|
||||
[ERROR] no closing `----` found for frontmatter
|
||||
--> script:1:1
|
||||
|
|
||||
1 | ----cargo
|
||||
| ^^^^
|
||||
[ERROR] unclosed frontmatter; expected `----`
|
||||
--> script:15:3
|
||||
|
|
||||
1 | ----cargo
|
||||
...
|
||||
15 | }
|
||||
| ^
|
||||
|
@ -1,5 +1,7 @@
|
||||
[ERROR] no closing `----` found for frontmatter
|
||||
--> script:1:1
|
||||
|
|
||||
1 | ----cargo
|
||||
| ^^^^
|
||||
[ERROR] unclosed frontmatter; expected `----`
|
||||
--> script:16:47
|
||||
|
|
||||
1 | ----cargo
|
||||
...
|
||||
16 | //~^ ERROR: unexpected closing delimiter: `}`
|
||||
| ^
|
||||
|
@ -1,5 +1,7 @@
|
||||
[ERROR] no closing `----` found for frontmatter
|
||||
--> script:1:1
|
||||
|
|
||||
1 | ----cargo
|
||||
| ^^^^
|
||||
[ERROR] unclosed frontmatter; expected `----`
|
||||
--> script:9:14
|
||||
|
|
||||
1 | ----cargo
|
||||
...
|
||||
9 | fn main() {}
|
||||
| ^
|
||||
|
@ -1,5 +1,7 @@
|
||||
[ERROR] no closing `----` found for frontmatter
|
||||
--> script:1:1
|
||||
|
|
||||
1 | ----cargo
|
||||
| ^^^^
|
||||
[ERROR] unclosed frontmatter; expected `----`
|
||||
--> script:10:14
|
||||
|
|
||||
1 | ----cargo
|
||||
...
|
||||
10 | fn main() {}
|
||||
| ^
|
||||
|
Loading…
x
Reference in New Issue
Block a user