1#![allow(missing_docs)]
16
17use std::collections::HashSet;
18use std::error;
19use std::mem;
20use std::str::FromStr;
21
22use itertools::Itertools as _;
23use once_cell::sync::Lazy;
24use pest::iterators::Pair;
25use pest::iterators::Pairs;
26use pest::pratt_parser::Assoc;
27use pest::pratt_parser::Op;
28use pest::pratt_parser::PrattParser;
29use pest::Parser;
30use pest_derive::Parser;
31use thiserror::Error;
32
33use crate::dsl_util;
34use crate::dsl_util::collect_similar;
35use crate::dsl_util::AliasDeclaration;
36use crate::dsl_util::AliasDeclarationParser;
37use crate::dsl_util::AliasDefinitionParser;
38use crate::dsl_util::AliasExpandError;
39use crate::dsl_util::AliasExpandableExpression;
40use crate::dsl_util::AliasId;
41use crate::dsl_util::AliasesMap;
42use crate::dsl_util::Diagnostics;
43use crate::dsl_util::ExpressionFolder;
44use crate::dsl_util::FoldableExpression;
45use crate::dsl_util::FunctionCallParser;
46use crate::dsl_util::InvalidArguments;
47use crate::dsl_util::StringLiteralParser;
48use crate::refs::RemoteRefSymbolBuf;
49
50#[derive(Parser)]
51#[grammar = "revset.pest"]
52struct RevsetParser;
53
54const STRING_LITERAL_PARSER: StringLiteralParser<Rule> = StringLiteralParser {
55 content_rule: Rule::string_content,
56 escape_rule: Rule::string_escape,
57};
58const FUNCTION_CALL_PARSER: FunctionCallParser<Rule> = FunctionCallParser {
59 function_name_rule: Rule::function_name,
60 function_arguments_rule: Rule::function_arguments,
61 keyword_argument_rule: Rule::keyword_argument,
62 argument_name_rule: Rule::strict_identifier,
63 argument_value_rule: Rule::expression,
64};
65
66impl Rule {
67 fn is_compat(&self) -> bool {
70 matches!(
71 self,
72 Rule::compat_parents_op
73 | Rule::compat_dag_range_op
74 | Rule::compat_dag_range_pre_op
75 | Rule::compat_dag_range_post_op
76 | Rule::compat_add_op
77 | Rule::compat_sub_op
78 )
79 }
80
81 fn to_symbol(self) -> Option<&'static str> {
82 match self {
83 Rule::EOI => None,
84 Rule::whitespace => None,
85 Rule::identifier_part => None,
86 Rule::identifier => None,
87 Rule::strict_identifier_part => None,
88 Rule::strict_identifier => None,
89 Rule::symbol => None,
90 Rule::string_escape => None,
91 Rule::string_content_char => None,
92 Rule::string_content => None,
93 Rule::string_literal => None,
94 Rule::raw_string_content => None,
95 Rule::raw_string_literal => None,
96 Rule::at_op => Some("@"),
97 Rule::pattern_kind_op => Some(":"),
98 Rule::parents_op => Some("-"),
99 Rule::children_op => Some("+"),
100 Rule::compat_parents_op => Some("^"),
101 Rule::dag_range_op
102 | Rule::dag_range_pre_op
103 | Rule::dag_range_post_op
104 | Rule::dag_range_all_op => Some("::"),
105 Rule::compat_dag_range_op
106 | Rule::compat_dag_range_pre_op
107 | Rule::compat_dag_range_post_op => Some(":"),
108 Rule::range_op => Some(".."),
109 Rule::range_pre_op | Rule::range_post_op | Rule::range_all_op => Some(".."),
110 Rule::range_ops => None,
111 Rule::range_pre_ops => None,
112 Rule::range_post_ops => None,
113 Rule::range_all_ops => None,
114 Rule::negate_op => Some("~"),
115 Rule::union_op => Some("|"),
116 Rule::intersection_op => Some("&"),
117 Rule::difference_op => Some("~"),
118 Rule::compat_add_op => Some("+"),
119 Rule::compat_sub_op => Some("-"),
120 Rule::infix_op => None,
121 Rule::function => None,
122 Rule::function_name => None,
123 Rule::keyword_argument => None,
124 Rule::argument => None,
125 Rule::function_arguments => None,
126 Rule::formal_parameters => None,
127 Rule::string_pattern => None,
128 Rule::primary => None,
129 Rule::neighbors_expression => None,
130 Rule::range_expression => None,
131 Rule::expression => None,
132 Rule::program_modifier => None,
133 Rule::program => None,
134 Rule::symbol_name => None,
135 Rule::function_alias_declaration => None,
136 Rule::alias_declaration => None,
137 }
138 }
139}
140
141pub type RevsetDiagnostics = Diagnostics<RevsetParseError>;
144
145#[derive(Debug, Error)]
146#[error("{pest_error}")]
147pub struct RevsetParseError {
148 kind: Box<RevsetParseErrorKind>,
149 pest_error: Box<pest::error::Error<Rule>>,
150 source: Option<Box<dyn error::Error + Send + Sync>>,
151}
152
153#[derive(Debug, Error, PartialEq, Eq)]
154pub enum RevsetParseErrorKind {
155 #[error("Syntax error")]
156 SyntaxError,
157 #[error("`{op}` is not a prefix operator")]
158 NotPrefixOperator {
159 op: String,
160 similar_op: String,
161 description: String,
162 },
163 #[error("`{op}` is not a postfix operator")]
164 NotPostfixOperator {
165 op: String,
166 similar_op: String,
167 description: String,
168 },
169 #[error("`{op}` is not an infix operator")]
170 NotInfixOperator {
171 op: String,
172 similar_op: String,
173 description: String,
174 },
175 #[error("Modifier `{0}` doesn't exist")]
176 NoSuchModifier(String),
177 #[error("Function `{name}` doesn't exist")]
178 NoSuchFunction {
179 name: String,
180 candidates: Vec<String>,
181 },
182 #[error("Function `{name}`: {message}")]
183 InvalidFunctionArguments { name: String, message: String },
184 #[error("Cannot resolve file pattern without workspace")]
185 FsPathWithoutWorkspace,
186 #[error("Cannot resolve `@` without workspace")]
187 WorkingCopyWithoutWorkspace,
188 #[error("Redefinition of function parameter")]
189 RedefinedFunctionParameter,
190 #[error("{0}")]
191 Expression(String),
192 #[error("In alias `{0}`")]
193 InAliasExpansion(String),
194 #[error("In function parameter `{0}`")]
195 InParameterExpansion(String),
196 #[error("Alias `{0}` expanded recursively")]
197 RecursiveAlias(String),
198}
199
200impl RevsetParseError {
201 pub(super) fn with_span(kind: RevsetParseErrorKind, span: pest::Span<'_>) -> Self {
202 let message = kind.to_string();
203 let pest_error = Box::new(pest::error::Error::new_from_span(
204 pest::error::ErrorVariant::CustomError { message },
205 span,
206 ));
207 RevsetParseError {
208 kind: Box::new(kind),
209 pest_error,
210 source: None,
211 }
212 }
213
214 pub(super) fn with_source(
215 mut self,
216 source: impl Into<Box<dyn error::Error + Send + Sync>>,
217 ) -> Self {
218 self.source = Some(source.into());
219 self
220 }
221
222 pub fn expression(message: impl Into<String>, span: pest::Span<'_>) -> Self {
224 Self::with_span(RevsetParseErrorKind::Expression(message.into()), span)
225 }
226
227 pub(super) fn extend_function_candidates<I>(mut self, other_functions: I) -> Self
230 where
231 I: IntoIterator,
232 I::Item: AsRef<str>,
233 {
234 if let RevsetParseErrorKind::NoSuchFunction { name, candidates } = self.kind.as_mut() {
235 let other_candidates = collect_similar(name, other_functions);
236 *candidates = itertools::merge(mem::take(candidates), other_candidates)
237 .dedup()
238 .collect();
239 }
240 self
241 }
242
243 pub fn kind(&self) -> &RevsetParseErrorKind {
244 &self.kind
245 }
246
247 pub fn origin(&self) -> Option<&Self> {
249 self.source.as_ref().and_then(|e| e.downcast_ref())
250 }
251}
252
253impl AliasExpandError for RevsetParseError {
254 fn invalid_arguments(err: InvalidArguments<'_>) -> Self {
255 err.into()
256 }
257
258 fn recursive_expansion(id: AliasId<'_>, span: pest::Span<'_>) -> Self {
259 Self::with_span(RevsetParseErrorKind::RecursiveAlias(id.to_string()), span)
260 }
261
262 fn within_alias_expansion(self, id: AliasId<'_>, span: pest::Span<'_>) -> Self {
263 let kind = match id {
264 AliasId::Symbol(_) | AliasId::Function(..) => {
265 RevsetParseErrorKind::InAliasExpansion(id.to_string())
266 }
267 AliasId::Parameter(_) => RevsetParseErrorKind::InParameterExpansion(id.to_string()),
268 };
269 Self::with_span(kind, span).with_source(self)
270 }
271}
272
273impl From<pest::error::Error<Rule>> for RevsetParseError {
274 fn from(err: pest::error::Error<Rule>) -> Self {
275 RevsetParseError {
276 kind: Box::new(RevsetParseErrorKind::SyntaxError),
277 pest_error: Box::new(rename_rules_in_pest_error(err)),
278 source: None,
279 }
280 }
281}
282
283impl From<InvalidArguments<'_>> for RevsetParseError {
284 fn from(err: InvalidArguments<'_>) -> Self {
285 let kind = RevsetParseErrorKind::InvalidFunctionArguments {
286 name: err.name.to_owned(),
287 message: err.message,
288 };
289 Self::with_span(kind, err.span)
290 }
291}
292
293fn rename_rules_in_pest_error(mut err: pest::error::Error<Rule>) -> pest::error::Error<Rule> {
294 let pest::error::ErrorVariant::ParsingError {
295 positives,
296 negatives,
297 } = &mut err.variant
298 else {
299 return err;
300 };
301
302 let mut known_syms = HashSet::new();
305 positives.retain(|rule| {
306 !rule.is_compat() && rule.to_symbol().map_or(true, |sym| known_syms.insert(sym))
307 });
308 let mut known_syms = HashSet::new();
309 negatives.retain(|rule| rule.to_symbol().map_or(true, |sym| known_syms.insert(sym)));
310 err.renamed_rules(|rule| {
311 rule.to_symbol()
312 .map(|sym| format!("`{sym}`"))
313 .unwrap_or_else(|| format!("<{rule:?}>"))
314 })
315}
316
317#[derive(Clone, Debug, Eq, PartialEq)]
318pub enum ExpressionKind<'i> {
319 Identifier(&'i str),
321 String(String),
323 StringPattern {
325 kind: &'i str,
326 value: String,
327 },
328 RemoteSymbol(RemoteRefSymbolBuf),
330 AtWorkspace(String),
332 AtCurrentWorkspace,
334 DagRangeAll,
336 RangeAll,
338 Unary(UnaryOp, Box<ExpressionNode<'i>>),
339 Binary(BinaryOp, Box<ExpressionNode<'i>>, Box<ExpressionNode<'i>>),
340 UnionAll(Vec<ExpressionNode<'i>>),
342 FunctionCall(Box<FunctionCallNode<'i>>),
343 Modifier(Box<ModifierNode<'i>>),
345 AliasExpanded(AliasId<'i>, Box<ExpressionNode<'i>>),
347}
348
349impl<'i> FoldableExpression<'i> for ExpressionKind<'i> {
350 fn fold<F>(self, folder: &mut F, span: pest::Span<'i>) -> Result<Self, F::Error>
351 where
352 F: ExpressionFolder<'i, Self> + ?Sized,
353 {
354 match self {
355 ExpressionKind::Identifier(name) => folder.fold_identifier(name, span),
356 ExpressionKind::String(_)
357 | ExpressionKind::StringPattern { .. }
358 | ExpressionKind::RemoteSymbol(_)
359 | ExpressionKind::AtWorkspace(_)
360 | ExpressionKind::AtCurrentWorkspace
361 | ExpressionKind::DagRangeAll
362 | ExpressionKind::RangeAll => Ok(self),
363 ExpressionKind::Unary(op, arg) => {
364 let arg = Box::new(folder.fold_expression(*arg)?);
365 Ok(ExpressionKind::Unary(op, arg))
366 }
367 ExpressionKind::Binary(op, lhs, rhs) => {
368 let lhs = Box::new(folder.fold_expression(*lhs)?);
369 let rhs = Box::new(folder.fold_expression(*rhs)?);
370 Ok(ExpressionKind::Binary(op, lhs, rhs))
371 }
372 ExpressionKind::UnionAll(nodes) => {
373 let nodes = dsl_util::fold_expression_nodes(folder, nodes)?;
374 Ok(ExpressionKind::UnionAll(nodes))
375 }
376 ExpressionKind::FunctionCall(function) => folder.fold_function_call(function, span),
377 ExpressionKind::Modifier(modifier) => {
378 let modifier = Box::new(ModifierNode {
379 name: modifier.name,
380 name_span: modifier.name_span,
381 body: folder.fold_expression(modifier.body)?,
382 });
383 Ok(ExpressionKind::Modifier(modifier))
384 }
385 ExpressionKind::AliasExpanded(id, subst) => {
386 let subst = Box::new(folder.fold_expression(*subst)?);
387 Ok(ExpressionKind::AliasExpanded(id, subst))
388 }
389 }
390 }
391}
392
393impl<'i> AliasExpandableExpression<'i> for ExpressionKind<'i> {
394 fn identifier(name: &'i str) -> Self {
395 ExpressionKind::Identifier(name)
396 }
397
398 fn function_call(function: Box<FunctionCallNode<'i>>) -> Self {
399 ExpressionKind::FunctionCall(function)
400 }
401
402 fn alias_expanded(id: AliasId<'i>, subst: Box<ExpressionNode<'i>>) -> Self {
403 ExpressionKind::AliasExpanded(id, subst)
404 }
405}
406
407#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
408pub enum UnaryOp {
409 Negate,
411 DagRangePre,
413 DagRangePost,
415 RangePre,
417 RangePost,
419 Parents,
421 Children,
423}
424
425#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
426pub enum BinaryOp {
427 Intersection,
429 Difference,
431 DagRange,
433 Range,
435}
436
437pub type ExpressionNode<'i> = dsl_util::ExpressionNode<'i, ExpressionKind<'i>>;
438pub type FunctionCallNode<'i> = dsl_util::FunctionCallNode<'i, ExpressionKind<'i>>;
439
440#[derive(Clone, Debug, Eq, PartialEq)]
442pub struct ModifierNode<'i> {
443 pub name: &'i str,
445 pub name_span: pest::Span<'i>,
447 pub body: ExpressionNode<'i>,
449}
450
451fn union_nodes<'i>(lhs: ExpressionNode<'i>, rhs: ExpressionNode<'i>) -> ExpressionNode<'i> {
452 let span = lhs.span.start_pos().span(&rhs.span.end_pos());
453 let expr = match lhs.kind {
454 ExpressionKind::UnionAll(mut nodes) => {
457 nodes.push(rhs);
458 ExpressionKind::UnionAll(nodes)
459 }
460 _ => ExpressionKind::UnionAll(vec![lhs, rhs]),
461 };
462 ExpressionNode::new(expr, span)
463}
464
465pub fn parse_program(revset_str: &str) -> Result<ExpressionNode, RevsetParseError> {
467 let mut pairs = RevsetParser::parse(Rule::program, revset_str)?;
468 let first = pairs.next().unwrap();
469 match first.as_rule() {
470 Rule::expression => parse_expression_node(first.into_inner()),
471 Rule::program_modifier => {
472 let (lhs, op) = first.into_inner().collect_tuple().unwrap();
473 let rhs = pairs.next().unwrap();
474 assert_eq!(lhs.as_rule(), Rule::strict_identifier);
475 assert_eq!(op.as_rule(), Rule::pattern_kind_op);
476 assert_eq!(rhs.as_rule(), Rule::expression);
477 let span = lhs.as_span().start_pos().span(&rhs.as_span().end_pos());
478 let modifier = Box::new(ModifierNode {
479 name: lhs.as_str(),
480 name_span: lhs.as_span(),
481 body: parse_expression_node(rhs.into_inner())?,
482 });
483 let expr = ExpressionKind::Modifier(modifier);
484 Ok(ExpressionNode::new(expr, span))
485 }
486 r => panic!("unexpected revset parse rule: {r:?}"),
487 }
488}
489
490fn parse_expression_node(pairs: Pairs<Rule>) -> Result<ExpressionNode, RevsetParseError> {
491 fn not_prefix_op(
492 op: &Pair<Rule>,
493 similar_op: impl Into<String>,
494 description: impl Into<String>,
495 ) -> RevsetParseError {
496 RevsetParseError::with_span(
497 RevsetParseErrorKind::NotPrefixOperator {
498 op: op.as_str().to_owned(),
499 similar_op: similar_op.into(),
500 description: description.into(),
501 },
502 op.as_span(),
503 )
504 }
505
506 fn not_postfix_op(
507 op: &Pair<Rule>,
508 similar_op: impl Into<String>,
509 description: impl Into<String>,
510 ) -> RevsetParseError {
511 RevsetParseError::with_span(
512 RevsetParseErrorKind::NotPostfixOperator {
513 op: op.as_str().to_owned(),
514 similar_op: similar_op.into(),
515 description: description.into(),
516 },
517 op.as_span(),
518 )
519 }
520
521 fn not_infix_op(
522 op: &Pair<Rule>,
523 similar_op: impl Into<String>,
524 description: impl Into<String>,
525 ) -> RevsetParseError {
526 RevsetParseError::with_span(
527 RevsetParseErrorKind::NotInfixOperator {
528 op: op.as_str().to_owned(),
529 similar_op: similar_op.into(),
530 description: description.into(),
531 },
532 op.as_span(),
533 )
534 }
535
536 static PRATT: Lazy<PrattParser<Rule>> = Lazy::new(|| {
537 PrattParser::new()
538 .op(Op::infix(Rule::union_op, Assoc::Left)
539 | Op::infix(Rule::compat_add_op, Assoc::Left))
540 .op(Op::infix(Rule::intersection_op, Assoc::Left)
541 | Op::infix(Rule::difference_op, Assoc::Left)
542 | Op::infix(Rule::compat_sub_op, Assoc::Left))
543 .op(Op::prefix(Rule::negate_op))
544 .op(Op::infix(Rule::dag_range_op, Assoc::Left)
546 | Op::infix(Rule::compat_dag_range_op, Assoc::Left)
547 | Op::infix(Rule::range_op, Assoc::Left))
548 .op(Op::prefix(Rule::dag_range_pre_op)
549 | Op::prefix(Rule::compat_dag_range_pre_op)
550 | Op::prefix(Rule::range_pre_op))
551 .op(Op::postfix(Rule::dag_range_post_op)
552 | Op::postfix(Rule::compat_dag_range_post_op)
553 | Op::postfix(Rule::range_post_op))
554 .op(Op::postfix(Rule::parents_op)
556 | Op::postfix(Rule::children_op)
557 | Op::postfix(Rule::compat_parents_op))
558 });
559 PRATT
560 .map_primary(|primary| {
561 let expr = match primary.as_rule() {
562 Rule::primary => return parse_primary_node(primary),
563 Rule::dag_range_all_op => ExpressionKind::DagRangeAll,
564 Rule::range_all_op => ExpressionKind::RangeAll,
565 r => panic!("unexpected primary rule {r:?}"),
566 };
567 Ok(ExpressionNode::new(expr, primary.as_span()))
568 })
569 .map_prefix(|op, rhs| {
570 let op_kind = match op.as_rule() {
571 Rule::negate_op => UnaryOp::Negate,
572 Rule::dag_range_pre_op => UnaryOp::DagRangePre,
573 Rule::compat_dag_range_pre_op => Err(not_prefix_op(&op, "::", "ancestors"))?,
574 Rule::range_pre_op => UnaryOp::RangePre,
575 r => panic!("unexpected prefix operator rule {r:?}"),
576 };
577 let rhs = Box::new(rhs?);
578 let span = op.as_span().start_pos().span(&rhs.span.end_pos());
579 let expr = ExpressionKind::Unary(op_kind, rhs);
580 Ok(ExpressionNode::new(expr, span))
581 })
582 .map_postfix(|lhs, op| {
583 let op_kind = match op.as_rule() {
584 Rule::dag_range_post_op => UnaryOp::DagRangePost,
585 Rule::compat_dag_range_post_op => Err(not_postfix_op(&op, "::", "descendants"))?,
586 Rule::range_post_op => UnaryOp::RangePost,
587 Rule::parents_op => UnaryOp::Parents,
588 Rule::children_op => UnaryOp::Children,
589 Rule::compat_parents_op => Err(not_postfix_op(&op, "-", "parents"))?,
590 r => panic!("unexpected postfix operator rule {r:?}"),
591 };
592 let lhs = Box::new(lhs?);
593 let span = lhs.span.start_pos().span(&op.as_span().end_pos());
594 let expr = ExpressionKind::Unary(op_kind, lhs);
595 Ok(ExpressionNode::new(expr, span))
596 })
597 .map_infix(|lhs, op, rhs| {
598 let op_kind = match op.as_rule() {
599 Rule::union_op => return Ok(union_nodes(lhs?, rhs?)),
600 Rule::compat_add_op => Err(not_infix_op(&op, "|", "union"))?,
601 Rule::intersection_op => BinaryOp::Intersection,
602 Rule::difference_op => BinaryOp::Difference,
603 Rule::compat_sub_op => Err(not_infix_op(&op, "~", "difference"))?,
604 Rule::dag_range_op => BinaryOp::DagRange,
605 Rule::compat_dag_range_op => Err(not_infix_op(&op, "::", "DAG range"))?,
606 Rule::range_op => BinaryOp::Range,
607 r => panic!("unexpected infix operator rule {r:?}"),
608 };
609 let lhs = Box::new(lhs?);
610 let rhs = Box::new(rhs?);
611 let span = lhs.span.start_pos().span(&rhs.span.end_pos());
612 let expr = ExpressionKind::Binary(op_kind, lhs, rhs);
613 Ok(ExpressionNode::new(expr, span))
614 })
615 .parse(pairs)
616}
617
618fn parse_primary_node(pair: Pair<Rule>) -> Result<ExpressionNode, RevsetParseError> {
619 let span = pair.as_span();
620 let mut pairs = pair.into_inner();
621 let first = pairs.next().unwrap();
622 let expr = match first.as_rule() {
623 Rule::expression => return parse_expression_node(first.into_inner()),
624 Rule::function => {
625 let function = Box::new(FUNCTION_CALL_PARSER.parse(
626 first,
627 |pair| Ok(pair.as_str()),
628 |pair| parse_expression_node(pair.into_inner()),
629 )?);
630 ExpressionKind::FunctionCall(function)
631 }
632 Rule::string_pattern => {
633 let (lhs, op, rhs) = first.into_inner().collect_tuple().unwrap();
634 assert_eq!(lhs.as_rule(), Rule::strict_identifier);
635 assert_eq!(op.as_rule(), Rule::pattern_kind_op);
636 let kind = lhs.as_str();
637 let value = parse_as_string_literal(rhs);
638 ExpressionKind::StringPattern { kind, value }
639 }
640 Rule::identifier if pairs.peek().is_none() => ExpressionKind::Identifier(first.as_str()),
643 Rule::identifier | Rule::string_literal | Rule::raw_string_literal => {
644 let name = parse_as_string_literal(first);
645 match pairs.next() {
646 None => ExpressionKind::String(name),
647 Some(op) => {
648 assert_eq!(op.as_rule(), Rule::at_op);
649 match pairs.next() {
650 None => ExpressionKind::AtWorkspace(name),
652 Some(second) => {
654 let remote = parse_as_string_literal(second);
655 ExpressionKind::RemoteSymbol(RemoteRefSymbolBuf { name, remote })
656 }
657 }
658 }
659 }
660 }
661 Rule::at_op => ExpressionKind::AtCurrentWorkspace,
663 r => panic!("unexpected revset parse rule: {r:?}"),
664 };
665 Ok(ExpressionNode::new(expr, span))
666}
667
668fn parse_as_string_literal(pair: Pair<Rule>) -> String {
670 match pair.as_rule() {
671 Rule::identifier => pair.as_str().to_owned(),
672 Rule::string_literal => STRING_LITERAL_PARSER.parse(pair.into_inner()),
673 Rule::raw_string_literal => {
674 let (content,) = pair.into_inner().collect_tuple().unwrap();
675 assert_eq!(content.as_rule(), Rule::raw_string_content);
676 content.as_str().to_owned()
677 }
678 _ => {
679 panic!("unexpected string literal rule: {:?}", pair.as_str());
680 }
681 }
682}
683
684pub fn is_identifier(text: &str) -> bool {
686 match RevsetParser::parse(Rule::identifier, text) {
687 Ok(mut pairs) => pairs.next().unwrap().as_span().end() == text.len(),
688 Err(_) => false,
689 }
690}
691
692pub fn parse_symbol(text: &str) -> Result<String, RevsetParseError> {
694 let mut pairs = RevsetParser::parse(Rule::symbol_name, text)?;
695 let first = pairs.next().unwrap();
696 let span = first.as_span();
697 let name = parse_as_string_literal(first);
698 if name.is_empty() {
699 Err(RevsetParseError::expression(
700 "Expected non-empty string",
701 span,
702 ))
703 } else {
704 Ok(name)
705 }
706}
707
708pub type RevsetAliasesMap = AliasesMap<RevsetAliasParser, String>;
709
710#[derive(Clone, Debug, Default)]
711pub struct RevsetAliasParser;
712
713impl AliasDeclarationParser for RevsetAliasParser {
714 type Error = RevsetParseError;
715
716 fn parse_declaration(&self, source: &str) -> Result<AliasDeclaration, Self::Error> {
717 let mut pairs = RevsetParser::parse(Rule::alias_declaration, source)?;
718 let first = pairs.next().unwrap();
719 match first.as_rule() {
720 Rule::strict_identifier => Ok(AliasDeclaration::Symbol(first.as_str().to_owned())),
721 Rule::function_alias_declaration => {
722 let (name_pair, params_pair) = first.into_inner().collect_tuple().unwrap();
723 assert_eq!(name_pair.as_rule(), Rule::function_name);
724 assert_eq!(params_pair.as_rule(), Rule::formal_parameters);
725 let name = name_pair.as_str().to_owned();
726 let params_span = params_pair.as_span();
727 let params = params_pair
728 .into_inner()
729 .map(|pair| match pair.as_rule() {
730 Rule::strict_identifier => pair.as_str().to_owned(),
731 r => panic!("unexpected formal parameter rule {r:?}"),
732 })
733 .collect_vec();
734 if params.iter().all_unique() {
735 Ok(AliasDeclaration::Function(name, params))
736 } else {
737 Err(RevsetParseError::with_span(
738 RevsetParseErrorKind::RedefinedFunctionParameter,
739 params_span,
740 ))
741 }
742 }
743 r => panic!("unexpected alias declaration rule {r:?}"),
744 }
745 }
746}
747
748impl AliasDefinitionParser for RevsetAliasParser {
749 type Output<'i> = ExpressionKind<'i>;
750 type Error = RevsetParseError;
751
752 fn parse_definition<'i>(&self, source: &'i str) -> Result<ExpressionNode<'i>, Self::Error> {
753 parse_program(source)
754 }
755}
756
757pub(super) fn expect_program_with<B, M>(
760 diagnostics: &mut RevsetDiagnostics,
761 node: &ExpressionNode,
762 parse_body: impl FnOnce(&mut RevsetDiagnostics, &ExpressionNode) -> Result<B, RevsetParseError>,
763 parse_modifier: impl FnOnce(
764 &mut RevsetDiagnostics,
765 &str,
766 pest::Span<'_>,
767 ) -> Result<M, RevsetParseError>,
768) -> Result<(B, Option<M>), RevsetParseError> {
769 expect_expression_with(diagnostics, node, |diagnostics, node| match &node.kind {
770 ExpressionKind::Modifier(modifier) => {
771 let parsed_modifier = parse_modifier(diagnostics, modifier.name, modifier.name_span)?;
772 let parsed_body = parse_body(diagnostics, &modifier.body)?;
773 Ok((parsed_body, Some(parsed_modifier)))
774 }
775 _ => Ok((parse_body(diagnostics, node)?, None)),
776 })
777}
778
779pub(super) fn expect_pattern_with<T, E: Into<Box<dyn error::Error + Send + Sync>>>(
780 diagnostics: &mut RevsetDiagnostics,
781 type_name: &str,
782 node: &ExpressionNode,
783 parse_pattern: impl FnOnce(&mut RevsetDiagnostics, &str, Option<&str>) -> Result<T, E>,
784) -> Result<T, RevsetParseError> {
785 let wrap_error = |err: E| {
786 RevsetParseError::expression(format!("Invalid {type_name}"), node.span).with_source(err)
787 };
788 expect_expression_with(diagnostics, node, |diagnostics, node| match &node.kind {
789 ExpressionKind::Identifier(name) => {
790 parse_pattern(diagnostics, name, None).map_err(wrap_error)
791 }
792 ExpressionKind::String(name) => parse_pattern(diagnostics, name, None).map_err(wrap_error),
793 ExpressionKind::StringPattern { kind, value } => {
794 parse_pattern(diagnostics, value, Some(kind)).map_err(wrap_error)
795 }
796 _ => Err(RevsetParseError::expression(
797 format!("Expected expression of {type_name}"),
798 node.span,
799 )),
800 })
801}
802
803pub fn expect_literal<T: FromStr>(
804 diagnostics: &mut RevsetDiagnostics,
805 type_name: &str,
806 node: &ExpressionNode,
807) -> Result<T, RevsetParseError> {
808 let make_error = || {
809 RevsetParseError::expression(
810 format!("Expected expression of type {type_name}"),
811 node.span,
812 )
813 };
814 expect_expression_with(diagnostics, node, |_diagnostics, node| match &node.kind {
815 ExpressionKind::Identifier(name) => name.parse().map_err(|_| make_error()),
816 ExpressionKind::String(name) => name.parse().map_err(|_| make_error()),
817 _ => Err(make_error()),
818 })
819}
820
821pub(super) fn expect_expression_with<T>(
824 diagnostics: &mut RevsetDiagnostics,
825 node: &ExpressionNode,
826 f: impl FnOnce(&mut RevsetDiagnostics, &ExpressionNode) -> Result<T, RevsetParseError>,
827) -> Result<T, RevsetParseError> {
828 if let ExpressionKind::AliasExpanded(id, subst) = &node.kind {
829 let mut inner_diagnostics = RevsetDiagnostics::new();
830 let expression = expect_expression_with(&mut inner_diagnostics, subst, f)
831 .map_err(|e| e.within_alias_expansion(*id, node.span))?;
832 diagnostics.extend_with(inner_diagnostics, |diag| {
833 diag.within_alias_expansion(*id, node.span)
834 });
835 Ok(expression)
836 } else {
837 f(diagnostics, node)
838 }
839}
840
841#[cfg(test)]
842mod tests {
843 use assert_matches::assert_matches;
844
845 use super::*;
846 use crate::dsl_util::KeywordArgument;
847
848 #[derive(Debug)]
849 struct WithRevsetAliasesMap(RevsetAliasesMap);
850
851 impl WithRevsetAliasesMap {
852 fn parse<'i>(&'i self, text: &'i str) -> Result<ExpressionNode<'i>, RevsetParseError> {
853 let node = parse_program(text)?;
854 dsl_util::expand_aliases(node, &self.0)
855 }
856
857 fn parse_normalized<'i>(&'i self, text: &'i str) -> ExpressionNode<'i> {
858 normalize_tree(self.parse(text).unwrap())
859 }
860 }
861
862 fn with_aliases(
863 aliases: impl IntoIterator<Item = (impl AsRef<str>, impl Into<String>)>,
864 ) -> WithRevsetAliasesMap {
865 let mut aliases_map = RevsetAliasesMap::new();
866 for (decl, defn) in aliases {
867 aliases_map.insert(decl, defn).unwrap();
868 }
869 WithRevsetAliasesMap(aliases_map)
870 }
871
872 fn parse_into_kind(text: &str) -> Result<ExpressionKind, RevsetParseErrorKind> {
873 parse_program(text)
874 .map(|node| node.kind)
875 .map_err(|err| *err.kind)
876 }
877
878 fn parse_normalized(text: &str) -> ExpressionNode {
879 normalize_tree(parse_program(text).unwrap())
880 }
881
882 fn normalize_tree(node: ExpressionNode) -> ExpressionNode {
884 fn empty_span() -> pest::Span<'static> {
885 pest::Span::new("", 0, 0).unwrap()
886 }
887
888 fn normalize_list(nodes: Vec<ExpressionNode>) -> Vec<ExpressionNode> {
889 nodes.into_iter().map(normalize_tree).collect()
890 }
891
892 fn normalize_function_call(function: FunctionCallNode) -> FunctionCallNode {
893 FunctionCallNode {
894 name: function.name,
895 name_span: empty_span(),
896 args: normalize_list(function.args),
897 keyword_args: function
898 .keyword_args
899 .into_iter()
900 .map(|arg| KeywordArgument {
901 name: arg.name,
902 name_span: empty_span(),
903 value: normalize_tree(arg.value),
904 })
905 .collect(),
906 args_span: empty_span(),
907 }
908 }
909
910 let normalized_kind = match node.kind {
911 ExpressionKind::Identifier(_)
912 | ExpressionKind::String(_)
913 | ExpressionKind::StringPattern { .. }
914 | ExpressionKind::RemoteSymbol(_)
915 | ExpressionKind::AtWorkspace(_)
916 | ExpressionKind::AtCurrentWorkspace
917 | ExpressionKind::DagRangeAll
918 | ExpressionKind::RangeAll => node.kind,
919 ExpressionKind::Unary(op, arg) => {
920 let arg = Box::new(normalize_tree(*arg));
921 ExpressionKind::Unary(op, arg)
922 }
923 ExpressionKind::Binary(op, lhs, rhs) => {
924 let lhs = Box::new(normalize_tree(*lhs));
925 let rhs = Box::new(normalize_tree(*rhs));
926 ExpressionKind::Binary(op, lhs, rhs)
927 }
928 ExpressionKind::UnionAll(nodes) => {
929 let nodes = normalize_list(nodes);
930 ExpressionKind::UnionAll(nodes)
931 }
932 ExpressionKind::FunctionCall(function) => {
933 let function = Box::new(normalize_function_call(*function));
934 ExpressionKind::FunctionCall(function)
935 }
936 ExpressionKind::Modifier(modifier) => {
937 let modifier = Box::new(ModifierNode {
938 name: modifier.name,
939 name_span: empty_span(),
940 body: normalize_tree(modifier.body),
941 });
942 ExpressionKind::Modifier(modifier)
943 }
944 ExpressionKind::AliasExpanded(_, subst) => normalize_tree(*subst).kind,
945 };
946 ExpressionNode {
947 kind: normalized_kind,
948 span: empty_span(),
949 }
950 }
951
952 #[test]
953 fn test_parse_tree_eq() {
954 assert_eq!(
955 parse_normalized(r#" foo( x ) | ~bar:"baz" "#),
956 parse_normalized(r#"(foo(x))|(~(bar:"baz"))"#)
957 );
958 assert_ne!(parse_normalized(r#" foo "#), parse_normalized(r#" "foo" "#));
959 }
960
961 #[test]
962 fn test_parse_revset() {
963 assert_eq!(
965 parse_into_kind("\"foo\""),
966 Ok(ExpressionKind::String("foo".to_owned()))
967 );
968 assert_eq!(
969 parse_into_kind("'foo'"),
970 Ok(ExpressionKind::String("foo".to_owned()))
971 );
972 assert_matches!(
974 parse_into_kind("foo-"),
975 Ok(ExpressionKind::Unary(UnaryOp::Parents, _))
976 );
977 assert_matches!(
979 parse_into_kind("foo+"),
980 Ok(ExpressionKind::Unary(UnaryOp::Children, _))
981 );
982 assert_matches!(
984 parse_into_kind("::foo"),
985 Ok(ExpressionKind::Unary(UnaryOp::DagRangePre, _))
986 );
987 assert_matches!(
989 parse_into_kind("foo::"),
990 Ok(ExpressionKind::Unary(UnaryOp::DagRangePost, _))
991 );
992 assert_matches!(
994 parse_into_kind("foo::bar"),
995 Ok(ExpressionKind::Binary(BinaryOp::DagRange, _, _))
996 );
997 assert_matches!(parse_into_kind("::"), Ok(ExpressionKind::DagRangeAll));
999 assert_matches!(
1001 parse_into_kind("..foo"),
1002 Ok(ExpressionKind::Unary(UnaryOp::RangePre, _))
1003 );
1004 assert_matches!(
1005 parse_into_kind("foo.."),
1006 Ok(ExpressionKind::Unary(UnaryOp::RangePost, _))
1007 );
1008 assert_matches!(
1009 parse_into_kind("foo..bar"),
1010 Ok(ExpressionKind::Binary(BinaryOp::Range, _, _))
1011 );
1012 assert_matches!(parse_into_kind(".."), Ok(ExpressionKind::RangeAll));
1014 assert_matches!(
1016 parse_into_kind("~ foo"),
1017 Ok(ExpressionKind::Unary(UnaryOp::Negate, _))
1018 );
1019 assert_eq!(
1020 parse_normalized("~ ~~ foo"),
1021 parse_normalized("~(~(~(foo)))"),
1022 );
1023 assert_matches!(
1025 parse_into_kind("foo & bar"),
1026 Ok(ExpressionKind::Binary(BinaryOp::Intersection, _, _))
1027 );
1028 assert_matches!(
1030 parse_into_kind("foo | bar"),
1031 Ok(ExpressionKind::UnionAll(nodes)) if nodes.len() == 2
1032 );
1033 assert_matches!(
1034 parse_into_kind("foo | bar | baz"),
1035 Ok(ExpressionKind::UnionAll(nodes)) if nodes.len() == 3
1036 );
1037 assert_matches!(
1039 parse_into_kind("foo ~ bar"),
1040 Ok(ExpressionKind::Binary(BinaryOp::Difference, _, _))
1041 );
1042 assert_eq!(parse_normalized("(foo)-"), parse_normalized("foo-"));
1044 assert_eq!(parse_normalized(" ::foo "), parse_normalized("::foo"));
1046 assert_eq!(parse_normalized("( ::foo )"), parse_normalized("::foo"));
1047 assert_eq!(
1049 parse_into_kind(" :: foo "),
1050 Err(RevsetParseErrorKind::SyntaxError)
1051 );
1052 assert_eq!(
1054 parse_into_kind("foo | -"),
1055 Err(RevsetParseErrorKind::SyntaxError)
1056 );
1057 assert_eq!(
1059 parse_normalized(
1060 " description( arg1 ) ~ file( arg1 , arg2 ) ~ visible_heads( ) ",
1061 ),
1062 parse_normalized("(description(arg1) ~ file(arg1, arg2)) ~ visible_heads()"),
1063 );
1064 assert_eq!(
1066 parse_normalized("remote_bookmarks( remote = foo )"),
1067 parse_normalized("remote_bookmarks(remote=foo)"),
1068 );
1069
1070 assert!(parse_into_kind("bookmarks(,)").is_err());
1072 assert_eq!(
1074 parse_normalized("bookmarks(a,)"),
1075 parse_normalized("bookmarks(a)")
1076 );
1077 assert_eq!(
1078 parse_normalized("bookmarks(a , )"),
1079 parse_normalized("bookmarks(a)")
1080 );
1081 assert!(parse_into_kind("bookmarks(,a)").is_err());
1082 assert!(parse_into_kind("bookmarks(a,,)").is_err());
1083 assert!(parse_into_kind("bookmarks(a , , )").is_err());
1084 assert_eq!(
1085 parse_normalized("file(a,b,)"),
1086 parse_normalized("file(a, b)")
1087 );
1088 assert!(parse_into_kind("file(a,,b)").is_err());
1089 assert_eq!(
1090 parse_normalized("remote_bookmarks(a,remote=b , )"),
1091 parse_normalized("remote_bookmarks(a, remote=b)"),
1092 );
1093 assert!(parse_into_kind("remote_bookmarks(a,,remote=b)").is_err());
1094 }
1095
1096 #[test]
1097 fn test_parse_revset_with_modifier() {
1098 assert_eq!(
1100 parse_into_kind("all:"),
1101 Err(RevsetParseErrorKind::SyntaxError)
1102 );
1103 assert_matches!(
1104 parse_into_kind("all:foo"),
1105 Ok(ExpressionKind::Modifier(modifier)) if modifier.name == "all"
1106 );
1107 assert_matches!(
1108 parse_into_kind("all::"),
1109 Ok(ExpressionKind::Unary(UnaryOp::DagRangePost, _))
1110 );
1111 assert_matches!(
1112 parse_into_kind("all::foo"),
1113 Ok(ExpressionKind::Binary(BinaryOp::DagRange, _, _))
1114 );
1115
1116 assert_eq!(
1118 parse_into_kind("all:::"),
1119 Err(RevsetParseErrorKind::SyntaxError)
1120 );
1121 assert_eq!(
1122 parse_into_kind("all:::foo"),
1123 Err(RevsetParseErrorKind::SyntaxError)
1124 );
1125
1126 assert_eq!(parse_normalized("all:(foo)"), parse_normalized("all:foo"));
1127 assert_eq!(
1128 parse_normalized("all:all::foo"),
1129 parse_normalized("all:(all::foo)"),
1130 );
1131 assert_eq!(
1132 parse_normalized("all:all | foo"),
1133 parse_normalized("all:(all | foo)"),
1134 );
1135
1136 assert_eq!(
1137 parse_normalized("all: ::foo"),
1138 parse_normalized("all:(::foo)"),
1139 );
1140 assert_eq!(parse_normalized(" all: foo"), parse_normalized("all:foo"));
1141 assert_eq!(
1142 parse_into_kind("(all:foo)"),
1143 Ok(ExpressionKind::StringPattern {
1144 kind: "all",
1145 value: "foo".to_owned()
1146 })
1147 );
1148 assert_matches!(
1149 parse_into_kind("all :foo"),
1150 Err(RevsetParseErrorKind::SyntaxError)
1151 );
1152 assert_eq!(
1153 parse_normalized("all:all:all"),
1154 parse_normalized("all:(all:all)"),
1155 );
1156 }
1157
1158 #[test]
1159 fn test_parse_whitespace() {
1160 let ascii_whitespaces: String = ('\x00'..='\x7f')
1161 .filter(char::is_ascii_whitespace)
1162 .collect();
1163 assert_eq!(
1164 parse_normalized(&format!("{ascii_whitespaces}all()")),
1165 parse_normalized("all()"),
1166 );
1167 }
1168
1169 #[test]
1170 fn test_parse_identifier() {
1171 assert_eq!(parse_into_kind("0"), Ok(ExpressionKind::Identifier("0")));
1173 assert_eq!(
1175 parse_into_kind("foo_bar/baz"),
1176 Ok(ExpressionKind::Identifier("foo_bar/baz"))
1177 );
1178
1179 assert_eq!(
1181 parse_into_kind("foo.bar-v1+7"),
1182 Ok(ExpressionKind::Identifier("foo.bar-v1+7"))
1183 );
1184 assert_eq!(
1185 parse_normalized("foo.bar-v1+7-"),
1186 parse_normalized("(foo.bar-v1+7)-")
1187 );
1188 assert_eq!(
1190 parse_into_kind(".foo"),
1191 Err(RevsetParseErrorKind::SyntaxError)
1192 );
1193 assert_eq!(
1194 parse_into_kind("foo."),
1195 Err(RevsetParseErrorKind::SyntaxError)
1196 );
1197 assert_eq!(
1199 parse_into_kind("foo.+bar"),
1200 Err(RevsetParseErrorKind::SyntaxError)
1201 );
1202 assert_eq!(
1203 parse_into_kind("foo--bar"),
1204 Err(RevsetParseErrorKind::SyntaxError)
1205 );
1206 assert_eq!(
1207 parse_into_kind("foo+-bar"),
1208 Err(RevsetParseErrorKind::SyntaxError)
1209 );
1210
1211 assert_eq!(parse_normalized("(foo)"), parse_normalized("foo"));
1213
1214 assert_eq!(
1216 parse_into_kind("柔術+jj"),
1217 Ok(ExpressionKind::Identifier("柔術+jj"))
1218 );
1219 }
1220
1221 #[test]
1222 fn test_parse_string_literal() {
1223 assert_eq!(
1225 parse_into_kind(r#" "\t\r\n\"\\\0\e" "#),
1226 Ok(ExpressionKind::String("\t\r\n\"\\\0\u{1b}".to_owned()))
1227 );
1228
1229 assert_eq!(
1231 parse_into_kind(r#" "\y" "#),
1232 Err(RevsetParseErrorKind::SyntaxError)
1233 );
1234
1235 assert_eq!(
1237 parse_into_kind(r#" '' "#),
1238 Ok(ExpressionKind::String("".to_owned()))
1239 );
1240 assert_eq!(
1241 parse_into_kind(r#" 'a\n' "#),
1242 Ok(ExpressionKind::String(r"a\n".to_owned()))
1243 );
1244 assert_eq!(
1245 parse_into_kind(r#" '\' "#),
1246 Ok(ExpressionKind::String(r"\".to_owned()))
1247 );
1248 assert_eq!(
1249 parse_into_kind(r#" '"' "#),
1250 Ok(ExpressionKind::String(r#"""#.to_owned()))
1251 );
1252
1253 assert_eq!(
1255 parse_into_kind(r#""\x61\x65\x69\x6f\x75""#),
1256 Ok(ExpressionKind::String("aeiou".to_owned()))
1257 );
1258 assert_eq!(
1259 parse_into_kind(r#""\xe0\xe8\xec\xf0\xf9""#),
1260 Ok(ExpressionKind::String("àèìðù".to_owned()))
1261 );
1262 assert_eq!(
1263 parse_into_kind(r#""\x""#),
1264 Err(RevsetParseErrorKind::SyntaxError)
1265 );
1266 assert_eq!(
1267 parse_into_kind(r#""\xf""#),
1268 Err(RevsetParseErrorKind::SyntaxError)
1269 );
1270 assert_eq!(
1271 parse_into_kind(r#""\xgg""#),
1272 Err(RevsetParseErrorKind::SyntaxError)
1273 );
1274 }
1275
1276 #[test]
1277 fn test_parse_string_pattern() {
1278 assert_eq!(
1279 parse_into_kind(r#"(substring:"foo")"#),
1280 Ok(ExpressionKind::StringPattern {
1281 kind: "substring",
1282 value: "foo".to_owned()
1283 })
1284 );
1285 assert_eq!(
1286 parse_into_kind(r#"("exact:foo")"#),
1287 Ok(ExpressionKind::String("exact:foo".to_owned()))
1288 );
1289 assert_eq!(
1290 parse_normalized(r#"(exact:"foo" )"#),
1291 parse_normalized(r#"(exact:"foo")"#),
1292 );
1293 assert_eq!(
1294 parse_into_kind(r#"(exact:'\')"#),
1295 Ok(ExpressionKind::StringPattern {
1296 kind: "exact",
1297 value: r"\".to_owned()
1298 })
1299 );
1300 assert_matches!(
1301 parse_into_kind(r#"(exact:("foo" ))"#),
1302 Err(RevsetParseErrorKind::NotInfixOperator { .. })
1303 );
1304 }
1305
1306 #[test]
1307 fn test_parse_symbol_explicitly() {
1308 assert_matches!(parse_symbol("").as_deref(), Err(_));
1309 assert_matches!(parse_symbol("''").as_deref(), Err(_));
1312
1313 assert_matches!(parse_symbol("foo.bar").as_deref(), Ok("foo.bar"));
1314 assert_matches!(parse_symbol("foo@bar").as_deref(), Err(_));
1315 assert_matches!(parse_symbol("foo bar").as_deref(), Err(_));
1316
1317 assert_matches!(parse_symbol("'foo bar'").as_deref(), Ok("foo bar"));
1318 assert_matches!(parse_symbol(r#""foo\tbar""#).as_deref(), Ok("foo\tbar"));
1319
1320 assert_matches!(parse_symbol(" foo").as_deref(), Err(_));
1322 assert_matches!(parse_symbol("foo ").as_deref(), Err(_));
1323
1324 assert_matches!(parse_symbol("(foo)").as_deref(), Err(_));
1327 }
1328
1329 #[test]
1330 fn parse_at_workspace_and_remote_symbol() {
1331 assert_eq!(parse_into_kind("@"), Ok(ExpressionKind::AtCurrentWorkspace));
1333 assert_eq!(
1334 parse_into_kind("main@"),
1335 Ok(ExpressionKind::AtWorkspace("main".to_owned()))
1336 );
1337 assert_eq!(
1338 parse_into_kind("main@origin"),
1339 Ok(ExpressionKind::RemoteSymbol(RemoteRefSymbolBuf {
1340 name: "main".to_owned(),
1341 remote: "origin".to_owned()
1342 }))
1343 );
1344
1345 assert_eq!(
1347 parse_into_kind(r#""foo bar"@"#),
1348 Ok(ExpressionKind::AtWorkspace("foo bar".to_owned()))
1349 );
1350 assert_eq!(
1351 parse_into_kind(r#""foo bar"@origin"#),
1352 Ok(ExpressionKind::RemoteSymbol(RemoteRefSymbolBuf {
1353 name: "foo bar".to_owned(),
1354 remote: "origin".to_owned()
1355 }))
1356 );
1357 assert_eq!(
1358 parse_into_kind(r#"main@"foo bar""#),
1359 Ok(ExpressionKind::RemoteSymbol(RemoteRefSymbolBuf {
1360 name: "main".to_owned(),
1361 remote: "foo bar".to_owned()
1362 }))
1363 );
1364 assert_eq!(
1365 parse_into_kind(r#"'foo bar'@'bar baz'"#),
1366 Ok(ExpressionKind::RemoteSymbol(RemoteRefSymbolBuf {
1367 name: "foo bar".to_owned(),
1368 remote: "bar baz".to_owned()
1369 }))
1370 );
1371
1372 assert_eq!(
1374 parse_into_kind(r#""@""#),
1375 Ok(ExpressionKind::String("@".to_owned()))
1376 );
1377 assert_eq!(
1378 parse_into_kind(r#""main@""#),
1379 Ok(ExpressionKind::String("main@".to_owned()))
1380 );
1381 assert_eq!(
1382 parse_into_kind(r#""main@origin""#),
1383 Ok(ExpressionKind::String("main@origin".to_owned()))
1384 );
1385
1386 assert_eq!(
1388 parse_into_kind("柔術@"),
1389 Ok(ExpressionKind::AtWorkspace("柔術".to_owned()))
1390 );
1391 assert_eq!(
1392 parse_into_kind("柔@術"),
1393 Ok(ExpressionKind::RemoteSymbol(RemoteRefSymbolBuf {
1394 name: "柔".to_owned(),
1395 remote: "術".to_owned()
1396 }))
1397 );
1398 }
1399
1400 #[test]
1401 fn test_parse_revset_alias_symbol_decl() {
1402 let mut aliases_map = RevsetAliasesMap::new();
1403 assert!(aliases_map.insert("@", "none()").is_err());
1405 assert!(aliases_map.insert("a@", "none()").is_err());
1406 assert!(aliases_map.insert("a@b", "none()").is_err());
1407 assert!(aliases_map.insert("柔術", "none()").is_err());
1410 }
1411
1412 #[test]
1413 fn test_parse_revset_alias_func_decl() {
1414 let mut aliases_map = RevsetAliasesMap::new();
1415 assert!(aliases_map.insert("5func()", r#""is function 0""#).is_err());
1416 aliases_map.insert("func()", r#""is function 0""#).unwrap();
1417 aliases_map
1418 .insert("func(a, b)", r#""is function 2""#)
1419 .unwrap();
1420 aliases_map.insert("func(a)", r#""is function a""#).unwrap();
1421 aliases_map.insert("func(b)", r#""is function b""#).unwrap();
1422
1423 let (id, params, defn) = aliases_map.get_function("func", 0).unwrap();
1424 assert_eq!(id, AliasId::Function("func", &[]));
1425 assert!(params.is_empty());
1426 assert_eq!(defn, r#""is function 0""#);
1427
1428 let (id, params, defn) = aliases_map.get_function("func", 1).unwrap();
1429 assert_eq!(id, AliasId::Function("func", &["b".to_owned()]));
1430 assert_eq!(params, ["b"]);
1431 assert_eq!(defn, r#""is function b""#);
1432
1433 let (id, params, defn) = aliases_map.get_function("func", 2).unwrap();
1434 assert_eq!(
1435 id,
1436 AliasId::Function("func", &["a".to_owned(), "b".to_owned()])
1437 );
1438 assert_eq!(params, ["a", "b"]);
1439 assert_eq!(defn, r#""is function 2""#);
1440
1441 assert!(aliases_map.get_function("func", 3).is_none());
1442 }
1443
1444 #[test]
1445 fn test_parse_revset_alias_formal_parameter() {
1446 let mut aliases_map = RevsetAliasesMap::new();
1447 assert!(aliases_map.insert("f(@)", "none()").is_err());
1449 assert!(aliases_map.insert("f(a@)", "none()").is_err());
1450 assert!(aliases_map.insert("f(a@b)", "none()").is_err());
1451 assert!(aliases_map.insert("f(,)", "none()").is_err());
1453 assert!(aliases_map.insert("g(a,)", "none()").is_ok());
1455 assert!(aliases_map.insert("h(a , )", "none()").is_ok());
1456 assert!(aliases_map.insert("i(,a)", "none()").is_err());
1457 assert!(aliases_map.insert("j(a,,)", "none()").is_err());
1458 assert!(aliases_map.insert("k(a , , )", "none()").is_err());
1459 assert!(aliases_map.insert("l(a,b,)", "none()").is_ok());
1460 assert!(aliases_map.insert("m(a,,b)", "none()").is_err());
1461 }
1462
1463 #[test]
1464 fn test_parse_revset_compat_operator() {
1465 assert_eq!(
1466 parse_into_kind(":foo"),
1467 Err(RevsetParseErrorKind::NotPrefixOperator {
1468 op: ":".to_owned(),
1469 similar_op: "::".to_owned(),
1470 description: "ancestors".to_owned(),
1471 })
1472 );
1473 assert_eq!(
1474 parse_into_kind("foo^"),
1475 Err(RevsetParseErrorKind::NotPostfixOperator {
1476 op: "^".to_owned(),
1477 similar_op: "-".to_owned(),
1478 description: "parents".to_owned(),
1479 })
1480 );
1481 assert_eq!(
1482 parse_into_kind("foo + bar"),
1483 Err(RevsetParseErrorKind::NotInfixOperator {
1484 op: "+".to_owned(),
1485 similar_op: "|".to_owned(),
1486 description: "union".to_owned(),
1487 })
1488 );
1489 assert_eq!(
1490 parse_into_kind("foo - bar"),
1491 Err(RevsetParseErrorKind::NotInfixOperator {
1492 op: "-".to_owned(),
1493 similar_op: "~".to_owned(),
1494 description: "difference".to_owned(),
1495 })
1496 );
1497 }
1498
1499 #[test]
1500 fn test_parse_revset_operator_combinations() {
1501 assert_eq!(parse_normalized("foo---"), parse_normalized("((foo-)-)-"));
1503 assert_eq!(parse_normalized("foo+++"), parse_normalized("((foo+)+)+"));
1505 assert_eq!(parse_normalized("~x|y"), parse_normalized("(~x)|y"));
1507 assert_eq!(parse_normalized("x&~y"), parse_normalized("x&(~y)"));
1508 assert_eq!(parse_normalized("x~~y"), parse_normalized("x~(~y)"));
1509 assert_eq!(parse_normalized("x~~~y"), parse_normalized("x~(~(~y))"));
1510 assert_eq!(parse_normalized("~x::y"), parse_normalized("~(x::y)"));
1511 assert_eq!(parse_normalized("x|y|z"), parse_normalized("(x|y)|z"));
1512 assert_eq!(parse_normalized("x&y|z"), parse_normalized("(x&y)|z"));
1513 assert_eq!(parse_normalized("x|y&z"), parse_normalized("x|(y&z)"));
1514 assert_eq!(parse_normalized("x|y~z"), parse_normalized("x|(y~z)"));
1515 assert_eq!(parse_normalized("::&.."), parse_normalized("(::)&(..)"));
1516 assert_eq!(
1518 parse_into_kind("::foo::"),
1519 Err(RevsetParseErrorKind::SyntaxError)
1520 );
1521 assert_eq!(
1522 parse_into_kind(":::foo"),
1523 Err(RevsetParseErrorKind::SyntaxError)
1524 );
1525 assert_eq!(
1526 parse_into_kind("::::foo"),
1527 Err(RevsetParseErrorKind::SyntaxError)
1528 );
1529 assert_eq!(
1530 parse_into_kind("foo:::"),
1531 Err(RevsetParseErrorKind::SyntaxError)
1532 );
1533 assert_eq!(
1534 parse_into_kind("foo::::"),
1535 Err(RevsetParseErrorKind::SyntaxError)
1536 );
1537 assert_eq!(
1538 parse_into_kind("foo:::bar"),
1539 Err(RevsetParseErrorKind::SyntaxError)
1540 );
1541 assert_eq!(
1542 parse_into_kind("foo::::bar"),
1543 Err(RevsetParseErrorKind::SyntaxError)
1544 );
1545 assert_eq!(
1546 parse_into_kind("::foo::bar"),
1547 Err(RevsetParseErrorKind::SyntaxError)
1548 );
1549 assert_eq!(
1550 parse_into_kind("foo::bar::"),
1551 Err(RevsetParseErrorKind::SyntaxError)
1552 );
1553 assert_eq!(
1554 parse_into_kind("::::"),
1555 Err(RevsetParseErrorKind::SyntaxError)
1556 );
1557 assert_eq!(
1558 parse_into_kind("....foo"),
1559 Err(RevsetParseErrorKind::SyntaxError)
1560 );
1561 assert_eq!(
1562 parse_into_kind("foo...."),
1563 Err(RevsetParseErrorKind::SyntaxError)
1564 );
1565 assert_eq!(
1566 parse_into_kind("foo.....bar"),
1567 Err(RevsetParseErrorKind::SyntaxError)
1568 );
1569 assert_eq!(
1570 parse_into_kind("..foo..bar"),
1571 Err(RevsetParseErrorKind::SyntaxError)
1572 );
1573 assert_eq!(
1574 parse_into_kind("foo..bar.."),
1575 Err(RevsetParseErrorKind::SyntaxError)
1576 );
1577 assert_eq!(
1578 parse_into_kind("...."),
1579 Err(RevsetParseErrorKind::SyntaxError)
1580 );
1581 assert_eq!(
1582 parse_into_kind("::.."),
1583 Err(RevsetParseErrorKind::SyntaxError)
1584 );
1585 assert_eq!(parse_normalized("foo-+"), parse_normalized("(foo-)+"));
1588 assert_eq!(parse_normalized("foo-::"), parse_normalized("(foo-)::"));
1589 assert_eq!(parse_normalized("::foo+"), parse_normalized("::(foo+)"));
1590 assert_eq!(
1591 parse_into_kind("::-"),
1592 Err(RevsetParseErrorKind::SyntaxError)
1593 );
1594 assert_eq!(
1595 parse_into_kind("..+"),
1596 Err(RevsetParseErrorKind::SyntaxError)
1597 );
1598 }
1599
1600 #[test]
1601 fn test_parse_revset_function() {
1602 assert_matches!(
1603 parse_into_kind("parents(foo)"),
1604 Ok(ExpressionKind::FunctionCall(_))
1605 );
1606 assert_eq!(
1607 parse_normalized("parents((foo))"),
1608 parse_normalized("parents(foo)"),
1609 );
1610 assert_eq!(
1611 parse_into_kind("parents(foo"),
1612 Err(RevsetParseErrorKind::SyntaxError)
1613 );
1614 }
1615
1616 #[test]
1617 fn test_expand_symbol_alias() {
1618 assert_eq!(
1619 with_aliases([("AB", "a&b")]).parse_normalized("AB|c"),
1620 parse_normalized("(a&b)|c")
1621 );
1622 assert_eq!(
1623 with_aliases([("AB", "a|b")]).parse_normalized("AB::heads(AB)"),
1624 parse_normalized("(a|b)::heads(a|b)")
1625 );
1626
1627 assert_eq!(
1629 with_aliases([("BC", "b|c")]).parse_normalized("a&BC"),
1630 parse_normalized("a&(b|c)")
1631 );
1632
1633 assert_eq!(
1635 with_aliases([("A", "a")]).parse_normalized(r#"A|"A"|'A'"#),
1636 parse_normalized("a|'A'|'A'")
1637 );
1638
1639 assert_eq!(
1641 with_aliases([("A", "a")]).parse_normalized("author(exact:A)"),
1642 parse_normalized("author(exact:A)")
1643 );
1644
1645 assert_eq!(
1647 with_aliases([("A", "a")]).parse_normalized("A@"),
1648 parse_normalized("A@")
1649 );
1650 assert_eq!(
1651 with_aliases([("A", "a")]).parse_normalized("A@b"),
1652 parse_normalized("A@b")
1653 );
1654 assert_eq!(
1655 with_aliases([("B", "b")]).parse_normalized("a@B"),
1656 parse_normalized("a@B")
1657 );
1658
1659 assert_eq!(
1661 with_aliases([("all", "ALL")]).parse_normalized("all:all"),
1662 parse_normalized("all:ALL")
1663 );
1664
1665 assert_eq!(
1667 with_aliases([("A", "all:a")]).parse_normalized("A"),
1668 parse_normalized("all:a")
1669 );
1670
1671 assert_eq!(
1673 with_aliases([("A", "BC"), ("BC", "b|C"), ("C", "c")]).parse_normalized("A"),
1674 parse_normalized("b|c")
1675 );
1676
1677 assert_eq!(
1679 *with_aliases([("A", "A")]).parse("A").unwrap_err().kind,
1680 RevsetParseErrorKind::InAliasExpansion("A".to_owned())
1681 );
1682 assert_eq!(
1683 *with_aliases([("A", "B"), ("B", "b|C"), ("C", "c|B")])
1684 .parse("A")
1685 .unwrap_err()
1686 .kind,
1687 RevsetParseErrorKind::InAliasExpansion("A".to_owned())
1688 );
1689
1690 assert_eq!(
1692 *with_aliases([("A", "a(")]).parse("A").unwrap_err().kind,
1693 RevsetParseErrorKind::InAliasExpansion("A".to_owned())
1694 );
1695 }
1696
1697 #[test]
1698 fn test_expand_function_alias() {
1699 assert_eq!(
1700 with_aliases([("F( )", "a")]).parse_normalized("F()"),
1701 parse_normalized("a")
1702 );
1703 assert_eq!(
1704 with_aliases([("F( x )", "x")]).parse_normalized("F(a)"),
1705 parse_normalized("a")
1706 );
1707 assert_eq!(
1708 with_aliases([("F( x, y )", "x|y")]).parse_normalized("F(a, b)"),
1709 parse_normalized("a|b")
1710 );
1711
1712 assert_eq!(
1714 with_aliases([("F(x)", "F(x,b)"), ("F(x,y)", "x|y")]).parse_normalized("F(a)"),
1715 parse_normalized("a|b")
1716 );
1717
1718 assert_eq!(
1720 with_aliases([("F(x,y)", "x|y")]).parse_normalized("F(a::y,b::x)"),
1721 parse_normalized("(a::y)|(b::x)")
1722 );
1723 assert_eq!(
1725 with_aliases([("F(x)", "G(x)&y"), ("G(y)", "x|y")]).parse_normalized("F(a)"),
1726 parse_normalized("(x|a)&y")
1727 );
1728 assert_eq!(
1730 with_aliases([("F(x)", "G(x)&y"), ("G(y)", "x|y")]).parse_normalized("F(G(a))"),
1731 parse_normalized("(x|(x|a))&y")
1732 );
1733
1734 assert_eq!(
1736 with_aliases([("F(X)", "X"), ("X", "x")]).parse_normalized("F(a)|X"),
1737 parse_normalized("a|x")
1738 );
1739
1740 assert_eq!(
1742 with_aliases([("F(x)", "x|A"), ("A", "x")]).parse_normalized("F(a)"),
1743 parse_normalized("a|x")
1744 );
1745
1746 assert_eq!(
1748 with_aliases([("F(x)", r#"x|"x""#)]).parse_normalized("F(a)"),
1749 parse_normalized("a|'x'")
1750 );
1751
1752 assert_eq!(
1754 with_aliases([("F(x)", "all:x")]).parse_normalized("F(a|b)"),
1755 parse_normalized("all:(a|b)")
1756 );
1757
1758 assert_eq!(
1760 with_aliases([("A()", "A"), ("A", "a")]).parse_normalized("A()"),
1761 parse_normalized("a")
1762 );
1763
1764 assert_eq!(
1766 *with_aliases([("F()", "x")]).parse("F(a)").unwrap_err().kind,
1767 RevsetParseErrorKind::InvalidFunctionArguments {
1768 name: "F".to_owned(),
1769 message: "Expected 0 arguments".to_owned()
1770 }
1771 );
1772 assert_eq!(
1773 *with_aliases([("F(x)", "x")]).parse("F()").unwrap_err().kind,
1774 RevsetParseErrorKind::InvalidFunctionArguments {
1775 name: "F".to_owned(),
1776 message: "Expected 1 arguments".to_owned()
1777 }
1778 );
1779 assert_eq!(
1780 *with_aliases([("F(x,y)", "x|y")])
1781 .parse("F(a,b,c)")
1782 .unwrap_err()
1783 .kind,
1784 RevsetParseErrorKind::InvalidFunctionArguments {
1785 name: "F".to_owned(),
1786 message: "Expected 2 arguments".to_owned()
1787 }
1788 );
1789 assert_eq!(
1790 *with_aliases([("F(x)", "x"), ("F(x,y)", "x|y")])
1791 .parse("F()")
1792 .unwrap_err()
1793 .kind,
1794 RevsetParseErrorKind::InvalidFunctionArguments {
1795 name: "F".to_owned(),
1796 message: "Expected 1 to 2 arguments".to_owned()
1797 }
1798 );
1799 assert_eq!(
1800 *with_aliases([("F()", "x"), ("F(x,y)", "x|y")])
1801 .parse("F(a)")
1802 .unwrap_err()
1803 .kind,
1804 RevsetParseErrorKind::InvalidFunctionArguments {
1805 name: "F".to_owned(),
1806 message: "Expected 0, 2 arguments".to_owned()
1807 }
1808 );
1809
1810 assert_eq!(
1812 *with_aliases([("F(x)", "x")])
1813 .parse("F(x=y)")
1814 .unwrap_err()
1815 .kind,
1816 RevsetParseErrorKind::InvalidFunctionArguments {
1817 name: "F".to_owned(),
1818 message: "Unexpected keyword arguments".to_owned()
1819 }
1820 );
1821
1822 assert_eq!(
1824 *with_aliases([("F(x)", "G(x)"), ("G(x)", "H(x)"), ("H(x)", "F(x)")])
1825 .parse("F(a)")
1826 .unwrap_err()
1827 .kind,
1828 RevsetParseErrorKind::InAliasExpansion("F(x)".to_owned())
1829 );
1830 assert_eq!(
1831 *with_aliases([("F(x)", "F(x,b)"), ("F(x,y)", "F(x|y)")])
1832 .parse("F(a)")
1833 .unwrap_err()
1834 .kind,
1835 RevsetParseErrorKind::InAliasExpansion("F(x)".to_owned())
1836 );
1837 }
1838}