mirror of
https://github.com/typst/typst
synced 2025-06-28 16:22: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.
|
/// The error messages for this node and its descendants.
|
||||||
pub fn errors(&self) -> Vec<SourceError> {
|
pub fn errors(&self) -> Vec<SourceError> {
|
||||||
if !self.erroneous() {
|
if !self.erroneous() {
|
||||||
@ -142,7 +149,8 @@ impl SyntaxNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Repr::Error(error) = &self.0 {
|
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 {
|
} else {
|
||||||
self.children()
|
self.children()
|
||||||
.filter(|node| node.erroneous())
|
.filter(|node| node.erroneous())
|
||||||
@ -539,6 +547,9 @@ struct ErrorNode {
|
|||||||
text: EcoString,
|
text: EcoString,
|
||||||
/// The node's span.
|
/// The node's span.
|
||||||
span: Span,
|
span: Span,
|
||||||
|
/// Additonal hints to the user, indicating how this error could be avoided
|
||||||
|
/// or worked around.
|
||||||
|
hints: Vec<EcoString>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ErrorNode {
|
impl ErrorNode {
|
||||||
@ -548,6 +559,7 @@ impl ErrorNode {
|
|||||||
message: message.into(),
|
message: message.into(),
|
||||||
text: text.into(),
|
text: text.into(),
|
||||||
span: Span::detached(),
|
span: Span::detached(),
|
||||||
|
hints: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -555,6 +567,11 @@ impl ErrorNode {
|
|||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
self.text.len()
|
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 {
|
impl Debug for ErrorNode {
|
||||||
|
@ -1066,7 +1066,8 @@ fn for_loop(p: &mut Parser) {
|
|||||||
p.assert(SyntaxKind::For);
|
p.assert(SyntaxKind::For);
|
||||||
pattern(p);
|
pattern(p);
|
||||||
if p.at(SyntaxKind::Comma) {
|
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) {
|
if !p.eat_if(SyntaxKind::Ident) {
|
||||||
p.eat_if(SyntaxKind::Underscore);
|
p.eat_if(SyntaxKind::Underscore);
|
||||||
}
|
}
|
||||||
@ -1613,6 +1614,15 @@ impl<'s> Parser<'s> {
|
|||||||
self.skip();
|
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) {
|
fn expected_at(&mut self, m: Marker, thing: &str) {
|
||||||
let message = eco_format!("expected {}", thing);
|
let message = eco_format!("expected {}", thing);
|
||||||
let error = SyntaxNode::error(message, "");
|
let error = SyntaxNode::error(message, "");
|
||||||
|
@ -92,7 +92,8 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
// Destructuring without parentheses.
|
// 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) {
|
#for k, v in (a: 4, b: 5) {
|
||||||
dont-care
|
dont-care
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user