Parser hints infrastructure (#1570)

This commit is contained in:
Mathias Fischler 2023-07-05 16:25:26 +02:00 committed by GitHub
parent d37217aaa4
commit 5bdad06d92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 3 deletions

View File

@ -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 {

View File

@ -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, "");

View File

@ -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
}