From 0c05c541a1e2ac68b0a4704b0d6773feaa71c214 Mon Sep 17 00:00:00 2001 From: Yuya Nishihara Date: Mon, 20 May 2024 17:31:35 +0900 Subject: [PATCH] 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. --- cli/src/template_parser.rs | 39 +++++++++++++++++++++----------------- lib/src/dsl_util.rs | 14 ++++++++++++++ lib/src/fileset_parser.rs | 29 +++++++++++++++------------- 3 files changed, 52 insertions(+), 30 deletions(-) diff --git a/cli/src/template_parser.rs b/cli/src/template_parser.rs index aa77d88c0..4c9473b4e 100644 --- a/cli/src/template_parser.rs +++ b/cli/src/template_parser.rs @@ -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> for TemplateParseError { } } +impl From> 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) -> pest::error::Error { 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() } } diff --git a/lib/src/dsl_util.rs b/lib/src/dsl_util.rs index ec5c9610d..c0e230843 100644 --- a/lib/src/dsl_util.rs +++ b/lib/src/dsl_util.rs @@ -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 { diff --git a/lib/src/fileset_parser.rs b/lib/src/fileset_parser.rs index f1ecae9f7..790c33edf 100644 --- a/lib/src/fileset_parser.rs +++ b/lib/src/fileset_parser.rs @@ -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, span: pest::Span<'_>) -> Self { FilesetParseError::new(FilesetParseErrorKind::Expression(message.into()), span) @@ -153,6 +142,15 @@ impl From> for FilesetParseError { } } +impl From> 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) -> pest::error::Error { 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() } }