fileset, templater: insert intermediate InvalidArguments error type

This will help extract common FunctionCallNode<'i, T> type. We don't need
freedom of arbitrary error type choices, but implementing From<_> is the
easiest option I can think of. Another option is to constrain error type by
the expression type T through "T::ParseError: ArgumentsParseError" or
something, but it seemed a bit weird that we have to use trait just for that.
This commit is contained in:
Yuya Nishihara 2024-05-20 17:31:35 +09:00
parent 82b0e88a21
commit 0c05c541a1
3 changed files with 52 additions and 30 deletions

View file

@ -18,7 +18,7 @@ use std::{error, mem};
use itertools::Itertools as _;
use jj_lib::dsl_util::{
collect_similar, AliasDeclaration, AliasDeclarationParser, AliasId, AliasesMap,
StringLiteralParser,
InvalidArguments, StringLiteralParser,
};
use once_cell::sync::Lazy;
use pest::iterators::{Pair, Pairs};
@ -149,16 +149,6 @@ impl TemplateParseError {
)
}
pub fn invalid_arguments(name: &str, message: String, span: pest::Span<'_>) -> Self {
TemplateParseError::with_span(
TemplateParseErrorKind::InvalidArguments {
name: name.to_owned(),
message,
},
span,
)
}
pub fn expected_type(expected: &str, actual: &str, span: pest::Span<'_>) -> Self {
let message =
format!(r#"Expected expression of type "{expected}", but actual type is "{actual}""#);
@ -238,6 +228,16 @@ impl From<pest::error::Error<Rule>> for TemplateParseError {
}
}
impl From<InvalidArguments<'_>> for TemplateParseError {
fn from(err: InvalidArguments<'_>) -> Self {
let kind = TemplateParseErrorKind::InvalidArguments {
name: err.name.to_owned(),
message: err.message,
};
Self::with_span(kind, err.span)
}
}
fn rename_rules_in_pest_error(err: pest::error::Error<Rule>) -> pest::error::Error<Rule> {
err.renamed_rules(|rule| {
rule.to_symbol()
@ -623,11 +623,12 @@ pub fn expand_aliases<'i>(
ExpressionKind::FunctionCall(function) => {
if let Some((id, params, defn)) = state.aliases_map.get_function(function.name) {
if function.args.len() != params.len() {
return Err(TemplateParseError::invalid_arguments(
function.name,
format!("Expected {} arguments", params.len()),
function.args_span,
));
return Err(InvalidArguments {
name: function.name,
message: format!("Expected {} arguments", params.len()),
span: function.args_span,
}
.into());
}
// Resolve arguments in the current scope, and pass them in to the alias
// expansion scope.
@ -727,7 +728,11 @@ impl<'i> FunctionCallNode<'i> {
}
fn invalid_arguments(&self, message: String) -> TemplateParseError {
TemplateParseError::invalid_arguments(self.name, message, self.args_span)
InvalidArguments {
name: self.name,
message,
span: self.args_span,
}.into()
}
}

View file

@ -21,6 +21,20 @@ use itertools::Itertools as _;
use pest::iterators::Pairs;
use pest::RuleType;
/// Unexpected number of arguments, or invalid combination of arguments.
///
/// This error is supposed to be converted to language-specific parse error
/// type, where lifetime `'i` will be eliminated.
#[derive(Clone, Debug)]
pub struct InvalidArguments<'i> {
/// Function name.
pub name: &'i str,
/// Error message.
pub message: String,
/// Span of the bad arguments.
pub span: pest::Span<'i>,
}
/// Helper to parse string literal.
#[derive(Debug)]
pub struct StringLiteralParser<R> {

View file

@ -24,7 +24,7 @@ use pest::Parser;
use pest_derive::Parser;
use thiserror::Error;
use crate::dsl_util::StringLiteralParser;
use crate::dsl_util::{InvalidArguments, StringLiteralParser};
#[derive(Parser)]
#[grammar = "fileset.pest"]
@ -121,17 +121,6 @@ impl FilesetParseError {
self
}
/// Unexpected number of arguments, or invalid combination of arguments.
pub(super) fn invalid_arguments(name: &str, message: String, span: pest::Span<'_>) -> Self {
FilesetParseError::new(
FilesetParseErrorKind::InvalidArguments {
name: name.to_owned(),
message,
},
span,
)
}
/// Some other expression error.
pub(super) fn expression(message: impl Into<String>, span: pest::Span<'_>) -> Self {
FilesetParseError::new(FilesetParseErrorKind::Expression(message.into()), span)
@ -153,6 +142,15 @@ impl From<pest::error::Error<Rule>> for FilesetParseError {
}
}
impl From<InvalidArguments<'_>> for FilesetParseError {
fn from(err: InvalidArguments<'_>) -> Self {
let kind = FilesetParseErrorKind::InvalidArguments {
name: err.name.to_owned(),
message: err.message,
};
Self::new(kind, err.span)
}
}
fn rename_rules_in_pest_error(err: pest::error::Error<Rule>) -> pest::error::Error<Rule> {
err.renamed_rules(|rule| {
rule.to_symbol()
@ -349,7 +347,12 @@ impl<'i> FunctionCallNode<'i> {
}
fn invalid_arguments(&self, message: String) -> FilesetParseError {
FilesetParseError::invalid_arguments(self.name, message, self.args_span)
InvalidArguments {
name: self.name,
message,
span: self.args_span,
}
.into()
}
}