Skip to content

Commit 0e7bfb3

Browse files
committed
yeast: Test query choice parsing
Adds a few tests for various aspects of choice parsing.
1 parent 18c08e5 commit 0e7bfb3

1 file changed

Lines changed: 98 additions & 0 deletions

File tree

‎shared/yeast-macros/src/rule_parse.rs‎

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,60 @@ mod tests {
640640
assert!(matches!(rule.replacement, Replacement::Templates(_)));
641641
}
642642

643+
#[test]
644+
fn parses_quantified_query_choice_alternatives() {
645+
let pattern = parse_pattern(quote! {
646+
[
647+
(identifier)+ @items
648+
(integer)?
649+
","*
650+
]
651+
})
652+
.unwrap();
653+
654+
let Pattern::Choice { alternatives } = pattern else {
655+
panic!("expected query choice");
656+
};
657+
assert!(matches!(
658+
&alternatives[0],
659+
Pattern::Capture {
660+
cardinality: Cardinality::ONE_OR_MORE,
661+
..
662+
}
663+
));
664+
assert!(matches!(
665+
&alternatives[1],
666+
Pattern::Repeated {
667+
cardinality: Cardinality::OPTIONAL,
668+
..
669+
}
670+
));
671+
assert!(matches!(
672+
&alternatives[2],
673+
Pattern::Repeated {
674+
cardinality: Cardinality::ZERO_OR_MORE,
675+
..
676+
}
677+
));
678+
}
679+
680+
#[test]
681+
fn rejects_mixed_capture_modes_in_query_choice() {
682+
for pattern in [
683+
quote!([(identifier) @value (integer) @@value]),
684+
quote!([(identifier) @@value (integer) @value]),
685+
] {
686+
let result = parse_pattern(pattern);
687+
let Err(error) = result else {
688+
panic!("expected mixed capture modes to be rejected");
689+
};
690+
assert_eq!(
691+
error.to_string(),
692+
"capture `value` must consistently use `@` or `@@` across query choice alternatives"
693+
);
694+
}
695+
}
696+
643697
#[test]
644698
fn rejects_eager_capture_of_rule_root() {
645699
let result = parse_rule(quote! {
@@ -656,6 +710,25 @@ mod tests {
656710
);
657711
}
658712

713+
#[test]
714+
fn rejects_eager_capture_in_rule_root_choice() {
715+
let result = parse_rule(quote! {
716+
[
717+
(identifier) @name
718+
(integer)
719+
]
720+
=>
721+
(identifier "replacement")
722+
});
723+
let Err(error) = result else {
724+
panic!("expected eager capture in rule-root choice to be rejected");
725+
};
726+
assert_eq!(
727+
error.to_string(),
728+
"a capture of the rule root must use `@@`; the matched root cannot be eagerly translated"
729+
);
730+
}
731+
659732
#[test]
660733
fn repeated_capture_owns_its_cardinality() {
661734
let pattern = parse_pattern(quote!((array (identifier)* @items))).unwrap();
@@ -798,6 +871,31 @@ mod tests {
798871
));
799872
}
800873

874+
#[test]
875+
fn parses_choice_led_repeated_sequence() {
876+
let pattern = parse_pattern(quote!((root ([(identifier) (integer)] ",")*))).unwrap();
877+
let Pattern::Node { fields, .. } = pattern else {
878+
panic!("expected root node");
879+
};
880+
let Pattern::Sequence(children) = &fields[0].1 else {
881+
panic!("expected child sequence");
882+
};
883+
let Pattern::Repeated {
884+
pattern: repeated, ..
885+
} = &children[0]
886+
else {
887+
panic!("expected repetition");
888+
};
889+
assert!(matches!(
890+
repeated.as_ref(),
891+
Pattern::Sequence(patterns)
892+
if matches!(
893+
patterns.as_slice(),
894+
[Pattern::Choice { .. }, Pattern::Unnamed(comma)] if comma == ","
895+
)
896+
));
897+
}
898+
801899
#[test]
802900
fn rejects_unconsumed_node_pattern_tokens() {
803901
for query in [quote!((root (foo . (bar) @x))), quote!((root(bar @ x)))] {

0 commit comments

Comments
 (0)