use crate::parser::tests::cst::{ExpectedNode, assert_equivalent};
use crate::{SyntaxKind, parse};
#[test]
fn inner_expr_bare_variable() {
assert_equivalent(
parse("Hello {x}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
TEXT
INLINE_LOGIC {
INNER_EXPRESSION {
PATH
}
}
}
}
}),
);
}
#[test]
fn inner_expr_dotted_path() {
assert_equivalent(
parse("{knot.stitch}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
INNER_EXPRESSION {
PATH
}
}
}
}
}),
);
}
#[test]
fn inner_expr_integer() {
assert_equivalent(
parse("{42}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
INNER_EXPRESSION {
INTEGER_LIT
}
}
}
}
}),
);
}
#[test]
fn inner_expr_string() {
assert_equivalent(
parse("{\"hello\"}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
INNER_EXPRESSION {
STRING_LIT
}
}
}
}
}),
);
}
#[test]
fn inner_expr_boolean() {
assert_equivalent(
parse("{true}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
INNER_EXPRESSION {
BOOLEAN_LIT
}
}
}
}
}),
);
}
#[test]
fn inner_expr_infix() {
assert_equivalent(
parse("{x + 1}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
INNER_EXPRESSION {
INFIX_EXPR {
PATH
INTEGER_LIT
}
}
}
}
}
}),
);
}
#[test]
fn inner_expr_prefix_not() {
assert_equivalent(
parse("{not visited}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
INNER_EXPRESSION {
PREFIX_EXPR {
PATH
}
}
}
}
}
}),
);
}
#[test]
fn inner_expr_complex_infix() {
assert_equivalent(
parse("{x > 5 and y < 10}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
INNER_EXPRESSION {
INFIX_EXPR {
INFIX_EXPR {
PATH
INTEGER_LIT
}
INFIX_EXPR {
PATH
INTEGER_LIT
}
}
}
}
}
}
}),
);
}
#[test]
fn inner_expr_function_call() {
assert_equivalent(
parse("{greet(name)}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
INNER_EXPRESSION {
FUNCTION_CALL {
IDENTIFIER
ARG_LIST {
PATH
}
}
}
}
}
}
}),
);
}
#[test]
fn inner_expr_postfix() {
assert_equivalent(
parse("{count++}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
INNER_EXPRESSION {
POSTFIX_EXPR {
PATH
}
}
}
}
}
}),
);
}
#[test]
fn cond_true_only() {
assert_equivalent(
parse("{x: yes}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
PATH
INLINE_BRANCHES_COND {
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn cond_true_and_false() {
assert_equivalent(
parse("{x: yes|no}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
PATH
INLINE_BRANCHES_COND {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn cond_infix_expr() {
assert_equivalent(
parse("{x > 5: big|small}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
INFIX_EXPR {
PATH
INTEGER_LIT
}
INLINE_BRANCHES_COND {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn cond_empty_true_branch() {
assert_equivalent(
parse("{x: |no}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
PATH
INLINE_BRANCHES_COND {
BRANCH_CONTENT
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn cond_empty_false_branch() {
assert_equivalent(
parse("{x: yes|}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
PATH
INLINE_BRANCHES_COND {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT
}
}
}
}
}
}),
);
}
#[test]
fn cond_empty_both() {
assert_equivalent(
parse("{x: |}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
PATH
INLINE_BRANCHES_COND {
BRANCH_CONTENT
BRANCH_CONTENT
}
}
}
}
}
}),
);
}
#[test]
fn cond_empty_body() {
assert_equivalent(
parse("{x:}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
PATH
INLINE_BRANCHES_COND {
BRANCH_CONTENT
}
}
}
}
}
}),
);
}
#[test]
fn cond_function_call_expr() {
assert_equivalent(
parse("{check(x): passed}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
FUNCTION_CALL {
IDENTIFIER
ARG_LIST {
PATH
}
}
INLINE_BRANCHES_COND {
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn cond_prefix_not_expr() {
assert_equivalent(
parse("{not done: continue}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
PREFIX_EXPR {
PATH
}
INLINE_BRANCHES_COND {
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn cond_with_text_around() {
assert_equivalent(
parse("Hello {x: world} goodbye\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
TEXT
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
PATH
INLINE_BRANCHES_COND {
BRANCH_CONTENT {
TEXT
}
}
}
}
TEXT
}
}
}),
);
}
#[test]
fn implicit_seq_two() {
assert_equivalent(
parse("{a|b}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
IMPLICIT_SEQUENCE {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}),
);
}
#[test]
fn implicit_seq_three() {
assert_equivalent(
parse("{a|b|c}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
IMPLICIT_SEQUENCE {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}),
);
}
#[test]
fn implicit_seq_four_sentences() {
assert_equivalent(
parse("{First.|Second.|Third.|Fourth.}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
IMPLICIT_SEQUENCE {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}),
);
}
#[test]
fn implicit_seq_empty_first() {
assert_equivalent(
parse("{|b|c}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
IMPLICIT_SEQUENCE {
BRANCH_CONTENT
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}),
);
}
#[test]
fn implicit_seq_empty_middle() {
assert_equivalent(
parse("{a||c}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
IMPLICIT_SEQUENCE {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}),
);
}
#[test]
fn implicit_seq_empty_last() {
assert_equivalent(
parse("{a|b|}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
IMPLICIT_SEQUENCE {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT
}
}
}
}
}),
);
}
#[test]
fn implicit_seq_with_nested() {
assert_equivalent(
parse("{The {&big|small} dog.|The cat.}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
IMPLICIT_SEQUENCE {
BRANCH_CONTENT {
TEXT
INLINE_LOGIC {
SEQUENCE_WITH_ANNOTATION {
SEQUENCE_SYMBOL_ANNOTATION
INLINE_BRANCHES_SEQ {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
}
}
}
TEXT
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}),
);
}
#[test]
fn implicit_seq_with_diverts() {
assert_equivalent(
parse("{->Fish1->|->Fish2->|nothing.}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
IMPLICIT_SEQUENCE {
BRANCH_CONTENT {
DIVERT_NODE {
TUNNEL_CALL_NODE {
DIVERT_TARGET_WITH_ARGS {
PATH
}
}
}
}
BRANCH_CONTENT {
DIVERT_NODE {
TUNNEL_CALL_NODE {
DIVERT_TARGET_WITH_ARGS {
PATH
}
}
}
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}),
);
}
#[test]
fn sym_seq_cycle() {
assert_equivalent(
parse("{&first|second|third}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
SEQUENCE_WITH_ANNOTATION {
SEQUENCE_SYMBOL_ANNOTATION
INLINE_BRANCHES_SEQ {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn sym_seq_once() {
assert_equivalent(
parse("{!first|second}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
SEQUENCE_WITH_ANNOTATION {
SEQUENCE_SYMBOL_ANNOTATION
INLINE_BRANCHES_SEQ {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn sym_seq_shuffle() {
assert_equivalent(
parse("{~first|second|third}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
SEQUENCE_WITH_ANNOTATION {
SEQUENCE_SYMBOL_ANNOTATION
INLINE_BRANCHES_SEQ {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn sym_seq_stopping() {
assert_equivalent(
parse("{$first|second}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
SEQUENCE_WITH_ANNOTATION {
SEQUENCE_SYMBOL_ANNOTATION
INLINE_BRANCHES_SEQ {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn sym_seq_combined() {
assert_equivalent(
parse("{&!first|second}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
SEQUENCE_WITH_ANNOTATION {
SEQUENCE_SYMBOL_ANNOTATION
INLINE_BRANCHES_SEQ {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn sym_seq_two_branches() {
assert_equivalent(
parse("{&a|b}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
SEQUENCE_WITH_ANNOTATION {
SEQUENCE_SYMBOL_ANNOTATION
INLINE_BRANCHES_SEQ {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn word_seq_stopping() {
assert_equivalent(
parse("{stopping: first|second|third}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
SEQUENCE_WITH_ANNOTATION {
SEQUENCE_WORD_ANNOTATION
INLINE_BRANCHES_SEQ {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn word_seq_cycle() {
assert_equivalent(
parse("{cycle: a|b|c}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
SEQUENCE_WITH_ANNOTATION {
SEQUENCE_WORD_ANNOTATION
INLINE_BRANCHES_SEQ {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn word_seq_shuffle() {
assert_equivalent(
parse("{shuffle: a|b|c}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
SEQUENCE_WITH_ANNOTATION {
SEQUENCE_WORD_ANNOTATION
INLINE_BRANCHES_SEQ {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn word_seq_once() {
assert_equivalent(
parse("{once: a|b}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
SEQUENCE_WITH_ANNOTATION {
SEQUENCE_WORD_ANNOTATION
INLINE_BRANCHES_SEQ {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn word_seq_two_branches() {
assert_equivalent(
parse("{stopping: a|b}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
SEQUENCE_WITH_ANNOTATION {
SEQUENCE_WORD_ANNOTATION
INLINE_BRANCHES_SEQ {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn multiline_two_cond_branches() {
assert_equivalent(
parse("{\n- x > 5:\n Big.\n- else:\n Small.\n}\n"),
cst!(SOURCE_FILE {
MULTILINE_BLOCK {
MULTILINE_BRANCHES_COND {
MULTILINE_BRANCH_COND {
INFIX_EXPR {
PATH
INTEGER_LIT
}
MULTILINE_BRANCH_BODY {
TEXT
}
}
MULTILINE_BRANCH_COND {
MULTILINE_BRANCH_BODY {
TEXT
}
}
}
}
}),
);
}
#[test]
fn multiline_three_cond_branches() {
assert_equivalent(
parse("{\n- x > 10:\n Very big.\n- x > 5:\n Big.\n- else:\n Small.\n}\n"),
cst!(SOURCE_FILE {
MULTILINE_BLOCK {
MULTILINE_BRANCHES_COND {
MULTILINE_BRANCH_COND {
INFIX_EXPR {
PATH
INTEGER_LIT
}
MULTILINE_BRANCH_BODY {
TEXT
}
}
MULTILINE_BRANCH_COND {
INFIX_EXPR {
PATH
INTEGER_LIT
}
MULTILINE_BRANCH_BODY {
TEXT
}
}
MULTILINE_BRANCH_COND {
MULTILINE_BRANCH_BODY {
TEXT
}
}
}
}
}),
);
}
#[test]
fn multiline_cond_no_else() {
assert_equivalent(
parse("{\n- x:\n Yes.\n}\n"),
cst!(SOURCE_FILE {
MULTILINE_BLOCK {
MULTILINE_BRANCHES_COND {
MULTILINE_BRANCH_COND {
PATH
MULTILINE_BRANCH_BODY {
TEXT
}
}
}
}
}),
);
}
#[test]
fn multiline_bare_branches() {
assert_equivalent(
parse("{\n- Branch one.\n- Branch two.\n}\n"),
cst!(SOURCE_FILE {
MULTILINE_BLOCK {
MULTILINE_BRANCHES_COND {
MULTILINE_BRANCH_COND {
MULTILINE_BRANCH_BODY {
TEXT
}
}
MULTILINE_BRANCH_COND {
MULTILINE_BRANCH_BODY {
TEXT
}
}
}
}
}),
);
}
#[test]
fn multiline_cond_with_expr() {
assert_equivalent(
parse("{\n- x > 5:\n Big.\n}\n"),
cst!(SOURCE_FILE {
MULTILINE_BLOCK {
MULTILINE_BRANCHES_COND {
MULTILINE_BRANCH_COND {
INFIX_EXPR {
PATH
INTEGER_LIT
}
MULTILINE_BRANCH_BODY {
TEXT
}
}
}
}
}),
);
}
#[test]
fn multiline_else_only() {
assert_equivalent(
parse("{\n- else:\n Fallback.\n}\n"),
cst!(SOURCE_FILE {
MULTILINE_BLOCK {
MULTILINE_BRANCHES_COND {
MULTILINE_BRANCH_COND {
MULTILINE_BRANCH_BODY {
TEXT
}
}
}
}
}),
);
}
#[test]
fn multiline_seq_stopping() {
assert_equivalent(
parse("{\nstopping:\n- first\n- second\n}\n"),
cst!(SOURCE_FILE {
MULTILINE_BLOCK {
SEQUENCE_WITH_ANNOTATION {
SEQUENCE_WORD_ANNOTATION
MULTILINE_BRANCHES_SEQ {
MULTILINE_BRANCH_SEQ {
MULTILINE_BRANCH_BODY {
TEXT
}
}
MULTILINE_BRANCH_SEQ {
MULTILINE_BRANCH_BODY {
TEXT
}
}
}
}
}
}),
);
}
#[test]
fn multiline_seq_cycle() {
assert_equivalent(
parse("{\ncycle:\n- a\n- b\n- c\n}\n"),
cst!(SOURCE_FILE {
MULTILINE_BLOCK {
SEQUENCE_WITH_ANNOTATION {
SEQUENCE_WORD_ANNOTATION
MULTILINE_BRANCHES_SEQ {
MULTILINE_BRANCH_SEQ {
MULTILINE_BRANCH_BODY {
TEXT
}
}
MULTILINE_BRANCH_SEQ {
MULTILINE_BRANCH_BODY {
TEXT
}
}
MULTILINE_BRANCH_SEQ {
MULTILINE_BRANCH_BODY {
TEXT
}
}
}
}
}
}),
);
}
#[test]
fn multiline_seq_symbol() {
assert_equivalent(
parse("{\n&\n- first\n- second\n}\n"),
cst!(SOURCE_FILE {
MULTILINE_BLOCK {
SEQUENCE_WITH_ANNOTATION {
SEQUENCE_SYMBOL_ANNOTATION
MULTILINE_BRANCHES_SEQ {
MULTILINE_BRANCH_SEQ {
MULTILINE_BRANCH_BODY {
TEXT
}
}
MULTILINE_BRANCH_SEQ {
MULTILINE_BRANCH_BODY {
TEXT
}
}
}
}
}
}),
);
}
#[test]
fn multiline_seq_three_branches() {
assert_equivalent(
parse("{\nstopping:\n- one\n- two\n- three\n}\n"),
cst!(SOURCE_FILE {
MULTILINE_BLOCK {
SEQUENCE_WITH_ANNOTATION {
SEQUENCE_WORD_ANNOTATION
MULTILINE_BRANCHES_SEQ {
MULTILINE_BRANCH_SEQ {
MULTILINE_BRANCH_BODY {
TEXT
}
}
MULTILINE_BRANCH_SEQ {
MULTILINE_BRANCH_BODY {
TEXT
}
}
MULTILINE_BRANCH_SEQ {
MULTILINE_BRANCH_BODY {
TEXT
}
}
}
}
}
}),
);
}
#[test]
fn inline_multiline_conditional() {
assert_equivalent(
parse("Hello {\n- x:\n Yes.\n- else:\n No.\n}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
TEXT
INLINE_LOGIC {
MULTILINE_CONDITIONAL {
MULTILINE_BRANCH_COND {
PATH
MULTILINE_BRANCH_BODY {
TEXT
}
}
MULTILINE_BRANCH_COND {
MULTILINE_BRANCH_BODY {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn inline_multiline_bare_branches() {
assert_equivalent(
parse("Hello {\n- One.\n- Two.\n}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
TEXT
INLINE_LOGIC {
MULTILINE_CONDITIONAL {
MULTILINE_BRANCH_COND {
MULTILINE_BRANCH_BODY {
TEXT
}
}
MULTILINE_BRANCH_COND {
MULTILINE_BRANCH_BODY {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn branchless_body_simple() {
assert_equivalent(
parse("{\n x:\n Content here.\n}\n"),
cst!(SOURCE_FILE {
MULTILINE_BLOCK {
CONDITIONAL_WITH_EXPR {
PATH
BRANCHLESS_COND_BODY {
TEXT
}
}
}
}),
);
}
#[test]
fn branchless_body_with_else() {
assert_equivalent(
parse("{\n x:\n Content.\n- else:\n Other.\n}\n"),
cst!(SOURCE_FILE {
MULTILINE_BLOCK {
CONDITIONAL_WITH_EXPR {
PATH
BRANCHLESS_COND_BODY {
TEXT
ELSE_BRANCH {
MULTILINE_BRANCH_COND {
MULTILINE_BRANCH_BODY {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn branchless_body_with_choice_then_else() {
assert_equivalent(
parse("{\n x:\n * Choice A\n- else:\n * Choice B\n}\n"),
cst!(SOURCE_FILE {
MULTILINE_BLOCK {
CONDITIONAL_WITH_EXPR {
PATH
BRANCHLESS_COND_BODY {
CHOICE {
CHOICE_BULLETS
CHOICE_START_CONTENT {
TEXT
}
}
ELSE_BRANCH {
MULTILINE_BRANCH_COND {
MULTILINE_BRANCH_BODY {
CHOICE {
CHOICE_BULLETS
CHOICE_START_CONTENT {
TEXT
}
}
}
}
}
}
}
}
}),
);
}
#[test]
fn nested_cond_in_cond_true() {
assert_equivalent(
parse("{x: {y: inner}|no}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
PATH
INLINE_BRANCHES_COND {
BRANCH_CONTENT {
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
PATH
INLINE_BRANCHES_COND {
BRANCH_CONTENT {
TEXT
}
}
}
}
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn nested_expr_in_branch() {
assert_equivalent(
parse("{a|{x}|c}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
IMPLICIT_SEQUENCE {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
INLINE_LOGIC {
INNER_EXPRESSION {
PATH
}
}
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}),
);
}
#[test]
fn nested_seq_in_cond() {
assert_equivalent(
parse("{x: {&a|b}|no}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
PATH
INLINE_BRANCHES_COND {
BRANCH_CONTENT {
INLINE_LOGIC {
SEQUENCE_WITH_ANNOTATION {
SEQUENCE_SYMBOL_ANNOTATION
INLINE_BRANCHES_SEQ {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn deeply_nested() {
assert_equivalent(
parse("{x: {y: {z: deep}}}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
PATH
INLINE_BRANCHES_COND {
BRANCH_CONTENT {
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
PATH
INLINE_BRANCHES_COND {
BRANCH_CONTENT {
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
PATH
INLINE_BRANCHES_COND {
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}),
);
}
#[test]
fn branch_with_divert() {
assert_equivalent(
parse("{x: -> target|no}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
PATH
INLINE_BRANCHES_COND {
BRANCH_CONTENT {
DIVERT_NODE {
SIMPLE_DIVERT {
DIVERT_TARGET_WITH_ARGS {
PATH
}
}
}
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn branch_with_glue() {
assert_equivalent(
parse("{x: <>glued|no}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
PATH
INLINE_BRANCHES_COND {
BRANCH_CONTENT {
GLUE_NODE
TEXT
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn branch_with_escape() {
assert_equivalent(
parse("{x: hello\\|world|no}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
PATH
INLINE_BRANCHES_COND {
BRANCH_CONTENT {
TEXT
ESCAPE
TEXT
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn branch_with_thread() {
assert_equivalent(
parse("{x: <- thread|no}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
PATH
INLINE_BRANCHES_COND {
BRANCH_CONTENT {
DIVERT_NODE {
THREAD_START {
PATH
}
}
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn branch_divert_in_seq() {
assert_equivalent(
parse("{&-> a|-> b}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
SEQUENCE_WITH_ANNOTATION {
SEQUENCE_SYMBOL_ANNOTATION
INLINE_BRANCHES_SEQ {
BRANCH_CONTENT {
DIVERT_NODE {
SIMPLE_DIVERT {
DIVERT_TARGET_WITH_ARGS {
PATH
}
}
}
}
BRANCH_CONTENT {
DIVERT_NODE {
SIMPLE_DIVERT {
DIVERT_TARGET_WITH_ARGS {
PATH
}
}
}
}
}
}
}
}
}
}),
);
}
#[test]
fn inline_in_content_line() {
assert_equivalent(
parse("Hello {x} world\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
TEXT
INLINE_LOGIC {
INNER_EXPRESSION {
PATH
}
}
TEXT
}
}
}),
);
}
#[test]
fn inline_in_choice() {
assert_equivalent(
parse("* Choice {x: yes|no}\n"),
cst!(SOURCE_FILE {
CHOICE {
CHOICE_BULLETS
CHOICE_START_CONTENT {
TEXT
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
PATH
INLINE_BRANCHES_COND {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn inline_in_gather() {
assert_equivalent(
parse("- Gathered {x}\n"),
cst!(SOURCE_FILE {
GATHER {
GATHER_DASHES
MIXED_CONTENT {
TEXT
INLINE_LOGIC {
INNER_EXPRESSION {
PATH
}
}
}
}
}),
);
}
#[test]
fn multiple_inline_in_line() {
assert_equivalent(
parse("{x} and {y}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
INNER_EXPRESSION {
PATH
}
}
TEXT
INLINE_LOGIC {
INNER_EXPRESSION {
PATH
}
}
}
}
}),
);
}
#[test]
fn inline_before_divert() {
assert_equivalent(
parse("{x} -> target\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
INNER_EXPRESSION {
PATH
}
}
}
DIVERT_NODE {
SIMPLE_DIVERT {
DIVERT_TARGET_WITH_ARGS {
PATH
}
}
}
}
}),
);
}
const INLINE_VARIANTS: [SyntaxKind; 5] = [
SyntaxKind::SEQUENCE_WITH_ANNOTATION,
SyntaxKind::MULTILINE_CONDITIONAL,
SyntaxKind::IMPLICIT_SEQUENCE,
SyntaxKind::CONDITIONAL_WITH_EXPR,
SyntaxKind::INNER_EXPRESSION,
];
fn assert_inline_uniformity(src: &str) {
let p = parse(src);
assert!(p.errors().is_empty(), "unexpected errors: {:?}", p.errors());
for node in p.syntax().descendants() {
if node.kind() == SyntaxKind::INLINE_LOGIC {
let variant_children: Vec<_> = node
.children()
.filter(|c| INLINE_VARIANTS.contains(&c.kind()))
.collect();
assert_eq!(
variant_children.len(),
1,
"INLINE_LOGIC should have exactly one variant child, found {} in `{src}`:\n {:?}",
variant_children.len(),
variant_children
.iter()
.map(crate::SyntaxNode::kind)
.collect::<Vec<_>>(),
);
}
}
}
#[test]
fn uniformity_inner_expr() {
assert_inline_uniformity("{x}\n");
}
#[test]
fn uniformity_conditional() {
assert_inline_uniformity("{x: yes|no}\n");
}
#[test]
fn uniformity_implicit_seq() {
assert_inline_uniformity("{a|b|c}\n");
}
#[test]
fn uniformity_sym_annotation() {
assert_inline_uniformity("{&a|b}\n");
}
#[test]
fn uniformity_word_annotation() {
assert_inline_uniformity("{stopping: a|b}\n");
}
#[test]
fn uniformity_nested() {
assert_inline_uniformity("{x: {y}|no}\n");
}
#[test]
fn uniformity_content_line() {
assert_inline_uniformity("Hello {x} world\n");
}
const MULTILINE_VARIANTS: [SyntaxKind; 3] = [
SyntaxKind::SEQUENCE_WITH_ANNOTATION,
SyntaxKind::MULTILINE_BRANCHES_COND,
SyntaxKind::CONDITIONAL_WITH_EXPR,
];
fn assert_multiline_uniformity(src: &str) {
let p = parse(src);
assert!(p.errors().is_empty(), "unexpected errors: {:?}", p.errors());
for node in p.syntax().descendants() {
if node.kind() == SyntaxKind::MULTILINE_BLOCK {
let variant_children: Vec<_> = node
.children()
.filter(|c| MULTILINE_VARIANTS.contains(&c.kind()))
.collect();
assert_eq!(
variant_children.len(),
1,
"MULTILINE_BLOCK should have exactly one variant child, found {} in `{src}`:\n {:?}",
variant_children.len(),
variant_children
.iter()
.map(crate::SyntaxNode::kind)
.collect::<Vec<_>>(),
);
}
}
}
#[test]
fn uniformity_multiline_cond() {
assert_multiline_uniformity("{\n- x:\n Yes.\n}\n");
}
#[test]
fn uniformity_multiline_seq() {
assert_multiline_uniformity("{\nstopping:\n- a\n- b\n}\n");
}
#[test]
fn uniformity_multiline_bare() {
assert_multiline_uniformity("{\n- One.\n- Two.\n}\n");
}
#[test]
fn has_inner_expr_not_conditional() {
let p = parse("{x}\n");
let root = p.syntax();
let has = root
.descendants()
.any(|n| n.kind() == SyntaxKind::INNER_EXPRESSION);
let has_cond = root
.descendants()
.any(|n| n.kind() == SyntaxKind::CONDITIONAL_WITH_EXPR);
let has_seq = root
.descendants()
.any(|n| n.kind() == SyntaxKind::IMPLICIT_SEQUENCE);
assert!(has, "expected INNER_EXPRESSION");
assert!(!has_cond, "must not have CONDITIONAL_WITH_EXPR");
assert!(!has_seq, "must not have IMPLICIT_SEQUENCE");
}
#[test]
fn has_conditional_not_sequence() {
let p = parse("{x: yes|no}\n");
let root = p.syntax();
let has = root
.descendants()
.any(|n| n.kind() == SyntaxKind::CONDITIONAL_WITH_EXPR);
let has_seq = root
.descendants()
.any(|n| n.kind() == SyntaxKind::IMPLICIT_SEQUENCE);
let has_inner = root
.descendants()
.any(|n| n.kind() == SyntaxKind::INNER_EXPRESSION);
assert!(has, "expected CONDITIONAL_WITH_EXPR");
assert!(!has_seq, "must not have IMPLICIT_SEQUENCE");
assert!(!has_inner, "must not have INNER_EXPRESSION");
}
#[test]
fn has_implicit_seq_not_conditional() {
let p = parse("{a|b|c}\n");
let root = p.syntax();
let has = root
.descendants()
.any(|n| n.kind() == SyntaxKind::IMPLICIT_SEQUENCE);
let has_cond = root
.descendants()
.any(|n| n.kind() == SyntaxKind::CONDITIONAL_WITH_EXPR);
let has_inner = root
.descendants()
.any(|n| n.kind() == SyntaxKind::INNER_EXPRESSION);
assert!(has, "expected IMPLICIT_SEQUENCE");
assert!(!has_cond, "must not have CONDITIONAL_WITH_EXPR");
assert!(!has_inner, "must not have INNER_EXPRESSION");
}
#[test]
fn has_sym_annotation_not_word() {
let p = parse("{&a|b}\n");
let root = p.syntax();
let has_sym = root
.descendants()
.any(|n| n.kind() == SyntaxKind::SEQUENCE_SYMBOL_ANNOTATION);
let has_word = root
.descendants()
.any(|n| n.kind() == SyntaxKind::SEQUENCE_WORD_ANNOTATION);
assert!(has_sym, "expected SEQUENCE_SYMBOL_ANNOTATION");
assert!(!has_word, "must not have SEQUENCE_WORD_ANNOTATION");
}
#[test]
fn has_word_annotation_not_sym() {
let p = parse("{stopping: a|b}\n");
let root = p.syntax();
let has_word = root
.descendants()
.any(|n| n.kind() == SyntaxKind::SEQUENCE_WORD_ANNOTATION);
let has_sym = root
.descendants()
.any(|n| n.kind() == SyntaxKind::SEQUENCE_SYMBOL_ANNOTATION);
assert!(has_word, "expected SEQUENCE_WORD_ANNOTATION");
assert!(!has_sym, "must not have SEQUENCE_SYMBOL_ANNOTATION");
}
#[test]
fn has_inline_logic_not_multiline() {
let p = parse("{x: yes|no}\n");
let root = p.syntax();
let has_inline = root
.descendants()
.any(|n| n.kind() == SyntaxKind::INLINE_LOGIC);
let has_multiline = root
.descendants()
.any(|n| n.kind() == SyntaxKind::MULTILINE_BLOCK);
assert!(has_inline, "expected INLINE_LOGIC");
assert!(!has_multiline, "must not have MULTILINE_BLOCK");
}
#[test]
fn has_multiline_not_inline() {
let p = parse("{\n- x:\n Yes.\n}\n");
let root = p.syntax();
let has_multiline = root
.descendants()
.any(|n| n.kind() == SyntaxKind::MULTILINE_BLOCK);
let has_inline = root
.descendants()
.any(|n| n.kind() == SyntaxKind::INLINE_LOGIC);
assert!(has_multiline, "expected MULTILINE_BLOCK");
assert!(!has_inline, "must not have INLINE_LOGIC");
}
#[test]
fn conditional_has_inline_not_multiline_branches() {
let p = parse("{x: yes|no}\n");
let root = p.syntax();
let has_inline = root
.descendants()
.any(|n| n.kind() == SyntaxKind::INLINE_BRANCHES_COND);
let has_multiline = root
.descendants()
.any(|n| n.kind() == SyntaxKind::MULTILINE_BRANCHES_COND);
assert!(has_inline, "expected INLINE_BRANCHES_COND");
assert!(!has_multiline, "must not have MULTILINE_BRANCHES_COND");
}
#[test]
fn error_unclosed_brace() {
let src = "{x\n";
let p = parse(src);
assert_eq!(src, p.syntax().text().to_string(), "lossless round-trip");
assert!(
!p.errors().is_empty(),
"expected parse error for unclosed brace"
);
}
#[test]
fn error_missing_colon_in_cond() {
let src = "{x yes|no}\n";
let p = parse(src);
assert_eq!(src, p.syntax().text().to_string(), "lossless round-trip");
}
#[test]
fn error_unclosed_nested() {
let src = "{x: {y}\n";
let p = parse(src);
assert_eq!(src, p.syntax().text().to_string(), "lossless round-trip");
assert!(
!p.errors().is_empty(),
"expected parse error for unclosed outer brace"
);
}
#[test]
fn error_empty_braces() {
let src = "{}\n";
let p = parse(src);
assert_eq!(src, p.syntax().text().to_string(), "lossless round-trip");
}
#[test]
fn pipe_pipe_with_colon_is_conditional() {
assert_equivalent(
parse("{x || y: body}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
INFIX_EXPR [PIPE, PIPE] {
PATH
PATH
}
INLINE_BRANCHES_COND {
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn pipe_pipe_no_colon_is_sequence() {
assert_equivalent(
parse("{x || y}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
IMPLICIT_SEQUENCE {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}),
);
}
#[test]
fn single_pipe_before_colon_is_sequence() {
assert_equivalent(
parse("{a|b:c}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
IMPLICIT_SEQUENCE {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}),
);
}
#[test]
fn compound_logical_or_conditional() {
assert_equivalent(
parse("{x < 10 || x > 20: body}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
INFIX_EXPR {
INFIX_EXPR {
PATH
INTEGER_LIT
}
INFIX_EXPR {
PATH
INTEGER_LIT
}
}
INLINE_BRANCHES_COND {
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn pipe_pipe_colon_is_conditional_not_sequence() {
assert_equivalent(
parse("{a||b:c}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
INFIX_EXPR [PIPE, PIPE] {
PATH
PATH
}
INLINE_BRANCHES_COND {
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn mixed_pipe_and_pipe_pipe_no_colon_is_sequence() {
assert_equivalent(
parse("{a|b||c}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
IMPLICIT_SEQUENCE {
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT {
TEXT
}
BRANCH_CONTENT
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}),
);
}
#[test]
fn chained_logical_or_conditional() {
assert_equivalent(
parse("{x || y || z: w}\n"),
cst!(SOURCE_FILE {
CONTENT_LINE {
MIXED_CONTENT {
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
INFIX_EXPR {
INFIX_EXPR [PIPE, PIPE] {
PATH
PATH
}
PATH
}
INLINE_BRANCHES_COND {
BRANCH_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn else_body_with_logical_or_nested_conditional() {
assert_equivalent(
parse(
"\
{
- x >= 10:
big
- else:
{ x < 5 || x > 20:
out of range
- else:
in range
}
}
",
),
cst!(SOURCE_FILE {
MULTILINE_BLOCK {
MULTILINE_BRANCHES_COND {
MULTILINE_BRANCH_COND {
INFIX_EXPR {
PATH
INTEGER_LIT
}
MULTILINE_BRANCH_BODY {
TEXT
}
}
MULTILINE_BRANCH_COND {
MULTILINE_BRANCH_BODY {
INLINE_LOGIC {
CONDITIONAL_WITH_EXPR {
INFIX_EXPR {
INFIX_EXPR {
PATH
INTEGER_LIT
}
INFIX_EXPR {
PATH
INTEGER_LIT
}
}
BRANCHLESS_COND_BODY {
TEXT
ELSE_BRANCH {
MULTILINE_BRANCH_COND {
MULTILINE_BRANCH_BODY {
TEXT
}
}
}
}
}
}
}
}
}
}
}),
);
}
#[test]
fn multiline_cond_choice_single() {
assert_equivalent(
parse("{\n- x:\n * Go outside\n}\n"),
cst!(SOURCE_FILE {
MULTILINE_BLOCK {
MULTILINE_BRANCHES_COND {
MULTILINE_BRANCH_COND {
PATH
MULTILINE_BRANCH_BODY {
CHOICE {
CHOICE_BULLETS
CHOICE_START_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn multiline_cond_choice_multiple() {
assert_equivalent(
parse("{\n- x:\n * Option A\n * Option B\n}\n"),
cst!(SOURCE_FILE {
MULTILINE_BLOCK {
MULTILINE_BRANCHES_COND {
MULTILINE_BRANCH_COND {
PATH
MULTILINE_BRANCH_BODY {
CHOICE {
CHOICE_BULLETS
CHOICE_START_CONTENT {
TEXT
}
}
CHOICE {
CHOICE_BULLETS
CHOICE_START_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn multiline_cond_choices_both_branches() {
assert_equivalent(
parse(
"{\n- door_open:\n * Go outside\n- else:\n * Ask permission\n * Open the door\n}\n",
),
cst!(SOURCE_FILE {
MULTILINE_BLOCK {
MULTILINE_BRANCHES_COND {
MULTILINE_BRANCH_COND {
PATH
MULTILINE_BRANCH_BODY {
CHOICE {
CHOICE_BULLETS
CHOICE_START_CONTENT {
TEXT
}
}
}
}
MULTILINE_BRANCH_COND {
MULTILINE_BRANCH_BODY {
CHOICE {
CHOICE_BULLETS
CHOICE_START_CONTENT {
TEXT
}
}
CHOICE {
CHOICE_BULLETS
CHOICE_START_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn multiline_cond_choice_with_divert() {
assert_equivalent(
parse("{\n- x:\n * Go outside -> garden\n}\n"),
cst!(SOURCE_FILE {
MULTILINE_BLOCK {
MULTILINE_BRANCHES_COND {
MULTILINE_BRANCH_COND {
PATH
MULTILINE_BRANCH_BODY {
CHOICE {
CHOICE_BULLETS
CHOICE_START_CONTENT {
TEXT
}
DIVERT_NODE {
SIMPLE_DIVERT {
DIVERT_TARGET_WITH_ARGS {
PATH
}
}
}
}
}
}
}
}
}),
);
}
#[test]
fn multiline_cond_choice_with_brackets() {
assert_equivalent(
parse("{\n- x:\n * [hidden]shown\n}\n"),
cst!(SOURCE_FILE {
MULTILINE_BLOCK {
MULTILINE_BRANCHES_COND {
MULTILINE_BRANCH_COND {
PATH
MULTILINE_BRANCH_BODY {
CHOICE {
CHOICE_BULLETS
CHOICE_BRACKET_CONTENT {
TEXT
}
CHOICE_INNER_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn multiline_cond_choice_with_label() {
assert_equivalent(
parse("{\n- x:\n * (my_label) Go outside\n}\n"),
cst!(SOURCE_FILE {
MULTILINE_BLOCK {
MULTILINE_BRANCHES_COND {
MULTILINE_BRANCH_COND {
PATH
MULTILINE_BRANCH_BODY {
CHOICE {
CHOICE_BULLETS
LABEL {
IDENTIFIER
}
CHOICE_START_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn multiline_cond_text_then_choice() {
assert_equivalent(
parse("{\n- x:\n Some text.\n * A choice\n}\n"),
cst!(SOURCE_FILE {
MULTILINE_BLOCK {
MULTILINE_BRANCHES_COND {
MULTILINE_BRANCH_COND {
PATH
MULTILINE_BRANCH_BODY {
TEXT
CHOICE {
CHOICE_BULLETS
CHOICE_START_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn multiline_cond_sticky_choice() {
assert_equivalent(
parse("{\n- x:\n + Sticky option\n}\n"),
cst!(SOURCE_FILE {
MULTILINE_BLOCK {
MULTILINE_BRANCHES_COND {
MULTILINE_BRANCH_COND {
PATH
MULTILINE_BRANCH_BODY {
CHOICE {
CHOICE_BULLETS
CHOICE_START_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn multiline_cond_nested_choice() {
assert_equivalent(
parse("{\n- x:\n * * Nested choice\n}\n"),
cst!(SOURCE_FILE {
MULTILINE_BLOCK {
MULTILINE_BRANCHES_COND {
MULTILINE_BRANCH_COND {
PATH
MULTILINE_BRANCH_BODY {
CHOICE {
CHOICE_BULLETS
CHOICE_START_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}
#[test]
fn multiline_cond_choice_with_condition() {
assert_equivalent(
parse("{\n- x:\n * {flag} Conditional choice\n}\n"),
cst!(SOURCE_FILE {
MULTILINE_BLOCK {
MULTILINE_BRANCHES_COND {
MULTILINE_BRANCH_COND {
PATH
MULTILINE_BRANCH_BODY {
CHOICE {
CHOICE_BULLETS
CHOICE_CONDITION {
PATH
}
CHOICE_START_CONTENT {
TEXT
}
}
}
}
}
}
}),
);
}