mirror of
https://github.com/typst/typst
synced 2025-06-28 08:12:53 +08:00
Parser hints infrastructure (#1570)
This commit is contained in:
parent
d37217aaa4
commit
5bdad06d92
@ -135,6 +135,13 @@ impl SyntaxNode {
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a user-presentable hint if this is an error node.
|
||||
pub fn hint(&mut self, hint: impl Into<EcoString>) {
|
||||
if let Repr::Error(error) = &mut self.0 {
|
||||
Arc::make_mut(error).hint(hint);
|
||||
}
|
||||
}
|
||||
|
||||
/// The error messages for this node and its descendants.
|
||||
pub fn errors(&self) -> Vec<SourceError> {
|
||||
if !self.erroneous() {
|
||||
@ -142,7 +149,8 @@ impl SyntaxNode {
|
||||
}
|
||||
|
||||
if let Repr::Error(error) = &self.0 {
|
||||
vec![SourceError::new(error.span, error.message.clone())]
|
||||
vec![SourceError::new(error.span, error.message.clone())
|
||||
.with_hints(error.hints.to_owned())]
|
||||
} else {
|
||||
self.children()
|
||||
.filter(|node| node.erroneous())
|
||||
@ -539,6 +547,9 @@ struct ErrorNode {
|
||||
text: EcoString,
|
||||
/// The node's span.
|
||||
span: Span,
|
||||
/// Additonal hints to the user, indicating how this error could be avoided
|
||||
/// or worked around.
|
||||
hints: Vec<EcoString>,
|
||||
}
|
||||
|
||||
impl ErrorNode {
|
||||
@ -548,6 +559,7 @@ impl ErrorNode {
|
||||
message: message.into(),
|
||||
text: text.into(),
|
||||
span: Span::detached(),
|
||||
hints: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
@ -555,6 +567,11 @@ impl ErrorNode {
|
||||
fn len(&self) -> usize {
|
||||
self.text.len()
|
||||
}
|
||||
|
||||
/// Add a user-presentable hint to this error node.
|
||||
fn hint(&mut self, hint: impl Into<EcoString>) {
|
||||
self.hints.push(hint.into());
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for ErrorNode {
|
||||
|
@ -1066,7 +1066,8 @@ fn for_loop(p: &mut Parser) {
|
||||
p.assert(SyntaxKind::For);
|
||||
pattern(p);
|
||||
if p.at(SyntaxKind::Comma) {
|
||||
p.expected("keyword `in` - did you mean to use a destructuring pattern?");
|
||||
p.expected("keyword `in`");
|
||||
p.hint("did you mean to use a destructuring pattern?");
|
||||
if !p.eat_if(SyntaxKind::Ident) {
|
||||
p.eat_if(SyntaxKind::Underscore);
|
||||
}
|
||||
@ -1613,6 +1614,15 @@ impl<'s> Parser<'s> {
|
||||
self.skip();
|
||||
}
|
||||
|
||||
// Adds a hint to the last node, if the last node is an error.
|
||||
fn hint(&mut self, hint: impl Into<EcoString>) {
|
||||
self.unskip();
|
||||
if let Some(last) = self.nodes.last_mut() {
|
||||
last.hint(hint);
|
||||
}
|
||||
self.skip();
|
||||
}
|
||||
|
||||
fn expected_at(&mut self, m: Marker, thing: &str) {
|
||||
let message = eco_format!("expected {}", thing);
|
||||
let error = SyntaxNode::error(message, "");
|
||||
|
@ -92,7 +92,8 @@
|
||||
|
||||
---
|
||||
// Destructuring without parentheses.
|
||||
// Error: 7 expected keyword `in` - did you mean to use a destructuring pattern?
|
||||
// Error: 7 expected keyword `in`
|
||||
// Hint: 7 did you mean to use a destructuring pattern?
|
||||
#for k, v in (a: 4, b: 5) {
|
||||
dont-care
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user