From 1bca9ccecb9edb583a0a94bd3611147b66909ab9 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Wed, 4 May 2022 23:26:15 +0200 Subject: [PATCH] Improve diagnostics --- src/parse/mod.rs | 12 ++++++++---- src/parse/parser.rs | 8 +++++++- src/syntax/ast.rs | 2 +- src/syntax/mod.rs | 4 ++-- tests/typ/code/call.typ | 10 +++++----- tests/typ/code/closure.typ | 6 +++--- tests/typ/code/dict.typ | 6 +++--- tests/typ/code/import.typ | 7 +++---- tests/typ/code/spread.typ | 2 +- 9 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 8bf7b1c5f..b473c9af0 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -604,6 +604,7 @@ fn collection(p: &mut Parser, keyed: bool) -> (CollectionKind, usize) { missing_coma = Some(p.trivia_start()); } } else { + p.eat_if(NodeKind::Comma); kind = Some(CollectionKind::Group); } } @@ -638,11 +639,15 @@ fn item(p: &mut Parser, keyed: bool) -> ParseResult { p.eat(); marker.perform(p, NodeKind::Keyed, expr)?; } - _ => { + kind => { let mut msg = EcoString::from("expected identifier"); if keyed { msg.push_str(" or string"); } + if let Some(kind) = kind { + msg.push_str(", found "); + msg.push_str(kind.as_str()); + } let error = NodeKind::Error(ErrorPos::Full, msg); marker.end(p, error); p.eat(); @@ -661,8 +666,7 @@ fn item(p: &mut Parser, keyed: bool) -> ParseResult { /// expressions. fn array(p: &mut Parser, marker: Marker) { marker.filter_children(p, |x| match x.kind() { - NodeKind::Named => Err("expected expression, found named pair"), - NodeKind::Keyed => Err("expected expression, found keyed pair"), + NodeKind::Named | NodeKind::Keyed => Err("expected expression"), _ => Ok(()), }); marker.end(p, NodeKind::ArrayExpr); @@ -685,7 +689,7 @@ fn dict(p: &mut Parser, marker: Marker) { Ok(()) } NodeKind::Spread | NodeKind::Comma | NodeKind::Colon => Ok(()), - _ => Err("expected named or keyed pair, found expression"), + _ => Err("expected named or keyed pair"), }); marker.end(p, NodeKind::DictExpr); } diff --git a/src/parse/parser.rs b/src/parse/parser.rs index 50bb5711c..f3a3ffd1d 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -4,6 +4,7 @@ use std::ops::Range; use super::{TokenMode, Tokens}; use crate::syntax::{ErrorPos, Green, GreenData, GreenNode, NodeKind}; +use crate::util::EcoString; /// A convenient token-based parser. pub struct Parser<'s> { @@ -474,7 +475,12 @@ impl Marker { } if let Err(msg) = f(child) { - let error = NodeKind::Error(ErrorPos::Full, msg.into()); + let mut msg = EcoString::from(msg); + if msg.starts_with("expected") { + msg.push_str(", found "); + msg.push_str(child.kind().as_str()); + } + let error = NodeKind::Error(ErrorPos::Full, msg); let inner = mem::take(child); *child = GreenNode::with_child(error, inner).into(); } diff --git a/src/syntax/ast.rs b/src/syntax/ast.rs index 1add2fd67..95421213c 100644 --- a/src/syntax/ast.rs +++ b/src/syntax/ast.rs @@ -964,7 +964,7 @@ pub enum ClosureParam { Pos(Ident), /// A named parameter with a default value: `draw: false`. Named(Named), - /// A parameter sink: `..args`. + /// An argument sink: `..args`. Sink(Ident), } diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs index 09d7265d8..abe541b8c 100644 --- a/src/syntax/mod.rs +++ b/src/syntax/mod.rs @@ -662,7 +662,7 @@ pub enum NodeKind { MethodCall, /// A function call's argument list: `(x, y)`. CallArgs, - /// Spreaded arguments or a parameter sink: `..x`. + /// Spreaded arguments or a argument sink: `..x`. Spread, /// A closure expression: `(x, y) => z`. ClosureExpr, @@ -906,7 +906,7 @@ impl NodeKind { Self::FuncCall => "function call", Self::MethodCall => "method call", Self::CallArgs => "call arguments", - Self::Spread => "parameter sink", + Self::Spread => "spread", Self::ClosureExpr => "closure", Self::ClosureParams => "closure parameters", Self::LetExpr => "`let` expression", diff --git a/tests/typ/code/call.typ b/tests/typ/code/call.typ index 0285c8a21..5a3f45f91 100644 --- a/tests/typ/code/call.typ +++ b/tests/typ/code/call.typ @@ -79,17 +79,17 @@ // Error: 8 expected comma #func(1 2) -// Error: 7-8 expected identifier +// Error: 7-8 expected identifier, found integer // Error: 9 expected expression #func(1:) -// Error: 7-8 expected identifier +// Error: 7-8 expected identifier, found integer #func(1:2) -// Error: 7-12 expected identifier -#func("abc":2) +// Error: 7-12 expected identifier, found string +#func("abc": 2) -// Error: 7-10 expected identifier +// Error: 7-10 expected identifier, found group {func((x):1)} --- diff --git a/tests/typ/code/closure.typ b/tests/typ/code/closure.typ index 45f232ca0..aa7bc5b92 100644 --- a/tests/typ/code/closure.typ +++ b/tests/typ/code/closure.typ @@ -145,13 +145,13 @@ } --- -// Error: 6-16 expected identifier, named pair or argument sink +// Error: 6-16 expected identifier, named pair or argument sink, found keyed pair {(a, "named": b) => none} --- -// Error: 10-15 expected identifier +// Error: 10-15 expected identifier, found string #let foo("key": b) = key --- -// Error: 10-14 expected identifier +// Error: 10-14 expected identifier, found `none` #let foo(none: b) = key diff --git a/tests/typ/code/dict.typ b/tests/typ/code/dict.typ index 00c78c17b..800977612 100644 --- a/tests/typ/code/dict.typ +++ b/tests/typ/code/dict.typ @@ -49,12 +49,12 @@ --- // Simple expression after already being identified as a dictionary. -// Error: 9-10 expected named or keyed pair, found expression +// Error: 9-10 expected named or keyed pair, found identifier {(a: 1, b)} // Identified as dictionary due to initial colon. -// Error: 4-5 expected named or keyed pair, found expression +// Error: 4-5 expected named or keyed pair, found integer // Error: 5 expected comma -// Error: 12-16 expected identifier or string +// Error: 12-16 expected identifier or string, found boolean // Error: 17-18 expected expression, found colon {(:1 b:"", true::)} diff --git a/tests/typ/code/import.typ b/tests/typ/code/import.typ index 312ee6768..dab91daed 100644 --- a/tests/typ/code/import.typ +++ b/tests/typ/code/import.typ @@ -71,11 +71,11 @@ This is never reached. // Error: 8 expected keyword `from` #import -// Error: 9-19 expected identifier +// Error: 9-19 expected identifier, found string // Error: 19 expected keyword `from` #import "file.typ" -// Error: 16-19 expected identifier +// Error: 16-19 expected identifier, found string // Error: 22 expected keyword `from` #import afrom, "b", c @@ -108,7 +108,6 @@ This is never reached. // A star in the list. // Error: 12-13 expected expression, found star -// Error: 13-14 expected expression, found comma #import a, *, b from "target.typ" // An item after a star. @@ -117,5 +116,5 @@ This is never reached. #import *, a from "target.typ" --- -// Error: 9-13 expected identifier +// Error: 9-13 expected identifier, found named pair #import a: 1 from "" diff --git a/tests/typ/code/spread.typ b/tests/typ/code/spread.typ index a41e04b9d..86dbfd989 100644 --- a/tests/typ/code/spread.typ +++ b/tests/typ/code/spread.typ @@ -62,7 +62,7 @@ #min(.."nope") --- -// Error: 8-14 expected identifier, named pair or argument sink +// Error: 8-14 expected identifier, named pair or argument sink, found spread #let f(..true) = none ---