Add more concrete error messages for missing argument list
This commit is contained in:
parent
eb3c2646a0
commit
142894c3ce
5 changed files with 75 additions and 21 deletions
|
@ -62,6 +62,7 @@ pub fn stringify_diagnostic(mut diagnostic: codespan_reporting::diagnostic::Diag
|
||||||
let mut chars = Chars::box_drawing();
|
let mut chars = Chars::box_drawing();
|
||||||
chars.single_primary_caret = '─';
|
chars.single_primary_caret = '─';
|
||||||
config.chars = chars;
|
config.chars = chars;
|
||||||
|
config.chars.note_bullet = '→';
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
let mut writer = term::termcolor::Ansi::new(&mut buf);
|
let mut writer = term::termcolor::Ansi::new(&mut buf);
|
||||||
let files = YUCK_FILES.read().unwrap();
|
let files = YUCK_FILES.read().unwrap();
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
||||||
use simplexpr::SimplExpr;
|
use simplexpr::SimplExpr;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error::AstResult,
|
error::{AstError::WrongExprType, AstResult, AstResultExt, FormFormatError},
|
||||||
parser::{
|
parser::{
|
||||||
ast::Ast,
|
ast::Ast,
|
||||||
ast_iterator::AstIterator,
|
ast_iterator::AstIterator,
|
||||||
|
@ -26,11 +26,16 @@ impl FromAstElementContent for WidgetDefinition {
|
||||||
const ELEMENT_NAME: &'static str = "defwidget";
|
const ELEMENT_NAME: &'static str = "defwidget";
|
||||||
|
|
||||||
fn from_tail<I: Iterator<Item = Ast>>(span: Span, mut iter: AstIterator<I>) -> AstResult<Self> {
|
fn from_tail<I: Iterator<Item = Ast>>(span: Span, mut iter: AstIterator<I>) -> AstResult<Self> {
|
||||||
let (_, name) = iter.expect_symbol()?;
|
let (name_span, name) = iter.expect_symbol().note(EXPECTED_WIDGET_DEF_FORMAT)?;
|
||||||
let (args_span, expected_args) = iter.expect_array()?;
|
let (args_span, expected_args) = iter
|
||||||
|
.expect_array()
|
||||||
|
.wrong_expr_type_to(|_| FormFormatError::WidgetDefArglistMissing(name_span.point_span_at_end()))
|
||||||
|
.note(EXPECTED_WIDGET_DEF_FORMAT)?;
|
||||||
let expected_args = expected_args.into_iter().map(|x| x.as_symbol().map(AttrName)).collect::<AstResult<_>>()?;
|
let expected_args = expected_args.into_iter().map(|x| x.as_symbol().map(AttrName)).collect::<AstResult<_>>()?;
|
||||||
let widget = iter.expect_any().and_then(WidgetUse::from_ast)?;
|
let widget = iter.expect_any().note(EXPECTED_WIDGET_DEF_FORMAT).and_then(WidgetUse::from_ast)?;
|
||||||
iter.expect_done()?;
|
iter.expect_done()?;
|
||||||
Ok(Self { name, expected_args, widget, span, args_span })
|
Ok(Self { name, expected_args, widget, span, args_span })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static EXPECTED_WIDGET_DEF_FORMAT: &str = r#"Expected format: `(defwidget name [] (contained-widgets))`"#;
|
||||||
|
|
|
@ -24,6 +24,9 @@ pub enum AstError {
|
||||||
#[error("Did not expect any further elements here. Make sure your format is correct")]
|
#[error("Did not expect any further elements here. Make sure your format is correct")]
|
||||||
NoMoreElementsExpected(Span),
|
NoMoreElementsExpected(Span),
|
||||||
|
|
||||||
|
#[error(transparent)]
|
||||||
|
FormFormatError(#[from] FormFormatError),
|
||||||
|
|
||||||
#[error("Wrong type of expression: Expected {1} but got {2}")]
|
#[error("Wrong type of expression: Expected {1} but got {2}")]
|
||||||
WrongExprType(Span, AstType, AstType),
|
WrongExprType(Span, AstType, AstType),
|
||||||
#[error("Expected to get a value, but got {1}")]
|
#[error("Expected to get a value, but got {1}")]
|
||||||
|
@ -77,6 +80,14 @@ impl AstError {
|
||||||
) -> AstError {
|
) -> AstError {
|
||||||
AstError::ParseError { file_id, source: err }
|
AstError::ParseError { file_id, source: err }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn wrong_expr_type_to(self, f: impl FnOnce(Span) -> FormFormatError) -> AstError {
|
||||||
|
match self {
|
||||||
|
AstError::WrongExprType(span, ..) => AstError::FormFormatError(f(span.point_span())),
|
||||||
|
AstError::ErrorNote(s, err) => AstError::ErrorNote(s, Box::new(err.wrong_expr_type_to(f))),
|
||||||
|
other => other,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Spanned for AstError {
|
impl Spanned for AstError {
|
||||||
|
@ -98,6 +109,7 @@ impl Spanned for AstError {
|
||||||
AstError::ErrorNote(_, err) => err.span(),
|
AstError::ErrorNote(_, err) => err.span(),
|
||||||
AstError::NoMoreElementsExpected(span) => *span,
|
AstError::NoMoreElementsExpected(span) => *span,
|
||||||
AstError::SimplExpr(err) => err.span(),
|
AstError::SimplExpr(err) => err.span(),
|
||||||
|
AstError::FormFormatError(err) => err.span(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,6 +137,9 @@ impl<T> OptionAstErrorExt<T> for Option<T> {
|
||||||
pub trait AstResultExt<T> {
|
pub trait AstResultExt<T> {
|
||||||
fn context_label(self, label_span: Span, context: &str) -> AstResult<T>;
|
fn context_label(self, label_span: Span, context: &str) -> AstResult<T>;
|
||||||
fn note(self, note: &str) -> AstResult<T>;
|
fn note(self, note: &str) -> AstResult<T>;
|
||||||
|
|
||||||
|
/// Map any [AstError::WrongExprType]s error to a [FormFormatError]
|
||||||
|
fn wrong_expr_type_to(self, f: impl FnOnce(Span) -> FormFormatError) -> AstResult<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> AstResultExt<T> for AstResult<T> {
|
impl<T> AstResultExt<T> for AstResult<T> {
|
||||||
|
@ -135,4 +150,22 @@ impl<T> AstResultExt<T> for AstResult<T> {
|
||||||
fn note(self, note: &str) -> AstResult<T> {
|
fn note(self, note: &str) -> AstResult<T> {
|
||||||
self.map_err(|e| e.note(note))
|
self.map_err(|e| e.note(note))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn wrong_expr_type_to(self, f: impl FnOnce(Span) -> FormFormatError) -> AstResult<T> {
|
||||||
|
self.map_err(|err| err.wrong_expr_type_to(f))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum FormFormatError {
|
||||||
|
#[error("Widget definition missing argument list")]
|
||||||
|
WidgetDefArglistMissing(Span),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Spanned for FormFormatError {
|
||||||
|
fn span(&self) -> Span {
|
||||||
|
match self {
|
||||||
|
FormFormatError::WidgetDefArglistMissing(span) => *span,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use diagnostic::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{attributes::AttrError, config, validate::ValidationError},
|
config::{attributes::AttrError, config, validate::ValidationError},
|
||||||
error::{get_parse_error_span, AstError},
|
error::{get_parse_error_span, AstError, FormFormatError},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::parser::parse_error;
|
use super::parser::parse_error;
|
||||||
|
@ -124,6 +124,7 @@ impl ToDiagnostic for AstError {
|
||||||
AstError::ValidationError(source) => source.to_diagnostic(),
|
AstError::ValidationError(source) => source.to_diagnostic(),
|
||||||
AstError::NoMoreElementsExpected(span) => gen_diagnostic!(self, span),
|
AstError::NoMoreElementsExpected(span) => gen_diagnostic!(self, span),
|
||||||
AstError::SimplExpr(source) => source.to_diagnostic(),
|
AstError::SimplExpr(source) => source.to_diagnostic(),
|
||||||
|
AstError::FormFormatError(error) => error.to_diagnostic(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -246,3 +247,15 @@ fn generate_lexical_error_diagnostic(span: Span) -> Diagnostic<usize> {
|
||||||
label = span => "Invalid token"
|
label = span => "Invalid token"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToDiagnostic for FormFormatError {
|
||||||
|
fn to_diagnostic(&self) -> diagnostic::Diagnostic<usize> {
|
||||||
|
match self {
|
||||||
|
FormFormatError::WidgetDefArglistMissing(span) => gen_diagnostic! {
|
||||||
|
msg = self,
|
||||||
|
label = span => "Insert the argument list (e.g.: `[]`) here",
|
||||||
|
note = "This list will in the future need to declare all the non-global variables / attributes used in this widget.\nThis is not yet neccessary, but is still considered good style.",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -20,7 +20,8 @@ pub struct AstIterator<I: Iterator<Item = Ast>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! return_or_put_back {
|
macro_rules! return_or_put_back {
|
||||||
($name:ident, $expr_type:expr, $t:ty = $p:pat => $ret:expr) => {
|
($(fn $name:ident -> $expr_type:expr, $t:ty = $p:pat => $ret:expr)*) => {
|
||||||
|
$(
|
||||||
pub fn $name(&mut self) -> AstResult<$t> {
|
pub fn $name(&mut self) -> AstResult<$t> {
|
||||||
let expr_type = $expr_type;
|
let expr_type = $expr_type;
|
||||||
match self.expect_any()? {
|
match self.expect_any()? {
|
||||||
|
@ -33,15 +34,16 @@ macro_rules! return_or_put_back {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
)*
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I: Iterator<Item = Ast>> AstIterator<I> {
|
impl<I: Iterator<Item = Ast>> AstIterator<I> {
|
||||||
return_or_put_back!(expect_symbol, AstType::Symbol, (Span, String) = Ast::Symbol(span, x) => (span, x));
|
return_or_put_back! {
|
||||||
|
fn expect_symbol -> AstType::Symbol, (Span, String) = Ast::Symbol(span, x) => (span, x)
|
||||||
return_or_put_back!(expect_list, AstType::List, (Span, Vec<Ast>) = Ast::List(span, x) => (span, x));
|
fn expect_list -> AstType::List, (Span, Vec<Ast>) = Ast::List(span, x) => (span, x)
|
||||||
|
fn expect_array -> AstType::Array, (Span, Vec<Ast>) = Ast::Array(span, x) => (span, x)
|
||||||
return_or_put_back!(expect_array, AstType::Array, (Span, Vec<Ast>) = Ast::Array(span, x) => (span, x));
|
}
|
||||||
|
|
||||||
pub fn expect_literal(&mut self) -> AstResult<(Span, DynVal)> {
|
pub fn expect_literal(&mut self) -> AstResult<(Span, DynVal)> {
|
||||||
// TODO add some others
|
// TODO add some others
|
||||||
|
|
Loading…
Add table
Reference in a new issue