jj_cli/
template_parser.rs

1// Copyright 2020 The Jujutsu Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::collections::HashMap;
16use std::error;
17use std::mem;
18
19use itertools::Itertools as _;
20use jj_lib::dsl_util;
21use jj_lib::dsl_util::collect_similar;
22use jj_lib::dsl_util::AliasDeclaration;
23use jj_lib::dsl_util::AliasDeclarationParser;
24use jj_lib::dsl_util::AliasDefinitionParser;
25use jj_lib::dsl_util::AliasExpandError;
26use jj_lib::dsl_util::AliasExpandableExpression;
27use jj_lib::dsl_util::AliasId;
28use jj_lib::dsl_util::AliasesMap;
29use jj_lib::dsl_util::Diagnostics;
30use jj_lib::dsl_util::ExpressionFolder;
31use jj_lib::dsl_util::FoldableExpression;
32use jj_lib::dsl_util::FunctionCallParser;
33use jj_lib::dsl_util::InvalidArguments;
34use jj_lib::dsl_util::StringLiteralParser;
35use once_cell::sync::Lazy;
36use pest::iterators::Pair;
37use pest::iterators::Pairs;
38use pest::pratt_parser::Assoc;
39use pest::pratt_parser::Op;
40use pest::pratt_parser::PrattParser;
41use pest::Parser as _;
42use pest_derive::Parser;
43use thiserror::Error;
44
45#[derive(Parser)]
46#[grammar = "template.pest"]
47struct TemplateParser;
48
49const STRING_LITERAL_PARSER: StringLiteralParser<Rule> = StringLiteralParser {
50    content_rule: Rule::string_content,
51    escape_rule: Rule::string_escape,
52};
53const FUNCTION_CALL_PARSER: FunctionCallParser<Rule> = FunctionCallParser {
54    function_name_rule: Rule::identifier,
55    function_arguments_rule: Rule::function_arguments,
56    keyword_argument_rule: Rule::keyword_argument,
57    argument_name_rule: Rule::identifier,
58    argument_value_rule: Rule::template,
59};
60
61impl Rule {
62    fn to_symbol(self) -> Option<&'static str> {
63        match self {
64            Rule::EOI => None,
65            Rule::whitespace => None,
66            Rule::string_escape => None,
67            Rule::string_content_char => None,
68            Rule::string_content => None,
69            Rule::string_literal => None,
70            Rule::raw_string_content => None,
71            Rule::raw_string_literal => None,
72            Rule::integer_literal => None,
73            Rule::identifier => None,
74            Rule::concat_op => Some("++"),
75            Rule::logical_or_op => Some("||"),
76            Rule::logical_and_op => Some("&&"),
77            Rule::eq_op => Some("=="),
78            Rule::ne_op => Some("!="),
79            Rule::ge_op => Some(">="),
80            Rule::gt_op => Some(">"),
81            Rule::le_op => Some("<="),
82            Rule::lt_op => Some("<"),
83            Rule::add_op => Some("+"),
84            Rule::sub_op => Some("-"),
85            Rule::mul_op => Some("*"),
86            Rule::div_op => Some("/"),
87            Rule::rem_op => Some("%"),
88            Rule::logical_not_op => Some("!"),
89            Rule::negate_op => Some("-"),
90            Rule::prefix_ops => None,
91            Rule::infix_ops => None,
92            Rule::function => None,
93            Rule::keyword_argument => None,
94            Rule::argument => None,
95            Rule::function_arguments => None,
96            Rule::lambda => None,
97            Rule::formal_parameters => None,
98            Rule::primary => None,
99            Rule::term => None,
100            Rule::expression => None,
101            Rule::template => None,
102            Rule::program => None,
103            Rule::function_alias_declaration => None,
104            Rule::alias_declaration => None,
105        }
106    }
107}
108
109/// Manages diagnostic messages emitted during template parsing and building.
110pub type TemplateDiagnostics = Diagnostics<TemplateParseError>;
111
112pub type TemplateParseResult<T> = Result<T, TemplateParseError>;
113
114#[derive(Debug, Error)]
115#[error("{pest_error}")]
116pub struct TemplateParseError {
117    kind: TemplateParseErrorKind,
118    pest_error: Box<pest::error::Error<Rule>>,
119    source: Option<Box<dyn error::Error + Send + Sync>>,
120}
121
122#[derive(Clone, Debug, Eq, Error, PartialEq)]
123pub enum TemplateParseErrorKind {
124    #[error("Syntax error")]
125    SyntaxError,
126    #[error("Keyword `{name}` doesn't exist")]
127    NoSuchKeyword {
128        name: String,
129        candidates: Vec<String>,
130    },
131    #[error("Function `{name}` doesn't exist")]
132    NoSuchFunction {
133        name: String,
134        candidates: Vec<String>,
135    },
136    #[error("Method `{name}` doesn't exist for type `{type_name}`")]
137    NoSuchMethod {
138        type_name: String,
139        name: String,
140        candidates: Vec<String>,
141    },
142    #[error("Function `{name}`: {message}")]
143    InvalidArguments { name: String, message: String },
144    #[error("Redefinition of function parameter")]
145    RedefinedFunctionParameter,
146    #[error("{0}")]
147    Expression(String),
148    #[error("In alias `{0}`")]
149    InAliasExpansion(String),
150    #[error("In function parameter `{0}`")]
151    InParameterExpansion(String),
152    #[error("Alias `{0}` expanded recursively")]
153    RecursiveAlias(String),
154}
155
156impl TemplateParseError {
157    pub fn with_span(kind: TemplateParseErrorKind, span: pest::Span<'_>) -> Self {
158        let message = kind.to_string();
159        let pest_error = Box::new(pest::error::Error::new_from_span(
160            pest::error::ErrorVariant::CustomError { message },
161            span,
162        ));
163        TemplateParseError {
164            kind,
165            pest_error,
166            source: None,
167        }
168    }
169
170    pub fn with_source(mut self, source: impl Into<Box<dyn error::Error + Send + Sync>>) -> Self {
171        self.source = Some(source.into());
172        self
173    }
174
175    pub fn expected_type(expected: &str, actual: &str, span: pest::Span<'_>) -> Self {
176        let message =
177            format!("Expected expression of type `{expected}`, but actual type is `{actual}`");
178        TemplateParseError::expression(message, span)
179    }
180
181    /// Some other expression error.
182    pub fn expression(message: impl Into<String>, span: pest::Span<'_>) -> Self {
183        TemplateParseError::with_span(TemplateParseErrorKind::Expression(message.into()), span)
184    }
185
186    /// If this is a `NoSuchKeyword` error, expands the candidates list with the
187    /// given `other_keywords`.
188    pub fn extend_keyword_candidates<I>(mut self, other_keywords: I) -> Self
189    where
190        I: IntoIterator,
191        I::Item: AsRef<str>,
192    {
193        if let TemplateParseErrorKind::NoSuchKeyword { name, candidates } = &mut self.kind {
194            let other_candidates = collect_similar(name, other_keywords);
195            *candidates = itertools::merge(mem::take(candidates), other_candidates)
196                .dedup()
197                .collect();
198        }
199        self
200    }
201
202    /// If this is a `NoSuchFunction` error, expands the candidates list with
203    /// the given `other_functions`.
204    pub fn extend_function_candidates<I>(mut self, other_functions: I) -> Self
205    where
206        I: IntoIterator,
207        I::Item: AsRef<str>,
208    {
209        if let TemplateParseErrorKind::NoSuchFunction { name, candidates } = &mut self.kind {
210            let other_candidates = collect_similar(name, other_functions);
211            *candidates = itertools::merge(mem::take(candidates), other_candidates)
212                .dedup()
213                .collect();
214        }
215        self
216    }
217
218    /// Expands keyword/function candidates with the given aliases.
219    pub fn extend_alias_candidates(self, aliases_map: &TemplateAliasesMap) -> Self {
220        self.extend_keyword_candidates(aliases_map.symbol_names())
221            .extend_function_candidates(aliases_map.function_names())
222    }
223
224    pub fn kind(&self) -> &TemplateParseErrorKind {
225        &self.kind
226    }
227
228    /// Original parsing error which typically occurred in an alias expression.
229    pub fn origin(&self) -> Option<&Self> {
230        self.source.as_ref().and_then(|e| e.downcast_ref())
231    }
232}
233
234impl AliasExpandError for TemplateParseError {
235    fn invalid_arguments(err: InvalidArguments<'_>) -> Self {
236        err.into()
237    }
238
239    fn recursive_expansion(id: AliasId<'_>, span: pest::Span<'_>) -> Self {
240        Self::with_span(TemplateParseErrorKind::RecursiveAlias(id.to_string()), span)
241    }
242
243    fn within_alias_expansion(self, id: AliasId<'_>, span: pest::Span<'_>) -> Self {
244        let kind = match id {
245            AliasId::Symbol(_) | AliasId::Function(..) => {
246                TemplateParseErrorKind::InAliasExpansion(id.to_string())
247            }
248            AliasId::Parameter(_) => TemplateParseErrorKind::InParameterExpansion(id.to_string()),
249        };
250        Self::with_span(kind, span).with_source(self)
251    }
252}
253
254impl From<pest::error::Error<Rule>> for TemplateParseError {
255    fn from(err: pest::error::Error<Rule>) -> Self {
256        TemplateParseError {
257            kind: TemplateParseErrorKind::SyntaxError,
258            pest_error: Box::new(rename_rules_in_pest_error(err)),
259            source: None,
260        }
261    }
262}
263
264impl From<InvalidArguments<'_>> for TemplateParseError {
265    fn from(err: InvalidArguments<'_>) -> Self {
266        let kind = TemplateParseErrorKind::InvalidArguments {
267            name: err.name.to_owned(),
268            message: err.message,
269        };
270        Self::with_span(kind, err.span)
271    }
272}
273
274fn rename_rules_in_pest_error(err: pest::error::Error<Rule>) -> pest::error::Error<Rule> {
275    err.renamed_rules(|rule| {
276        rule.to_symbol()
277            .map(|sym| format!("`{sym}`"))
278            .unwrap_or_else(|| format!("<{rule:?}>"))
279    })
280}
281
282#[derive(Clone, Debug, PartialEq)]
283pub enum ExpressionKind<'i> {
284    Identifier(&'i str),
285    Boolean(bool),
286    Integer(i64),
287    String(String),
288    Unary(UnaryOp, Box<ExpressionNode<'i>>),
289    Binary(BinaryOp, Box<ExpressionNode<'i>>, Box<ExpressionNode<'i>>),
290    Concat(Vec<ExpressionNode<'i>>),
291    FunctionCall(Box<FunctionCallNode<'i>>),
292    MethodCall(Box<MethodCallNode<'i>>),
293    Lambda(Box<LambdaNode<'i>>),
294    /// Identity node to preserve the span in the source template text.
295    AliasExpanded(AliasId<'i>, Box<ExpressionNode<'i>>),
296}
297
298impl<'i> FoldableExpression<'i> for ExpressionKind<'i> {
299    fn fold<F>(self, folder: &mut F, span: pest::Span<'i>) -> Result<Self, F::Error>
300    where
301        F: ExpressionFolder<'i, Self> + ?Sized,
302    {
303        match self {
304            ExpressionKind::Identifier(name) => folder.fold_identifier(name, span),
305            ExpressionKind::Boolean(_) | ExpressionKind::Integer(_) | ExpressionKind::String(_) => {
306                Ok(self)
307            }
308            ExpressionKind::Unary(op, arg) => {
309                let arg = Box::new(folder.fold_expression(*arg)?);
310                Ok(ExpressionKind::Unary(op, arg))
311            }
312            ExpressionKind::Binary(op, lhs, rhs) => {
313                let lhs = Box::new(folder.fold_expression(*lhs)?);
314                let rhs = Box::new(folder.fold_expression(*rhs)?);
315                Ok(ExpressionKind::Binary(op, lhs, rhs))
316            }
317            ExpressionKind::Concat(nodes) => Ok(ExpressionKind::Concat(
318                dsl_util::fold_expression_nodes(folder, nodes)?,
319            )),
320            ExpressionKind::FunctionCall(function) => folder.fold_function_call(function, span),
321            ExpressionKind::MethodCall(method) => {
322                // Method call is syntactically different from function call.
323                let method = Box::new(MethodCallNode {
324                    object: folder.fold_expression(method.object)?,
325                    function: dsl_util::fold_function_call_args(folder, method.function)?,
326                });
327                Ok(ExpressionKind::MethodCall(method))
328            }
329            ExpressionKind::Lambda(lambda) => {
330                let lambda = Box::new(LambdaNode {
331                    params: lambda.params,
332                    params_span: lambda.params_span,
333                    body: folder.fold_expression(lambda.body)?,
334                });
335                Ok(ExpressionKind::Lambda(lambda))
336            }
337            ExpressionKind::AliasExpanded(id, subst) => {
338                let subst = Box::new(folder.fold_expression(*subst)?);
339                Ok(ExpressionKind::AliasExpanded(id, subst))
340            }
341        }
342    }
343}
344
345impl<'i> AliasExpandableExpression<'i> for ExpressionKind<'i> {
346    fn identifier(name: &'i str) -> Self {
347        ExpressionKind::Identifier(name)
348    }
349
350    fn function_call(function: Box<FunctionCallNode<'i>>) -> Self {
351        ExpressionKind::FunctionCall(function)
352    }
353
354    fn alias_expanded(id: AliasId<'i>, subst: Box<ExpressionNode<'i>>) -> Self {
355        ExpressionKind::AliasExpanded(id, subst)
356    }
357}
358
359#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
360pub enum UnaryOp {
361    /// `!`
362    LogicalNot,
363    /// `-`
364    Negate,
365}
366
367#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
368pub enum BinaryOp {
369    /// `||`
370    LogicalOr,
371    /// `&&`
372    LogicalAnd,
373    /// `==`
374    Eq,
375    /// `!=`
376    Ne,
377    /// `>=`
378    Ge,
379    /// `>`
380    Gt,
381    /// `<=`
382    Le,
383    /// `<`
384    Lt,
385    /// `+`
386    Add,
387    /// `-`
388    Sub,
389    /// `*`
390    Mul,
391    /// `/`
392    Div,
393    /// `%`
394    Rem,
395}
396
397pub type ExpressionNode<'i> = dsl_util::ExpressionNode<'i, ExpressionKind<'i>>;
398pub type FunctionCallNode<'i> = dsl_util::FunctionCallNode<'i, ExpressionKind<'i>>;
399
400#[derive(Clone, Debug, PartialEq)]
401pub struct MethodCallNode<'i> {
402    pub object: ExpressionNode<'i>,
403    pub function: FunctionCallNode<'i>,
404}
405
406#[derive(Clone, Debug, PartialEq)]
407pub struct LambdaNode<'i> {
408    pub params: Vec<&'i str>,
409    pub params_span: pest::Span<'i>,
410    pub body: ExpressionNode<'i>,
411}
412
413fn parse_identifier_or_literal(pair: Pair<Rule>) -> ExpressionKind {
414    assert_eq!(pair.as_rule(), Rule::identifier);
415    match pair.as_str() {
416        "false" => ExpressionKind::Boolean(false),
417        "true" => ExpressionKind::Boolean(true),
418        name => ExpressionKind::Identifier(name),
419    }
420}
421
422fn parse_identifier_name(pair: Pair<'_, Rule>) -> TemplateParseResult<&str> {
423    let span = pair.as_span();
424    if let ExpressionKind::Identifier(name) = parse_identifier_or_literal(pair) {
425        Ok(name)
426    } else {
427        Err(TemplateParseError::expression("Expected identifier", span))
428    }
429}
430
431fn parse_formal_parameters(params_pair: Pair<'_, Rule>) -> TemplateParseResult<Vec<&str>> {
432    assert_eq!(params_pair.as_rule(), Rule::formal_parameters);
433    let params_span = params_pair.as_span();
434    let params: Vec<_> = params_pair
435        .into_inner()
436        .map(parse_identifier_name)
437        .try_collect()?;
438    if params.iter().all_unique() {
439        Ok(params)
440    } else {
441        Err(TemplateParseError::with_span(
442            TemplateParseErrorKind::RedefinedFunctionParameter,
443            params_span,
444        ))
445    }
446}
447
448fn parse_lambda_node(pair: Pair<Rule>) -> TemplateParseResult<LambdaNode> {
449    assert_eq!(pair.as_rule(), Rule::lambda);
450    let mut inner = pair.into_inner();
451    let params_pair = inner.next().unwrap();
452    let params_span = params_pair.as_span();
453    let body_pair = inner.next().unwrap();
454    let params = parse_formal_parameters(params_pair)?;
455    let body = parse_template_node(body_pair)?;
456    Ok(LambdaNode {
457        params,
458        params_span,
459        body,
460    })
461}
462
463fn parse_term_node(pair: Pair<Rule>) -> TemplateParseResult<ExpressionNode> {
464    assert_eq!(pair.as_rule(), Rule::term);
465    let mut inner = pair.into_inner();
466    let expr = inner.next().unwrap();
467    let span = expr.as_span();
468    let primary = match expr.as_rule() {
469        Rule::string_literal => {
470            let text = STRING_LITERAL_PARSER.parse(expr.into_inner());
471            ExpressionNode::new(ExpressionKind::String(text), span)
472        }
473        Rule::raw_string_literal => {
474            let [content] = expr.into_inner().collect_array().unwrap();
475            assert_eq!(content.as_rule(), Rule::raw_string_content);
476            let text = content.as_str().to_owned();
477            ExpressionNode::new(ExpressionKind::String(text), span)
478        }
479        Rule::integer_literal => {
480            let value = expr.as_str().parse().map_err(|err| {
481                TemplateParseError::expression("Invalid integer literal", span).with_source(err)
482            })?;
483            ExpressionNode::new(ExpressionKind::Integer(value), span)
484        }
485        Rule::identifier => ExpressionNode::new(parse_identifier_or_literal(expr), span),
486        Rule::function => {
487            let function = Box::new(FUNCTION_CALL_PARSER.parse(
488                expr,
489                parse_identifier_name,
490                parse_template_node,
491            )?);
492            ExpressionNode::new(ExpressionKind::FunctionCall(function), span)
493        }
494        Rule::lambda => {
495            let lambda = Box::new(parse_lambda_node(expr)?);
496            ExpressionNode::new(ExpressionKind::Lambda(lambda), span)
497        }
498        Rule::template => parse_template_node(expr)?,
499        other => panic!("unexpected term: {other:?}"),
500    };
501    inner.try_fold(primary, |object, chain| {
502        assert_eq!(chain.as_rule(), Rule::function);
503        let span = object.span.start_pos().span(&chain.as_span().end_pos());
504        let method = Box::new(MethodCallNode {
505            object,
506            function: FUNCTION_CALL_PARSER.parse(
507                chain,
508                parse_identifier_name,
509                parse_template_node,
510            )?,
511        });
512        Ok(ExpressionNode::new(
513            ExpressionKind::MethodCall(method),
514            span,
515        ))
516    })
517}
518
519fn parse_expression_node(pair: Pair<Rule>) -> TemplateParseResult<ExpressionNode> {
520    assert_eq!(pair.as_rule(), Rule::expression);
521    static PRATT: Lazy<PrattParser<Rule>> = Lazy::new(|| {
522        PrattParser::new()
523            .op(Op::infix(Rule::logical_or_op, Assoc::Left))
524            .op(Op::infix(Rule::logical_and_op, Assoc::Left))
525            .op(Op::infix(Rule::eq_op, Assoc::Left) | Op::infix(Rule::ne_op, Assoc::Left))
526            .op(Op::infix(Rule::ge_op, Assoc::Left)
527                | Op::infix(Rule::gt_op, Assoc::Left)
528                | Op::infix(Rule::le_op, Assoc::Left)
529                | Op::infix(Rule::lt_op, Assoc::Left))
530            .op(Op::infix(Rule::add_op, Assoc::Left) | Op::infix(Rule::sub_op, Assoc::Left))
531            .op(Op::infix(Rule::mul_op, Assoc::Left)
532                | Op::infix(Rule::div_op, Assoc::Left)
533                | Op::infix(Rule::rem_op, Assoc::Left))
534            .op(Op::prefix(Rule::logical_not_op) | Op::prefix(Rule::negate_op))
535    });
536    PRATT
537        .map_primary(parse_term_node)
538        .map_prefix(|op, rhs| {
539            let op_kind = match op.as_rule() {
540                Rule::logical_not_op => UnaryOp::LogicalNot,
541                Rule::negate_op => UnaryOp::Negate,
542                r => panic!("unexpected prefix operator rule {r:?}"),
543            };
544            let rhs = Box::new(rhs?);
545            let span = op.as_span().start_pos().span(&rhs.span.end_pos());
546            let expr = ExpressionKind::Unary(op_kind, rhs);
547            Ok(ExpressionNode::new(expr, span))
548        })
549        .map_infix(|lhs, op, rhs| {
550            let op_kind = match op.as_rule() {
551                Rule::logical_or_op => BinaryOp::LogicalOr,
552                Rule::logical_and_op => BinaryOp::LogicalAnd,
553                Rule::eq_op => BinaryOp::Eq,
554                Rule::ne_op => BinaryOp::Ne,
555                Rule::ge_op => BinaryOp::Ge,
556                Rule::gt_op => BinaryOp::Gt,
557                Rule::le_op => BinaryOp::Le,
558                Rule::lt_op => BinaryOp::Lt,
559                Rule::add_op => BinaryOp::Add,
560                Rule::sub_op => BinaryOp::Sub,
561                Rule::mul_op => BinaryOp::Mul,
562                Rule::div_op => BinaryOp::Div,
563                Rule::rem_op => BinaryOp::Rem,
564                r => panic!("unexpected infix operator rule {r:?}"),
565            };
566            let lhs = Box::new(lhs?);
567            let rhs = Box::new(rhs?);
568            let span = lhs.span.start_pos().span(&rhs.span.end_pos());
569            let expr = ExpressionKind::Binary(op_kind, lhs, rhs);
570            Ok(ExpressionNode::new(expr, span))
571        })
572        .parse(pair.into_inner())
573}
574
575fn parse_template_node(pair: Pair<Rule>) -> TemplateParseResult<ExpressionNode> {
576    assert_eq!(pair.as_rule(), Rule::template);
577    let span = pair.as_span();
578    let inner = pair.into_inner();
579    let mut nodes: Vec<_> = inner
580        .filter_map(|pair| match pair.as_rule() {
581            Rule::concat_op => None,
582            Rule::expression => Some(parse_expression_node(pair)),
583            r => panic!("unexpected template item rule {r:?}"),
584        })
585        .try_collect()?;
586    if nodes.len() == 1 {
587        Ok(nodes.pop().unwrap())
588    } else {
589        Ok(ExpressionNode::new(ExpressionKind::Concat(nodes), span))
590    }
591}
592
593/// Parses text into AST nodes. No type/name checking is made at this stage.
594pub fn parse_template(template_text: &str) -> TemplateParseResult<ExpressionNode<'_>> {
595    let mut pairs: Pairs<Rule> = TemplateParser::parse(Rule::program, template_text)?;
596    let first_pair = pairs.next().unwrap();
597    if first_pair.as_rule() == Rule::EOI {
598        let span = first_pair.as_span();
599        Ok(ExpressionNode::new(ExpressionKind::Concat(vec![]), span))
600    } else {
601        parse_template_node(first_pair)
602    }
603}
604
605pub type TemplateAliasesMap = AliasesMap<TemplateAliasParser, String>;
606
607#[derive(Clone, Debug, Default)]
608pub struct TemplateAliasParser;
609
610impl AliasDeclarationParser for TemplateAliasParser {
611    type Error = TemplateParseError;
612
613    fn parse_declaration(&self, source: &str) -> Result<AliasDeclaration, Self::Error> {
614        let mut pairs = TemplateParser::parse(Rule::alias_declaration, source)?;
615        let first = pairs.next().unwrap();
616        match first.as_rule() {
617            Rule::identifier => {
618                let name = parse_identifier_name(first)?.to_owned();
619                Ok(AliasDeclaration::Symbol(name))
620            }
621            Rule::function_alias_declaration => {
622                let mut inner = first.into_inner();
623                let name_pair = inner.next().unwrap();
624                let params_pair = inner.next().unwrap();
625                let name = parse_identifier_name(name_pair)?.to_owned();
626                let params = parse_formal_parameters(params_pair)?
627                    .into_iter()
628                    .map(|s| s.to_owned())
629                    .collect();
630                Ok(AliasDeclaration::Function(name, params))
631            }
632            r => panic!("unexpected alias declaration rule {r:?}"),
633        }
634    }
635}
636
637impl AliasDefinitionParser for TemplateAliasParser {
638    type Output<'i> = ExpressionKind<'i>;
639    type Error = TemplateParseError;
640
641    fn parse_definition<'i>(&self, source: &'i str) -> Result<ExpressionNode<'i>, Self::Error> {
642        parse_template(source)
643    }
644}
645
646/// Parses text into AST nodes, and expands aliases.
647///
648/// No type/name checking is made at this stage.
649pub fn parse<'i>(
650    template_text: &'i str,
651    aliases_map: &'i TemplateAliasesMap,
652) -> TemplateParseResult<ExpressionNode<'i>> {
653    let node = parse_template(template_text)?;
654    dsl_util::expand_aliases(node, aliases_map)
655}
656
657/// Unwraps inner value if the given `node` is a string literal.
658pub fn expect_string_literal<'a>(node: &'a ExpressionNode<'_>) -> TemplateParseResult<&'a str> {
659    catch_aliases_no_diagnostics(node, |node| match &node.kind {
660        ExpressionKind::String(s) => Ok(s.as_str()),
661        _ => Err(TemplateParseError::expression(
662            "Expected string literal",
663            node.span,
664        )),
665    })
666}
667
668/// Unwraps inner node if the given `node` is a lambda.
669pub fn expect_lambda<'a, 'i>(
670    node: &'a ExpressionNode<'i>,
671) -> TemplateParseResult<&'a LambdaNode<'i>> {
672    catch_aliases_no_diagnostics(node, |node| match &node.kind {
673        ExpressionKind::Lambda(lambda) => Ok(lambda.as_ref()),
674        _ => Err(TemplateParseError::expression(
675            "Expected lambda expression",
676            node.span,
677        )),
678    })
679}
680
681/// Applies the given function to the innermost `node` by unwrapping alias
682/// expansion nodes. Appends alias expansion stack to error and diagnostics.
683pub fn catch_aliases<'a, 'i, T>(
684    diagnostics: &mut TemplateDiagnostics,
685    node: &'a ExpressionNode<'i>,
686    f: impl FnOnce(&mut TemplateDiagnostics, &'a ExpressionNode<'i>) -> TemplateParseResult<T>,
687) -> TemplateParseResult<T> {
688    let (node, stack) = skip_aliases(node);
689    if stack.is_empty() {
690        f(diagnostics, node)
691    } else {
692        let mut inner_diagnostics = TemplateDiagnostics::new();
693        let result = f(&mut inner_diagnostics, node);
694        diagnostics.extend_with(inner_diagnostics, |diag| attach_aliases_err(diag, &stack));
695        result.map_err(|err| attach_aliases_err(err, &stack))
696    }
697}
698
699fn catch_aliases_no_diagnostics<'a, 'i, T>(
700    node: &'a ExpressionNode<'i>,
701    f: impl FnOnce(&'a ExpressionNode<'i>) -> TemplateParseResult<T>,
702) -> TemplateParseResult<T> {
703    let (node, stack) = skip_aliases(node);
704    f(node).map_err(|err| attach_aliases_err(err, &stack))
705}
706
707fn skip_aliases<'a, 'i>(
708    mut node: &'a ExpressionNode<'i>,
709) -> (&'a ExpressionNode<'i>, Vec<(AliasId<'i>, pest::Span<'i>)>) {
710    let mut stack = Vec::new();
711    while let ExpressionKind::AliasExpanded(id, subst) = &node.kind {
712        stack.push((*id, node.span));
713        node = subst;
714    }
715    (node, stack)
716}
717
718fn attach_aliases_err(
719    err: TemplateParseError,
720    stack: &[(AliasId<'_>, pest::Span<'_>)],
721) -> TemplateParseError {
722    stack
723        .iter()
724        .rfold(err, |err, &(id, span)| err.within_alias_expansion(id, span))
725}
726
727/// Looks up `table` by the given function name.
728pub fn lookup_function<'a, V>(
729    table: &'a HashMap<&str, V>,
730    function: &FunctionCallNode,
731) -> TemplateParseResult<&'a V> {
732    if let Some(value) = table.get(function.name) {
733        Ok(value)
734    } else {
735        let candidates = collect_similar(function.name, table.keys());
736        Err(TemplateParseError::with_span(
737            TemplateParseErrorKind::NoSuchFunction {
738                name: function.name.to_owned(),
739                candidates,
740            },
741            function.name_span,
742        ))
743    }
744}
745
746/// Looks up `table` by the given method name.
747pub fn lookup_method<'a, V>(
748    type_name: impl Into<String>,
749    table: &'a HashMap<&str, V>,
750    function: &FunctionCallNode,
751) -> TemplateParseResult<&'a V> {
752    if let Some(value) = table.get(function.name) {
753        Ok(value)
754    } else {
755        let candidates = collect_similar(function.name, table.keys());
756        Err(TemplateParseError::with_span(
757            TemplateParseErrorKind::NoSuchMethod {
758                type_name: type_name.into(),
759                name: function.name.to_owned(),
760                candidates,
761            },
762            function.name_span,
763        ))
764    }
765}
766
767#[cfg(test)]
768mod tests {
769    use assert_matches::assert_matches;
770    use jj_lib::dsl_util::KeywordArgument;
771
772    use super::*;
773
774    #[derive(Debug)]
775    struct WithTemplateAliasesMap(TemplateAliasesMap);
776
777    impl WithTemplateAliasesMap {
778        fn parse<'i>(&'i self, template_text: &'i str) -> TemplateParseResult<ExpressionNode<'i>> {
779            parse(template_text, &self.0)
780        }
781
782        fn parse_normalized<'i>(&'i self, template_text: &'i str) -> ExpressionNode<'i> {
783            normalize_tree(self.parse(template_text).unwrap())
784        }
785    }
786
787    fn with_aliases(
788        aliases: impl IntoIterator<Item = (impl AsRef<str>, impl Into<String>)>,
789    ) -> WithTemplateAliasesMap {
790        let mut aliases_map = TemplateAliasesMap::new();
791        for (decl, defn) in aliases {
792            aliases_map.insert(decl, defn).unwrap();
793        }
794        WithTemplateAliasesMap(aliases_map)
795    }
796
797    fn parse_into_kind(template_text: &str) -> Result<ExpressionKind<'_>, TemplateParseErrorKind> {
798        parse_template(template_text)
799            .map(|node| node.kind)
800            .map_err(|err| err.kind)
801    }
802
803    fn parse_normalized(template_text: &str) -> ExpressionNode<'_> {
804        normalize_tree(parse_template(template_text).unwrap())
805    }
806
807    /// Drops auxiliary data of AST so it can be compared with other node.
808    fn normalize_tree(node: ExpressionNode) -> ExpressionNode {
809        fn empty_span() -> pest::Span<'static> {
810            pest::Span::new("", 0, 0).unwrap()
811        }
812
813        fn normalize_list(nodes: Vec<ExpressionNode>) -> Vec<ExpressionNode> {
814            nodes.into_iter().map(normalize_tree).collect()
815        }
816
817        fn normalize_function_call(function: FunctionCallNode) -> FunctionCallNode {
818            FunctionCallNode {
819                name: function.name,
820                name_span: empty_span(),
821                args: normalize_list(function.args),
822                keyword_args: function
823                    .keyword_args
824                    .into_iter()
825                    .map(|arg| KeywordArgument {
826                        name: arg.name,
827                        name_span: empty_span(),
828                        value: normalize_tree(arg.value),
829                    })
830                    .collect(),
831                args_span: empty_span(),
832            }
833        }
834
835        let normalized_kind = match node.kind {
836            ExpressionKind::Identifier(_)
837            | ExpressionKind::Boolean(_)
838            | ExpressionKind::Integer(_)
839            | ExpressionKind::String(_) => node.kind,
840            ExpressionKind::Unary(op, arg) => {
841                let arg = Box::new(normalize_tree(*arg));
842                ExpressionKind::Unary(op, arg)
843            }
844            ExpressionKind::Binary(op, lhs, rhs) => {
845                let lhs = Box::new(normalize_tree(*lhs));
846                let rhs = Box::new(normalize_tree(*rhs));
847                ExpressionKind::Binary(op, lhs, rhs)
848            }
849            ExpressionKind::Concat(nodes) => ExpressionKind::Concat(normalize_list(nodes)),
850            ExpressionKind::FunctionCall(function) => {
851                let function = Box::new(normalize_function_call(*function));
852                ExpressionKind::FunctionCall(function)
853            }
854            ExpressionKind::MethodCall(method) => {
855                let method = Box::new(MethodCallNode {
856                    object: normalize_tree(method.object),
857                    function: normalize_function_call(method.function),
858                });
859                ExpressionKind::MethodCall(method)
860            }
861            ExpressionKind::Lambda(lambda) => {
862                let lambda = Box::new(LambdaNode {
863                    params: lambda.params,
864                    params_span: empty_span(),
865                    body: normalize_tree(lambda.body),
866                });
867                ExpressionKind::Lambda(lambda)
868            }
869            ExpressionKind::AliasExpanded(_, subst) => normalize_tree(*subst).kind,
870        };
871        ExpressionNode {
872            kind: normalized_kind,
873            span: empty_span(),
874        }
875    }
876
877    #[test]
878    fn test_parse_tree_eq() {
879        assert_eq!(
880            normalize_tree(parse_template(r#" commit_id.short(1 )  ++ description"#).unwrap()),
881            normalize_tree(parse_template(r#"commit_id.short( 1 )++(description)"#).unwrap()),
882        );
883        assert_ne!(
884            normalize_tree(parse_template(r#" "ab" "#).unwrap()),
885            normalize_tree(parse_template(r#" "a" ++ "b" "#).unwrap()),
886        );
887        assert_ne!(
888            normalize_tree(parse_template(r#" "foo" ++ "0" "#).unwrap()),
889            normalize_tree(parse_template(r#" "foo" ++ 0 "#).unwrap()),
890        );
891    }
892
893    #[test]
894    fn test_parse_whitespace() {
895        let ascii_whitespaces: String = ('\x00'..='\x7f')
896            .filter(char::is_ascii_whitespace)
897            .collect();
898        assert_eq!(
899            parse_normalized(&format!("{ascii_whitespaces}f()")),
900            parse_normalized("f()"),
901        );
902    }
903
904    #[test]
905    fn test_parse_operator_syntax() {
906        // Operator precedence
907        assert_eq!(parse_normalized("!!x"), parse_normalized("!(!x)"));
908        assert_eq!(
909            parse_normalized("!x.f() || !g()"),
910            parse_normalized("(!(x.f())) || (!(g()))"),
911        );
912        assert_eq!(
913            parse_normalized("!x.f() <= !x.f()"),
914            parse_normalized("((!(x.f())) <= (!(x.f())))"),
915        );
916        assert_eq!(
917            parse_normalized("!x.f() < !x.f() == !x.f() >= !x.f() || !g() != !g()"),
918            parse_normalized(
919                "((!(x.f()) < (!(x.f()))) == ((!(x.f())) >= (!(x.f())))) || ((!(g())) != (!(g())))"
920            ),
921        );
922        assert_eq!(
923            parse_normalized("x.f() || y == y || z"),
924            parse_normalized("((x.f()) || (y == y)) || z"),
925        );
926        assert_eq!(
927            parse_normalized("x || y == y && z.h() == z"),
928            parse_normalized("x || ((y == y) && ((z.h()) == z))"),
929        );
930        assert_eq!(
931            parse_normalized("x == y || y != z && !z"),
932            parse_normalized("(x == y) || ((y != z) && (!z))"),
933        );
934        assert_eq!(
935            parse_normalized("a + b * c / d % e - -f == g"),
936            parse_normalized("((a + (((b * c) / d) % e)) - (-f)) == g"),
937        );
938
939        // Logical operator bounds more tightly than concatenation. This might
940        // not be so intuitive, but should be harmless.
941        assert_eq!(
942            parse_normalized(r"x && y ++ z"),
943            parse_normalized(r"(x && y) ++ z"),
944        );
945        assert_eq!(
946            parse_normalized(r"x ++ y || z"),
947            parse_normalized(r"x ++ (y || z)"),
948        );
949        assert_eq!(
950            parse_normalized(r"x == y ++ z"),
951            parse_normalized(r"(x == y) ++ z"),
952        );
953        assert_eq!(
954            parse_normalized(r"x != y ++ z"),
955            parse_normalized(r"(x != y) ++ z"),
956        );
957
958        // Expression span
959        assert_eq!(parse_template(" ! x ").unwrap().span.as_str(), "! x");
960        assert_eq!(parse_template(" x ||y ").unwrap().span.as_str(), "x ||y");
961    }
962
963    #[test]
964    fn test_function_call_syntax() {
965        // Trailing comma isn't allowed for empty argument
966        assert!(parse_template(r#" "".first_line() "#).is_ok());
967        assert!(parse_template(r#" "".first_line(,) "#).is_err());
968
969        // Trailing comma is allowed for the last argument
970        assert!(parse_template(r#" "".contains("") "#).is_ok());
971        assert!(parse_template(r#" "".contains("",) "#).is_ok());
972        assert!(parse_template(r#" "".contains("" ,  ) "#).is_ok());
973        assert!(parse_template(r#" "".contains(,"") "#).is_err());
974        assert!(parse_template(r#" "".contains("",,) "#).is_err());
975        assert!(parse_template(r#" "".contains("" , , ) "#).is_err());
976        assert!(parse_template(r#" label("","") "#).is_ok());
977        assert!(parse_template(r#" label("","",) "#).is_ok());
978        assert!(parse_template(r#" label("",,"") "#).is_err());
979
980        // Keyword arguments
981        assert!(parse_template("f(foo = bar)").is_ok());
982        assert!(parse_template("f( foo=bar )").is_ok());
983        assert!(parse_template("x.f(foo, bar=0, baz=1)").is_ok());
984
985        // Boolean literal cannot be used as a function name
986        assert!(parse_template("false()").is_err());
987        // Boolean literal cannot be used as a parameter name
988        assert!(parse_template("f(false=0)").is_err());
989        // Function arguments can be any expression
990        assert!(parse_template("f(false)").is_ok());
991    }
992
993    #[test]
994    fn test_method_call_syntax() {
995        assert_eq!(
996            parse_normalized("x.f().g()"),
997            parse_normalized("(x.f()).g()"),
998        );
999
1000        // Expression span
1001        assert_eq!(parse_template(" x.f() ").unwrap().span.as_str(), "x.f()");
1002        assert_eq!(
1003            parse_template(" x.f().g() ").unwrap().span.as_str(),
1004            "x.f().g()",
1005        );
1006    }
1007
1008    #[test]
1009    fn test_lambda_syntax() {
1010        fn unwrap_lambda(node: ExpressionNode<'_>) -> Box<LambdaNode<'_>> {
1011            match node.kind {
1012                ExpressionKind::Lambda(lambda) => lambda,
1013                _ => panic!("unexpected expression: {node:?}"),
1014            }
1015        }
1016
1017        let lambda = unwrap_lambda(parse_template("|| a").unwrap());
1018        assert_eq!(lambda.params.len(), 0);
1019        assert_eq!(lambda.body.kind, ExpressionKind::Identifier("a"));
1020        let lambda = unwrap_lambda(parse_template("|foo| a").unwrap());
1021        assert_eq!(lambda.params.len(), 1);
1022        let lambda = unwrap_lambda(parse_template("|foo, b| a").unwrap());
1023        assert_eq!(lambda.params.len(), 2);
1024
1025        // No body
1026        assert!(parse_template("||").is_err());
1027
1028        // Binding
1029        assert_eq!(
1030            parse_normalized("||  x ++ y"),
1031            parse_normalized("|| (x ++ y)"),
1032        );
1033        assert_eq!(
1034            parse_normalized("f( || x,   || y)"),
1035            parse_normalized("f((|| x), (|| y))"),
1036        );
1037        assert_eq!(
1038            parse_normalized("||  x ++  || y"),
1039            parse_normalized("|| (x ++ (|| y))"),
1040        );
1041
1042        // Lambda vs logical operator: weird, but this is type error anyway
1043        assert_eq!(parse_normalized("x||||y"), parse_normalized("x || (|| y)"));
1044        assert_eq!(parse_normalized("||||x"), parse_normalized("|| (|| x)"));
1045
1046        // Trailing comma
1047        assert!(parse_template("|,| a").is_err());
1048        assert!(parse_template("|x,| a").is_ok());
1049        assert!(parse_template("|x , | a").is_ok());
1050        assert!(parse_template("|,x| a").is_err());
1051        assert!(parse_template("| x,y,| a").is_ok());
1052        assert!(parse_template("|x,,y| a").is_err());
1053
1054        // Formal parameter can't be redefined
1055        assert_eq!(
1056            parse_template("|x, x| a").unwrap_err().kind,
1057            TemplateParseErrorKind::RedefinedFunctionParameter
1058        );
1059
1060        // Boolean literal cannot be used as a parameter name
1061        assert!(parse_template("|false| a").is_err());
1062    }
1063
1064    #[test]
1065    fn test_keyword_literal() {
1066        assert_eq!(parse_into_kind("false"), Ok(ExpressionKind::Boolean(false)));
1067        assert_eq!(parse_into_kind("(true)"), Ok(ExpressionKind::Boolean(true)));
1068        // Keyword literals are case sensitive
1069        assert_eq!(
1070            parse_into_kind("False"),
1071            Ok(ExpressionKind::Identifier("False")),
1072        );
1073        assert_eq!(
1074            parse_into_kind("tRue"),
1075            Ok(ExpressionKind::Identifier("tRue")),
1076        );
1077    }
1078
1079    #[test]
1080    fn test_string_literal() {
1081        // "\<char>" escapes
1082        assert_eq!(
1083            parse_into_kind(r#" "\t\r\n\"\\\0\e" "#),
1084            Ok(ExpressionKind::String("\t\r\n\"\\\0\u{1b}".to_owned())),
1085        );
1086
1087        // Invalid "\<char>" escape
1088        assert_eq!(
1089            parse_into_kind(r#" "\y" "#),
1090            Err(TemplateParseErrorKind::SyntaxError),
1091        );
1092
1093        // Single-quoted raw string
1094        assert_eq!(
1095            parse_into_kind(r#" '' "#),
1096            Ok(ExpressionKind::String("".to_owned())),
1097        );
1098        assert_eq!(
1099            parse_into_kind(r#" 'a\n' "#),
1100            Ok(ExpressionKind::String(r"a\n".to_owned())),
1101        );
1102        assert_eq!(
1103            parse_into_kind(r#" '\' "#),
1104            Ok(ExpressionKind::String(r"\".to_owned())),
1105        );
1106        assert_eq!(
1107            parse_into_kind(r#" '"' "#),
1108            Ok(ExpressionKind::String(r#"""#.to_owned())),
1109        );
1110
1111        // Hex bytes
1112        assert_eq!(
1113            parse_into_kind(r#""\x61\x65\x69\x6f\x75""#),
1114            Ok(ExpressionKind::String("aeiou".to_owned())),
1115        );
1116        assert_eq!(
1117            parse_into_kind(r#""\xe0\xe8\xec\xf0\xf9""#),
1118            Ok(ExpressionKind::String("àèìðù".to_owned())),
1119        );
1120        assert_eq!(
1121            parse_into_kind(r#""\x""#),
1122            Err(TemplateParseErrorKind::SyntaxError),
1123        );
1124        assert_eq!(
1125            parse_into_kind(r#""\xf""#),
1126            Err(TemplateParseErrorKind::SyntaxError),
1127        );
1128        assert_eq!(
1129            parse_into_kind(r#""\xgg""#),
1130            Err(TemplateParseErrorKind::SyntaxError),
1131        );
1132    }
1133
1134    #[test]
1135    fn test_integer_literal() {
1136        assert_eq!(parse_into_kind("0"), Ok(ExpressionKind::Integer(0)));
1137        assert_eq!(parse_into_kind("(42)"), Ok(ExpressionKind::Integer(42)));
1138        assert_eq!(
1139            parse_into_kind("00"),
1140            Err(TemplateParseErrorKind::SyntaxError),
1141        );
1142
1143        assert_eq!(
1144            parse_into_kind(&format!("{}", i64::MAX)),
1145            Ok(ExpressionKind::Integer(i64::MAX)),
1146        );
1147        assert_matches!(
1148            parse_into_kind(&format!("{}", (i64::MAX as u64) + 1)),
1149            Err(TemplateParseErrorKind::Expression(_))
1150        );
1151    }
1152
1153    #[test]
1154    fn test_parse_alias_decl() {
1155        let mut aliases_map = TemplateAliasesMap::new();
1156        aliases_map.insert("sym", r#""is symbol""#).unwrap();
1157        aliases_map.insert("func()", r#""is function 0""#).unwrap();
1158        aliases_map
1159            .insert("func(a, b)", r#""is function 2""#)
1160            .unwrap();
1161        aliases_map.insert("func(a)", r#""is function a""#).unwrap();
1162        aliases_map.insert("func(b)", r#""is function b""#).unwrap();
1163
1164        let (id, defn) = aliases_map.get_symbol("sym").unwrap();
1165        assert_eq!(id, AliasId::Symbol("sym"));
1166        assert_eq!(defn, r#""is symbol""#);
1167
1168        let (id, params, defn) = aliases_map.get_function("func", 0).unwrap();
1169        assert_eq!(id, AliasId::Function("func", &[]));
1170        assert!(params.is_empty());
1171        assert_eq!(defn, r#""is function 0""#);
1172
1173        let (id, params, defn) = aliases_map.get_function("func", 1).unwrap();
1174        assert_eq!(id, AliasId::Function("func", &["b".to_owned()]));
1175        assert_eq!(params, ["b"]);
1176        assert_eq!(defn, r#""is function b""#);
1177
1178        let (id, params, defn) = aliases_map.get_function("func", 2).unwrap();
1179        assert_eq!(
1180            id,
1181            AliasId::Function("func", &["a".to_owned(), "b".to_owned()])
1182        );
1183        assert_eq!(params, ["a", "b"]);
1184        assert_eq!(defn, r#""is function 2""#);
1185
1186        assert!(aliases_map.get_function("func", 3).is_none());
1187
1188        // Formal parameter 'a' can't be redefined
1189        assert_eq!(
1190            aliases_map.insert("f(a, a)", r#""""#).unwrap_err().kind,
1191            TemplateParseErrorKind::RedefinedFunctionParameter
1192        );
1193
1194        // Boolean literal cannot be used as a symbol, function, or parameter name
1195        assert!(aliases_map.insert("false", r#"""#).is_err());
1196        assert!(aliases_map.insert("true()", r#"""#).is_err());
1197        assert!(aliases_map.insert("f(false)", r#"""#).is_err());
1198
1199        // Trailing comma isn't allowed for empty parameter
1200        assert!(aliases_map.insert("f(,)", r#"""#).is_err());
1201        // Trailing comma is allowed for the last parameter
1202        assert!(aliases_map.insert("g(a,)", r#"""#).is_ok());
1203        assert!(aliases_map.insert("h(a ,  )", r#"""#).is_ok());
1204        assert!(aliases_map.insert("i(,a)", r#"""#).is_err());
1205        assert!(aliases_map.insert("j(a,,)", r#"""#).is_err());
1206        assert!(aliases_map.insert("k(a  , , )", r#"""#).is_err());
1207        assert!(aliases_map.insert("l(a,b,)", r#"""#).is_ok());
1208        assert!(aliases_map.insert("m(a,,b)", r#"""#).is_err());
1209    }
1210
1211    #[test]
1212    fn test_expand_symbol_alias() {
1213        assert_eq!(
1214            with_aliases([("AB", "a ++ b")]).parse_normalized("AB ++ c"),
1215            parse_normalized("(a ++ b) ++ c"),
1216        );
1217        assert_eq!(
1218            with_aliases([("AB", "a ++ b")]).parse_normalized("if(AB, label(c, AB))"),
1219            parse_normalized("if((a ++ b), label(c, (a ++ b)))"),
1220        );
1221
1222        // Multi-level substitution.
1223        assert_eq!(
1224            with_aliases([("A", "BC"), ("BC", "b ++ C"), ("C", "c")]).parse_normalized("A"),
1225            parse_normalized("b ++ c"),
1226        );
1227
1228        // Operator expression can be expanded in concatenation.
1229        assert_eq!(
1230            with_aliases([("AB", "a || b")]).parse_normalized("AB ++ c"),
1231            parse_normalized("(a || b) ++ c"),
1232        );
1233
1234        // Operands should be expanded.
1235        assert_eq!(
1236            with_aliases([("A", "a"), ("B", "b")]).parse_normalized("A || !B"),
1237            parse_normalized("a || !b"),
1238        );
1239
1240        // Method receiver and arguments should be expanded.
1241        assert_eq!(
1242            with_aliases([("A", "a")]).parse_normalized("A.f()"),
1243            parse_normalized("a.f()"),
1244        );
1245        assert_eq!(
1246            with_aliases([("A", "a"), ("B", "b")]).parse_normalized("x.f(A, B)"),
1247            parse_normalized("x.f(a, b)"),
1248        );
1249
1250        // Lambda expression body should be expanded.
1251        assert_eq!(
1252            with_aliases([("A", "a")]).parse_normalized("|| A"),
1253            parse_normalized("|| a"),
1254        );
1255        // No matter if 'A' is a formal parameter. Alias substitution isn't scoped.
1256        // If we don't like this behavior, maybe we can turn off alias substitution
1257        // for lambda parameters.
1258        assert_eq!(
1259            with_aliases([("A", "a ++ b")]).parse_normalized("|A| A"),
1260            parse_normalized("|A| (a ++ b)"),
1261        );
1262
1263        // Infinite recursion, where the top-level error isn't of RecursiveAlias kind.
1264        assert_eq!(
1265            with_aliases([("A", "A")]).parse("A").unwrap_err().kind,
1266            TemplateParseErrorKind::InAliasExpansion("A".to_owned()),
1267        );
1268        assert_eq!(
1269            with_aliases([("A", "B"), ("B", "b ++ C"), ("C", "c ++ B")])
1270                .parse("A")
1271                .unwrap_err()
1272                .kind,
1273            TemplateParseErrorKind::InAliasExpansion("A".to_owned()),
1274        );
1275
1276        // Error in alias definition.
1277        assert_eq!(
1278            with_aliases([("A", "a(")]).parse("A").unwrap_err().kind,
1279            TemplateParseErrorKind::InAliasExpansion("A".to_owned()),
1280        );
1281    }
1282
1283    #[test]
1284    fn test_expand_function_alias() {
1285        assert_eq!(
1286            with_aliases([("F(  )", "a")]).parse_normalized("F()"),
1287            parse_normalized("a"),
1288        );
1289        assert_eq!(
1290            with_aliases([("F( x )", "x")]).parse_normalized("F(a)"),
1291            parse_normalized("a"),
1292        );
1293        assert_eq!(
1294            with_aliases([("F( x, y )", "x ++ y")]).parse_normalized("F(a, b)"),
1295            parse_normalized("a ++ b"),
1296        );
1297
1298        // Not recursion because functions are overloaded by arity.
1299        assert_eq!(
1300            with_aliases([("F(x)", "F(x,b)"), ("F(x,y)", "x ++ y")]).parse_normalized("F(a)"),
1301            parse_normalized("a ++ b")
1302        );
1303
1304        // Arguments should be resolved in the current scope.
1305        assert_eq!(
1306            with_aliases([("F(x,y)", "if(x, y)")]).parse_normalized("F(a ++ y, b ++ x)"),
1307            parse_normalized("if((a ++ y), (b ++ x))"),
1308        );
1309        // F(a) -> if(G(a), y) -> if((x ++ a), y)
1310        assert_eq!(
1311            with_aliases([("F(x)", "if(G(x), y)"), ("G(y)", "x ++ y")]).parse_normalized("F(a)"),
1312            parse_normalized("if((x ++ a), y)"),
1313        );
1314        // F(G(a)) -> F(x ++ a) -> if(G(x ++ a), y) -> if((x ++ (x ++ a)), y)
1315        assert_eq!(
1316            with_aliases([("F(x)", "if(G(x), y)"), ("G(y)", "x ++ y")]).parse_normalized("F(G(a))"),
1317            parse_normalized("if((x ++ (x ++ a)), y)"),
1318        );
1319
1320        // Function parameter should precede the symbol alias.
1321        assert_eq!(
1322            with_aliases([("F(X)", "X"), ("X", "x")]).parse_normalized("F(a) ++ X"),
1323            parse_normalized("a ++ x"),
1324        );
1325
1326        // Function parameter shouldn't be expanded in symbol alias.
1327        assert_eq!(
1328            with_aliases([("F(x)", "x ++ A"), ("A", "x")]).parse_normalized("F(a)"),
1329            parse_normalized("a ++ x"),
1330        );
1331
1332        // Function and symbol aliases reside in separate namespaces.
1333        assert_eq!(
1334            with_aliases([("A()", "A"), ("A", "a")]).parse_normalized("A()"),
1335            parse_normalized("a"),
1336        );
1337
1338        // Method call shouldn't be substituted by function alias.
1339        assert_eq!(
1340            with_aliases([("F()", "f()")]).parse_normalized("x.F()"),
1341            parse_normalized("x.F()"),
1342        );
1343
1344        // Formal parameter shouldn't be substituted by alias parameter, but
1345        // the expression should be substituted.
1346        assert_eq!(
1347            with_aliases([("F(x)", "|x| x")]).parse_normalized("F(a ++ b)"),
1348            parse_normalized("|x| (a ++ b)"),
1349        );
1350
1351        // Invalid number of arguments.
1352        assert_matches!(
1353            with_aliases([("F()", "x")]).parse("F(a)").unwrap_err().kind,
1354            TemplateParseErrorKind::InvalidArguments { .. }
1355        );
1356        assert_matches!(
1357            with_aliases([("F(x)", "x")]).parse("F()").unwrap_err().kind,
1358            TemplateParseErrorKind::InvalidArguments { .. }
1359        );
1360        assert_matches!(
1361            with_aliases([("F(x,y)", "x ++ y")])
1362                .parse("F(a,b,c)")
1363                .unwrap_err()
1364                .kind,
1365            TemplateParseErrorKind::InvalidArguments { .. }
1366        );
1367
1368        // Infinite recursion, where the top-level error isn't of RecursiveAlias kind.
1369        assert_eq!(
1370            with_aliases([("F(x)", "G(x)"), ("G(x)", "H(x)"), ("H(x)", "F(x)")])
1371                .parse("F(a)")
1372                .unwrap_err()
1373                .kind,
1374            TemplateParseErrorKind::InAliasExpansion("F(x)".to_owned()),
1375        );
1376        assert_eq!(
1377            with_aliases([("F(x)", "F(x,b)"), ("F(x,y)", "F(x|y)")])
1378                .parse("F(a)")
1379                .unwrap_err()
1380                .kind,
1381            TemplateParseErrorKind::InAliasExpansion("F(x)".to_owned())
1382        );
1383    }
1384}