ok/jj
1
0
Fork 0
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:
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 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()
} }
} }

View file

@ -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> {

View file

@ -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()
} }
} }