ok/jj
1
0
Fork 0
forked from mirrors/jj

dsl_util: add trait for alias substitution errors

This is basically the same as the previous patch, but for error types. Some
of these functions could be encoded as "E: From<AliasExpandError<'i>>", but
alias substitution logic is recursive, so it would have to convert E back and
force.
This commit is contained in:
Yuya Nishihara 2024-05-18 12:17:06 +09:00
parent cf6357459d
commit 5061d4b831
3 changed files with 34 additions and 16 deletions

View file

@ -16,6 +16,7 @@ use std::collections::HashMap;
use itertools::Itertools as _;
use jj_lib::backend::{Signature, Timestamp};
use jj_lib::dsl_util::AliasExpandError as _;
use crate::template_parser::{
self, BinaryOp, ExpressionKind, ExpressionNode, FunctionCallNode, TemplateAliasesMap,

View file

@ -17,8 +17,8 @@ use std::{error, mem};
use itertools::Itertools as _;
use jj_lib::dsl_util::{
self, collect_similar, AliasDeclaration, AliasDeclarationParser, AliasExpandableExpression,
AliasId, AliasesMap, InvalidArguments, StringLiteralParser,
self, collect_similar, AliasDeclaration, AliasDeclarationParser, AliasExpandError,
AliasExpandableExpression, AliasId, AliasesMap, InvalidArguments, StringLiteralParser,
};
use once_cell::sync::Lazy;
use pest::iterators::{Pair, Pairs};
@ -160,16 +160,6 @@ impl TemplateParseError {
TemplateParseError::with_span(TemplateParseErrorKind::Expression(message.into()), span)
}
pub fn within_alias_expansion(self, id: AliasId<'_>, span: pest::Span<'_>) -> Self {
let kind = match id {
AliasId::Symbol(_) | AliasId::Function(_) => {
TemplateParseErrorKind::BadAliasExpansion(id.to_string())
}
AliasId::Parameter(_) => TemplateParseErrorKind::BadParameterExpansion(id.to_string()),
};
TemplateParseError::with_span(kind, span).with_source(self)
}
/// If this is a `NoSuchKeyword` error, expands the candidates list with the
/// given `other_keywords`.
pub fn extend_keyword_candidates<I>(mut self, other_keywords: I) -> Self
@ -218,6 +208,26 @@ impl TemplateParseError {
}
}
impl AliasExpandError for TemplateParseError {
fn invalid_arguments(err: InvalidArguments<'_>) -> Self {
err.into()
}
fn recursive_expansion(id: AliasId<'_>, span: pest::Span<'_>) -> Self {
Self::with_span(TemplateParseErrorKind::RecursiveAlias(id.to_string()), span)
}
fn within_alias_expansion(self, id: AliasId<'_>, span: pest::Span<'_>) -> Self {
let kind = match id {
AliasId::Symbol(_) | AliasId::Function(_) => {
TemplateParseErrorKind::BadAliasExpansion(id.to_string())
}
AliasId::Parameter(_) => TemplateParseErrorKind::BadParameterExpansion(id.to_string()),
};
Self::with_span(kind, span).with_source(self)
}
}
impl From<pest::error::Error<Rule>> for TemplateParseError {
fn from(err: pest::error::Error<Rule>) -> Self {
TemplateParseError {
@ -546,10 +556,7 @@ pub fn expand_aliases<'i>(
) -> TemplateParseResult<ExpressionKind<'i>> {
// The stack should be short, so let's simply do linear search and duplicate.
if state.aliases_expanding.contains(&id) {
return Err(TemplateParseError::with_span(
TemplateParseErrorKind::RecursiveAlias(id.to_string()),
span,
));
return Err(TemplateParseError::recursive_expansion(id, span));
}
let mut aliases_expanding = state.aliases_expanding.to_vec();
aliases_expanding.push(id);

View file

@ -276,6 +276,16 @@ pub trait AliasExpandableExpression<'i>: Sized {
fn alias_expanded(id: AliasId<'i>, subst: Box<ExpressionNode<'i, Self>>) -> Self;
}
/// Error that may occur during alias substitution.
pub trait AliasExpandError: Sized {
/// Unexpected number of arguments, or invalid combination of arguments.
fn invalid_arguments(err: InvalidArguments<'_>) -> Self;
/// Recursion detected during alias substitution.
fn recursive_expansion(id: AliasId<'_>, span: pest::Span<'_>) -> Self;
/// Attaches alias trace to the current error.
fn within_alias_expansion(self, id: AliasId<'_>, span: pest::Span<'_>) -> Self;
}
/// Collects similar names from the `candidates` list.
pub fn collect_similar<I>(name: &str, candidates: I) -> Vec<String>
where