forked from mirrors/jj
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:
parent
82b0e88a21
commit
0c05c541a1
3 changed files with 52 additions and 30 deletions
|
@ -18,7 +18,7 @@ use std::{error, mem};
|
||||||
use itertools::Itertools as _;
|
use itertools::Itertools as _;
|
||||||
use jj_lib::dsl_util::{
|
use jj_lib::dsl_util::{
|
||||||
collect_similar, AliasDeclaration, AliasDeclarationParser, AliasId, AliasesMap,
|
collect_similar, AliasDeclaration, AliasDeclarationParser, AliasId, AliasesMap,
|
||||||
StringLiteralParser,
|
InvalidArguments, StringLiteralParser,
|
||||||
};
|
};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use pest::iterators::{Pair, Pairs};
|
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 {
|
pub fn expected_type(expected: &str, actual: &str, span: pest::Span<'_>) -> Self {
|
||||||
let message =
|
let message =
|
||||||
format!(r#"Expected expression of type "{expected}", but actual type is "{actual}""#);
|
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> {
|
fn rename_rules_in_pest_error(err: pest::error::Error<Rule>) -> pest::error::Error<Rule> {
|
||||||
err.renamed_rules(|rule| {
|
err.renamed_rules(|rule| {
|
||||||
rule.to_symbol()
|
rule.to_symbol()
|
||||||
|
@ -623,11 +623,12 @@ pub fn expand_aliases<'i>(
|
||||||
ExpressionKind::FunctionCall(function) => {
|
ExpressionKind::FunctionCall(function) => {
|
||||||
if let Some((id, params, defn)) = state.aliases_map.get_function(function.name) {
|
if let Some((id, params, defn)) = state.aliases_map.get_function(function.name) {
|
||||||
if function.args.len() != params.len() {
|
if function.args.len() != params.len() {
|
||||||
return Err(TemplateParseError::invalid_arguments(
|
return Err(InvalidArguments {
|
||||||
function.name,
|
name: function.name,
|
||||||
format!("Expected {} arguments", params.len()),
|
message: format!("Expected {} arguments", params.len()),
|
||||||
function.args_span,
|
span: function.args_span,
|
||||||
));
|
}
|
||||||
|
.into());
|
||||||
}
|
}
|
||||||
// Resolve arguments in the current scope, and pass them in to the alias
|
// Resolve arguments in the current scope, and pass them in to the alias
|
||||||
// expansion scope.
|
// expansion scope.
|
||||||
|
@ -727,7 +728,11 @@ impl<'i> FunctionCallNode<'i> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn invalid_arguments(&self, message: String) -> TemplateParseError {
|
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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,20 @@ use itertools::Itertools as _;
|
||||||
use pest::iterators::Pairs;
|
use pest::iterators::Pairs;
|
||||||
use pest::RuleType;
|
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.
|
/// Helper to parse string literal.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct StringLiteralParser<R> {
|
pub struct StringLiteralParser<R> {
|
||||||
|
|
|
@ -24,7 +24,7 @@ use pest::Parser;
|
||||||
use pest_derive::Parser;
|
use pest_derive::Parser;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::dsl_util::StringLiteralParser;
|
use crate::dsl_util::{InvalidArguments, StringLiteralParser};
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[grammar = "fileset.pest"]
|
#[grammar = "fileset.pest"]
|
||||||
|
@ -121,17 +121,6 @@ impl FilesetParseError {
|
||||||
self
|
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.
|
/// Some other expression error.
|
||||||
pub(super) fn expression(message: impl Into<String>, span: pest::Span<'_>) -> Self {
|
pub(super) fn expression(message: impl Into<String>, span: pest::Span<'_>) -> Self {
|
||||||
FilesetParseError::new(FilesetParseErrorKind::Expression(message.into()), span)
|
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> {
|
fn rename_rules_in_pest_error(err: pest::error::Error<Rule>) -> pest::error::Error<Rule> {
|
||||||
err.renamed_rules(|rule| {
|
err.renamed_rules(|rule| {
|
||||||
rule.to_symbol()
|
rule.to_symbol()
|
||||||
|
@ -349,7 +347,12 @@ impl<'i> FunctionCallNode<'i> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn invalid_arguments(&self, message: String) -> FilesetParseError {
|
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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue