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:
parent
cf6357459d
commit
5061d4b831
3 changed files with 34 additions and 16 deletions
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue