diff --git a/crates/plotnik-cli/src/commands/exec.rs b/crates/plotnik-cli/src/commands/exec.rs
index d1c87595..5a2b82b8 100644
--- a/crates/plotnik-cli/src/commands/exec.rs
+++ b/crates/plotnik-cli/src/commands/exec.rs
@@ -41,10 +41,7 @@ pub fn run(args: ExecArgs) {
});
// Analyze query
- let query_analyzed = query_parsed.analyze().unwrap_or_else(|e| {
- eprintln!("error: {}", e);
- std::process::exit(1);
- });
+ let query_analyzed = query_parsed.analyze();
// Link query against language
let linked = query_analyzed.link(&lang);
diff --git a/crates/plotnik-lib/src/parser/ast_tests.rs b/crates/plotnik-lib/src/parser/ast_tests.rs
index 71f2044a..1b76c8ce 100644
--- a/crates/plotnik-lib/src/parser/ast_tests.rs
+++ b/crates/plotnik-lib/src/parser/ast_tests.rs
@@ -3,9 +3,8 @@ use indoc::indoc;
#[test]
fn simple_tree() {
- let query = Query::try_from("Q = (identifier)").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
+ let res = Query::expect_valid_ast("Q = (identifier)");
+ insta::assert_snapshot!(res, @r"
Root
Def Q
NamedNode identifier
@@ -18,9 +17,9 @@ fn nested_tree() {
Q = (function_definition name: (identifier))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
+ let res = Query::expect_valid_ast(input);
+
+ insta::assert_snapshot!(res, @r"
Root
Def Q
NamedNode function_definition
@@ -31,9 +30,8 @@ fn nested_tree() {
#[test]
fn wildcard() {
- let query = Query::try_from("Q = (_)").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
+ let res = Query::expect_valid_ast("Q = (_)");
+ insta::assert_snapshot!(res, @r"
Root
Def Q
NamedNode (any)
@@ -42,9 +40,8 @@ fn wildcard() {
#[test]
fn literal() {
- let query = Query::try_from(r#"Q = "if""#).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r#"
+ let res = Query::expect_valid_ast(r#"Q = "if""#);
+ insta::assert_snapshot!(res, @r#"
Root
Def Q
AnonymousNode "if"
@@ -53,9 +50,8 @@ fn literal() {
#[test]
fn capture() {
- let query = Query::try_from("Q = (identifier) @name").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
+ let res = Query::expect_valid_ast("Q = (identifier) @name");
+ insta::assert_snapshot!(res, @r"
Root
Def Q
CapturedExpr @name
@@ -65,9 +61,8 @@ fn capture() {
#[test]
fn capture_with_type() {
- let query = Query::try_from("Q = (identifier) @name :: string").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
+ let res = Query::expect_valid_ast("Q = (identifier) @name :: string");
+ insta::assert_snapshot!(res, @r"
Root
Def Q
CapturedExpr @name :: string
@@ -77,9 +72,8 @@ fn capture_with_type() {
#[test]
fn named_definition() {
- let query = Query::try_from("Expr = (expression)").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
+ let res = Query::expect_valid_ast("Expr = (expression)");
+ insta::assert_snapshot!(res, @r"
Root
Def Expr
NamedNode expression
@@ -93,9 +87,9 @@ fn reference() {
Q = (call (Expr))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
+ let res = Query::expect_valid_ast(input);
+
+ insta::assert_snapshot!(res, @r"
Root
Def Expr
NamedNode identifier
@@ -107,9 +101,8 @@ fn reference() {
#[test]
fn alternation_unlabeled() {
- let query = Query::try_from("Q = [(identifier) (number)]").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
+ let res = Query::expect_valid_ast("Q = [(identifier) (number)]");
+ insta::assert_snapshot!(res, @r"
Root
Def Q
Alt
@@ -126,9 +119,9 @@ fn alternation_tagged() {
Q = [Ident: (identifier) Num: (number)]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
+ let res = Query::expect_valid_ast(input);
+
+ insta::assert_snapshot!(res, @r"
Root
Def Q
Alt
@@ -141,9 +134,8 @@ fn alternation_tagged() {
#[test]
fn sequence() {
- let query = Query::try_from("Q = {(a) (b) (c)}").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
+ let res = Query::expect_valid_ast("Q = {(a) (b) (c)}");
+ insta::assert_snapshot!(res, @r"
Root
Def Q
Seq
@@ -155,9 +147,8 @@ fn sequence() {
#[test]
fn quantifier_star() {
- let query = Query::try_from("Q = (statement)*").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
+ let res = Query::expect_valid_ast("Q = (statement)*");
+ insta::assert_snapshot!(res, @r"
Root
Def Q
QuantifiedExpr *
@@ -167,9 +158,8 @@ fn quantifier_star() {
#[test]
fn quantifier_plus() {
- let query = Query::try_from("Q = (statement)+").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
+ let res = Query::expect_valid_ast("Q = (statement)+");
+ insta::assert_snapshot!(res, @r"
Root
Def Q
QuantifiedExpr +
@@ -179,9 +169,8 @@ fn quantifier_plus() {
#[test]
fn quantifier_optional() {
- let query = Query::try_from("Q = (statement)?").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
+ let res = Query::expect_valid_ast("Q = (statement)?");
+ insta::assert_snapshot!(res, @r"
Root
Def Q
QuantifiedExpr ?
@@ -191,9 +180,8 @@ fn quantifier_optional() {
#[test]
fn quantifier_non_greedy() {
- let query = Query::try_from("Q = (statement)*?").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
+ let res = Query::expect_valid_ast("Q = (statement)*?");
+ insta::assert_snapshot!(res, @r"
Root
Def Q
QuantifiedExpr *?
@@ -203,9 +191,8 @@ fn quantifier_non_greedy() {
#[test]
fn anchor() {
- let query = Query::try_from("Q = (block . (statement))").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
+ let res = Query::expect_valid_ast("Q = (block . (statement))");
+ insta::assert_snapshot!(res, @r"
Root
Def Q
NamedNode block
@@ -216,9 +203,8 @@ fn anchor() {
#[test]
fn negated_field() {
- let query = Query::try_from("Q = (function !async)").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
+ let res = Query::expect_valid_ast("Q = (function !async)");
+ insta::assert_snapshot!(res, @r"
Root
Def Q
NamedNode function
@@ -237,9 +223,9 @@ fn complex_example() {
]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
+ let res = Query::expect_valid_ast(input);
+
+ insta::assert_snapshot!(res, @r"
Root
Def Expression
Alt
@@ -259,9 +245,8 @@ fn complex_example() {
#[test]
fn ast_with_errors() {
- let query = Query::try_from("Q = (call (Undefined))").unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid("Q = (call (Undefined))");
+ insta::assert_snapshot!(res, @r"
error: `Undefined` is not defined
|
1 | Q = (call (Undefined))
@@ -271,9 +256,8 @@ fn ast_with_errors() {
#[test]
fn supertype() {
- let query = Query::try_from("Q = (expression/binary_expression)").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
+ let res = Query::expect_valid_ast("Q = (expression/binary_expression)");
+ insta::assert_snapshot!(res, @r"
Root
Def Q
NamedNode expression
@@ -289,9 +273,9 @@ fn multiple_fields() {
right: (_) @right) @expr
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
+ let res = Query::expect_valid_ast(input);
+
+ insta::assert_snapshot!(res, @r"
Root
Def Q
CapturedExpr @expr
diff --git a/crates/plotnik-lib/src/parser/tests/grammar/alternations_tests.rs b/crates/plotnik-lib/src/parser/tests/grammar/alternations_tests.rs
index f35f1f6c..1a138a28 100644
--- a/crates/plotnik-lib/src/parser/tests/grammar/alternations_tests.rs
+++ b/crates/plotnik-lib/src/parser/tests/grammar/alternations_tests.rs
@@ -7,9 +7,9 @@ fn alternation() {
Q = [(identifier) (string)]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -36,9 +36,9 @@ fn alternation_with_anonymous() {
Q = ["true" "false"]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -65,9 +65,9 @@ fn alternation_with_capture() {
Q = [(identifier) (string)] @value
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -100,9 +100,9 @@ fn alternation_with_quantifier() {
]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -136,9 +136,9 @@ fn alternation_nested() {
)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -171,9 +171,9 @@ fn alternation_in_field() {
)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -207,9 +207,9 @@ fn unlabeled_alternation_three_items() {
Q = [(identifier) (number) (string)]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -244,9 +244,9 @@ fn tagged_alternation_simple() {
]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -277,9 +277,9 @@ fn tagged_alternation_single_line() {
Q = [A: (a) B: (b) C: (c)]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -320,9 +320,9 @@ fn tagged_alternation_with_captures() {
] @stmt
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -379,9 +379,9 @@ fn tagged_alternation_with_type_annotation() {
] @chain :: MemberChain
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -435,9 +435,9 @@ fn tagged_alternation_nested() {
])
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -476,9 +476,9 @@ fn tagged_alternation_in_named_def() {
]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Statement"
@@ -519,9 +519,9 @@ fn tagged_alternation_with_quantifier() {
]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -557,9 +557,9 @@ fn tagged_alternation_with_sequence() {
]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -600,9 +600,9 @@ fn tagged_alternation_with_nested_alternation() {
]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -649,9 +649,9 @@ fn tagged_alternation_full_example() {
]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Expression"
diff --git a/crates/plotnik-lib/src/parser/tests/grammar/anchors_tests.rs b/crates/plotnik-lib/src/parser/tests/grammar/anchors_tests.rs
index 0be13661..cddcc1cc 100644
--- a/crates/plotnik-lib/src/parser/tests/grammar/anchors_tests.rs
+++ b/crates/plotnik-lib/src/parser/tests/grammar/anchors_tests.rs
@@ -7,9 +7,9 @@ fn anchor_first_child() {
Q = (block . (first_statement))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -33,9 +33,9 @@ fn anchor_last_child() {
Q = (block (last_statement) .)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -59,9 +59,9 @@ fn anchor_adjacency() {
Q = (dotted_name (identifier) @a . (identifier) @b)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -95,9 +95,9 @@ fn anchor_both_ends() {
Q = (array . (element) .)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -123,9 +123,9 @@ fn anchor_multiple_adjacent() {
Q = (tuple . (a) . (b) . (c) .)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -163,9 +163,9 @@ fn anchor_in_sequence() {
Q = {. (first) (second) .}
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
diff --git a/crates/plotnik-lib/src/parser/tests/grammar/captures_tests.rs b/crates/plotnik-lib/src/parser/tests/grammar/captures_tests.rs
index 03f897a9..24a39b16 100644
--- a/crates/plotnik-lib/src/parser/tests/grammar/captures_tests.rs
+++ b/crates/plotnik-lib/src/parser/tests/grammar/captures_tests.rs
@@ -7,9 +7,9 @@ fn capture() {
Q = (identifier) @name
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -30,9 +30,9 @@ fn capture_nested() {
Q = (call function: (identifier) @func)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -62,9 +62,9 @@ fn multiple_captures() {
right: (_) @right) @expr
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -105,9 +105,9 @@ fn capture_with_type_annotation() {
Q = (identifier) @name :: string
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -131,9 +131,9 @@ fn capture_with_custom_type() {
Q = (function_declaration) @fn :: FunctionDecl
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -157,9 +157,9 @@ fn capture_without_type_annotation() {
Q = (identifier) @name
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -182,9 +182,9 @@ fn multiple_captures_with_types() {
right: (_) @right :: string) @expr :: BinaryExpr
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -234,9 +234,9 @@ fn sequence_capture_with_type() {
Q = {(a) (b)} @seq :: MySequence
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -267,9 +267,9 @@ fn alternation_capture_with_type() {
Q = [(identifier) (number)] @value :: Value
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -302,9 +302,9 @@ fn quantified_capture_with_type() {
Q = (statement)+ @stmts :: Statement
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -333,9 +333,9 @@ fn nested_captures_with_types() {
(statement)* @body_stmts :: Statement)) @func :: Function
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -391,9 +391,9 @@ fn capture_with_type_no_spaces() {
Q = (identifier) @name::string
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -417,9 +417,9 @@ fn capture_literal() {
Q = "foo" @keyword
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -440,9 +440,9 @@ fn capture_literal_with_type() {
Q = "return" @kw :: string
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -466,9 +466,9 @@ fn capture_literal_in_tree() {
Q = (binary_expression "+" @op)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -493,9 +493,9 @@ fn capture_literal_with_quantifier() {
Q = ","* @commas
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
diff --git a/crates/plotnik-lib/src/parser/tests/grammar/definitions_tests.rs b/crates/plotnik-lib/src/parser/tests/grammar/definitions_tests.rs
index e53d6647..642444c0 100644
--- a/crates/plotnik-lib/src/parser/tests/grammar/definitions_tests.rs
+++ b/crates/plotnik-lib/src/parser/tests/grammar/definitions_tests.rs
@@ -7,9 +7,9 @@ fn simple_named_def() {
Expr = (identifier)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Expr"
@@ -27,9 +27,9 @@ fn named_def_with_alternation() {
Value = [(identifier) (number) (string)]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Value"
@@ -61,9 +61,9 @@ fn named_def_with_sequence() {
Pair = {(identifier) (expression)}
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Pair"
@@ -91,9 +91,9 @@ fn named_def_with_captures() {
right: (_) @right)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "BinaryOp"
@@ -140,9 +140,9 @@ fn multiple_named_defs() {
Stmt = (statement)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Expr"
@@ -168,39 +168,14 @@ fn named_def_then_expression() {
(program (Expr) @value)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
- Root
- Def
- Id "Expr"
- Equals "="
- Alt
- BracketOpen "["
- Branch
- Tree
- ParenOpen "("
- Id "identifier"
- ParenClose ")"
- Branch
- Tree
- ParenOpen "("
- Id "number"
- ParenClose ")"
- BracketClose "]"
- Def
- Tree
- ParenOpen "("
- Id "program"
- Capture
- Ref
- ParenOpen "("
- Id "Expr"
- ParenClose ")"
- At "@"
- Id "value"
- ParenClose ")"
- "#);
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
+ error: definitions must be named — give it a name like `Name = (program (Expr) @value)`
+ |
+ 2 | (program (Expr) @value)
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ ");
}
#[test]
@@ -210,9 +185,9 @@ fn named_def_referencing_another() {
Expr = [(identifier) (Literal)]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Literal"
@@ -255,9 +230,9 @@ fn named_def_with_quantifier() {
Statements = (statement)+
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Statements"
@@ -279,9 +254,9 @@ fn named_def_complex_recursive() {
arguments: (arguments))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "NestedCall"
@@ -330,9 +305,9 @@ fn named_def_with_type_annotation() {
body: (_) @body)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Func"
@@ -374,9 +349,9 @@ fn unnamed_def_allowed_as_last() {
Q = (program (Expr) @value)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Expr"
diff --git a/crates/plotnik-lib/src/parser/tests/grammar/fields_tests.rs b/crates/plotnik-lib/src/parser/tests/grammar/fields_tests.rs
index 9e7d16c3..2c72200d 100644
--- a/crates/plotnik-lib/src/parser/tests/grammar/fields_tests.rs
+++ b/crates/plotnik-lib/src/parser/tests/grammar/fields_tests.rs
@@ -7,9 +7,9 @@ fn field_expression() {
Q = (call function: (identifier))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -36,9 +36,9 @@ fn multiple_fields() {
right: (expression))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -70,9 +70,9 @@ fn negated_field() {
Q = (function !async)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -95,9 +95,9 @@ fn negated_and_regular_fields() {
name: (identifier))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -128,9 +128,9 @@ fn mixed_children_and_fields() {
else: (else_block))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -172,9 +172,9 @@ fn fields_and_quantifiers() {
baz: (baz)+?)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -246,9 +246,9 @@ fn fields_with_quantifiers_and_captures() {
Q = (node foo: (bar)* @baz)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
diff --git a/crates/plotnik-lib/src/parser/tests/grammar/nodes_tests.rs b/crates/plotnik-lib/src/parser/tests/grammar/nodes_tests.rs
index 82499f97..5642400d 100644
--- a/crates/plotnik-lib/src/parser/tests/grammar/nodes_tests.rs
+++ b/crates/plotnik-lib/src/parser/tests/grammar/nodes_tests.rs
@@ -3,9 +3,7 @@ use indoc::indoc;
#[test]
fn empty_input() {
- let query = Query::try_from("").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @"Root");
+ insta::assert_snapshot!(Query::expect_valid_cst(""), @"Root");
}
#[test]
@@ -14,9 +12,9 @@ fn simple_named_node() {
Q = (identifier)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -34,9 +32,9 @@ fn nested_node() {
Q = (function_definition name: (identifier))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -64,9 +62,9 @@ fn deeply_nested() {
(d))))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -99,9 +97,9 @@ fn sibling_children() {
(statement))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -131,9 +129,9 @@ fn wildcard() {
Q = (_)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -151,9 +149,9 @@ fn anonymous_node() {
Q = "if"
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -171,9 +169,9 @@ fn anonymous_node_operator() {
Q = "+="
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -191,9 +189,9 @@ fn supertype_basic() {
Q = (expression/binary_expression)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -213,9 +211,9 @@ fn supertype_with_string_subtype() {
Q = (expression/"()")
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -237,9 +235,9 @@ fn supertype_with_capture() {
Q = (expression/binary_expression) @expr
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -264,9 +262,9 @@ fn supertype_with_children() {
right: (_) @right)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -307,9 +305,9 @@ fn supertype_nested() {
(expression/call_expression))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -335,9 +333,9 @@ fn supertype_in_alternation() {
Q = [(expression/identifier) (expression/number)]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -368,9 +366,9 @@ fn no_supertype_plain_node() {
Q = (identifier)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
diff --git a/crates/plotnik-lib/src/parser/tests/grammar/quantifiers_tests.rs b/crates/plotnik-lib/src/parser/tests/grammar/quantifiers_tests.rs
index 1aa082c7..d324978b 100644
--- a/crates/plotnik-lib/src/parser/tests/grammar/quantifiers_tests.rs
+++ b/crates/plotnik-lib/src/parser/tests/grammar/quantifiers_tests.rs
@@ -7,9 +7,9 @@ fn quantifier_star() {
Q = (statement)*
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -29,9 +29,9 @@ fn quantifier_plus() {
Q = (statement)+
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -51,9 +51,9 @@ fn quantifier_optional() {
Q = (statement)?
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -73,9 +73,9 @@ fn quantifier_with_capture() {
Q = (statement)* @statements
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -99,9 +99,9 @@ fn quantifier_inside_node() {
(statement)*)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
diff --git a/crates/plotnik-lib/src/parser/tests/grammar/sequences_tests.rs b/crates/plotnik-lib/src/parser/tests/grammar/sequences_tests.rs
index de18f9ae..b1dfcdd8 100644
--- a/crates/plotnik-lib/src/parser/tests/grammar/sequences_tests.rs
+++ b/crates/plotnik-lib/src/parser/tests/grammar/sequences_tests.rs
@@ -7,9 +7,9 @@ fn simple_sequence() {
Q = {(a) (b)}
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -34,9 +34,9 @@ fn empty_sequence() {
Q = {}
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -53,9 +53,9 @@ fn sequence_single_element() {
Q = {(identifier)}
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -76,9 +76,9 @@ fn sequence_with_captures() {
Q = {(comment)* @comments (function) @fn}
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -111,9 +111,9 @@ fn sequence_with_quantifier() {
Q = {(a) (b)}+
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -140,9 +140,9 @@ fn nested_sequences() {
Q = {{(a)} {(b)}}
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -173,9 +173,9 @@ fn sequence_in_named_node() {
Q = (block {(statement) (statement)})
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -204,9 +204,9 @@ fn sequence_with_alternation() {
Q = {[(a) (b)] (c)}
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -240,9 +240,9 @@ fn sequence_comma_separated_expression() {
Q = {(number) {"," (number)}*}
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -276,9 +276,9 @@ fn sequence_with_anchor() {
Q = {. (first) (second) .}
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
diff --git a/crates/plotnik-lib/src/parser/tests/grammar/special_tests.rs b/crates/plotnik-lib/src/parser/tests/grammar/special_tests.rs
index 543df22a..985c8824 100644
--- a/crates/plotnik-lib/src/parser/tests/grammar/special_tests.rs
+++ b/crates/plotnik-lib/src/parser/tests/grammar/special_tests.rs
@@ -7,9 +7,9 @@ fn error_node() {
Q = (ERROR)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -27,9 +27,9 @@ fn error_node_with_capture() {
Q = (ERROR) @err
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -50,9 +50,9 @@ fn missing_node_bare() {
Q = (MISSING)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -70,9 +70,9 @@ fn missing_node_with_type() {
Q = (MISSING identifier)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -91,9 +91,9 @@ fn missing_node_with_string() {
Q = (MISSING ";")
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -114,9 +114,9 @@ fn missing_node_with_capture() {
Q = (MISSING ";") @missing_semi
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -140,9 +140,9 @@ fn error_in_alternation() {
Q = [(ERROR) (identifier)]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -169,9 +169,9 @@ fn missing_in_sequence() {
Q = {(MISSING ";") (identifier)}
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -200,9 +200,9 @@ fn special_node_nested() {
body: (block (ERROR)))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -231,9 +231,9 @@ fn error_with_quantifier() {
Q = (ERROR)*
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -253,9 +253,9 @@ fn missing_with_quantifier() {
Q = (MISSING identifier)?
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
diff --git a/crates/plotnik-lib/src/parser/tests/grammar/trivia_tests.rs b/crates/plotnik-lib/src/parser/tests/grammar/trivia_tests.rs
index 791a0075..b3a773f0 100644
--- a/crates/plotnik-lib/src/parser/tests/grammar/trivia_tests.rs
+++ b/crates/plotnik-lib/src/parser/tests/grammar/trivia_tests.rs
@@ -7,9 +7,9 @@ fn whitespace_preserved() {
Q = (identifier) @name
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst_full(), @r#"
+ let res = Query::expect_valid_cst_full(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -35,9 +35,9 @@ fn comment_preserved() {
Q = (identifier)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst_full(), @r#"
+ let res = Query::expect_valid_cst_full(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
LineComment "// comment"
Newline "\n"
@@ -61,9 +61,9 @@ fn comment_inside_expression() {
name: (identifier))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst_full(), @r#"
+ let res = Query::expect_valid_cst_full(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -97,17 +97,22 @@ fn trivia_filtered_by_default() {
Q = (identifier)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst_full(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
+ LineComment "// comment"
+ Newline "\n"
Def
Id "Q"
+ Whitespace " "
Equals "="
+ Whitespace " "
Tree
ParenOpen "("
Id "identifier"
ParenClose ")"
+ Newline "\n"
"#);
}
@@ -120,9 +125,9 @@ fn trivia_between_alternation_items() {
]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst_full(), @r#"
+ let res = Query::expect_valid_cst_full(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -155,9 +160,9 @@ fn trivia_between_alternation_items() {
fn whitespace_only() {
let input = " ";
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst_full(), @r#"
+ let res = Query::expect_valid_cst_full(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Whitespace " "
"#);
@@ -169,9 +174,9 @@ fn comment_only_raw() {
// just a comment
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst_full(), @r#"
+ let res = Query::expect_valid_cst_full(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
LineComment "// just a comment"
Newline "\n"
diff --git a/crates/plotnik-lib/src/parser/tests/recovery/coverage_tests.rs b/crates/plotnik-lib/src/parser/tests/recovery/coverage_tests.rs
index a783fac6..ad32e3d9 100644
--- a/crates/plotnik-lib/src/parser/tests/recovery/coverage_tests.rs
+++ b/crates/plotnik-lib/src/parser/tests/recovery/coverage_tests.rs
@@ -135,9 +135,9 @@ fn named_def_missing_equals_with_garbage() {
Q = Expr ^^^ (identifier)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r#"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r#"
error: bare identifier is not a valid expression; wrap in parentheses: `(identifier)`
|
1 | Q = Expr ^^^ (identifier)
@@ -157,9 +157,9 @@ fn named_def_missing_equals_recovers_to_next_def() {
Valid = (ok)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r#"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r#"
error: bare identifier is not a valid expression; wrap in parentheses: `(identifier)`
|
1 | Broken ^^^
@@ -178,9 +178,9 @@ fn empty_double_quote_string() {
Q = (a "")
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -201,9 +201,9 @@ fn empty_single_quote_string() {
Q = (a '')
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -222,9 +222,9 @@ fn empty_single_quote_string() {
fn single_quote_string_is_valid() {
let input = "Q = (node 'if')";
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -244,9 +244,9 @@ fn single_quote_string_is_valid() {
fn single_quote_in_alternation() {
let input = "Q = ['public' 'private']";
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -271,9 +271,9 @@ fn single_quote_in_alternation() {
fn single_quote_with_escape() {
let input = r"Q = (node 'it\'s')";
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
@@ -293,9 +293,9 @@ fn single_quote_with_escape() {
fn missing_with_nested_tree_parses() {
let input = "Q = (MISSING (something))";
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_cst(), @r#"
+ let res = Query::expect_valid_cst(input);
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
Id "Q"
diff --git a/crates/plotnik-lib/src/parser/tests/recovery/incomplete_tests.rs b/crates/plotnik-lib/src/parser/tests/recovery/incomplete_tests.rs
index 9bf981a2..3f61c647 100644
--- a/crates/plotnik-lib/src/parser/tests/recovery/incomplete_tests.rs
+++ b/crates/plotnik-lib/src/parser/tests/recovery/incomplete_tests.rs
@@ -7,9 +7,9 @@ fn missing_capture_name() {
(identifier) @
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: expected name after `@`
|
1 | (identifier) @
@@ -23,9 +23,9 @@ fn missing_field_value() {
(call name:)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: expected an expression; after `field:`
|
1 | (call name:)
@@ -37,9 +37,9 @@ fn missing_field_value() {
fn named_def_eof_after_equals() {
let input = "Expr = ";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: expected an expression; after `=` in definition
|
1 | Expr =
@@ -53,9 +53,9 @@ fn missing_type_name() {
(identifier) @name ::
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: expected type name after `::`; e.g., `::MyType` or `::string`
|
1 | (identifier) @name ::
@@ -69,9 +69,9 @@ fn missing_negated_field_name() {
(call !)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: expected field name; e.g., `!value`
|
1 | (call !)
@@ -85,9 +85,9 @@ fn missing_subtype() {
(expression/)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: expected subtype after `/`; e.g., `expression/binary_expression`
|
1 | (expression/)
@@ -101,9 +101,9 @@ fn tagged_branch_missing_expression() {
[Label:]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: expected an expression; after `Label:`
|
1 | [Label:]
@@ -115,9 +115,9 @@ fn tagged_branch_missing_expression() {
fn type_annotation_missing_name_at_eof() {
let input = "(a) @x ::";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: expected type name after `::`; e.g., `::MyType` or `::string`
|
1 | (a) @x ::
@@ -129,9 +129,9 @@ fn type_annotation_missing_name_at_eof() {
fn type_annotation_missing_name_with_bracket() {
let input = "[(a) @x :: ]";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: expected type name after `::`; e.g., `::MyType` or `::string`
|
1 | [(a) @x :: ]
@@ -145,9 +145,9 @@ fn type_annotation_invalid_token_after() {
(identifier) @name :: (
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: expected type name after `::`; e.g., `::MyType` or `::string`
|
1 | (identifier) @name :: (
@@ -161,9 +161,9 @@ fn field_value_is_garbage() {
(call name: %%%)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: expected an expression; after `field:`
|
1 | (call name: %%%)
@@ -177,9 +177,9 @@ fn capture_with_invalid_char() {
(identifier) @123
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: expected name after `@`
|
1 | (identifier) @123
@@ -191,9 +191,9 @@ fn capture_with_invalid_char() {
fn bare_capture_at_eof_triggers_sync() {
let input = "@";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: `@` must follow an expression to capture
|
1 | @
@@ -207,9 +207,9 @@ fn bare_capture_at_root() {
@name
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: `@` must follow an expression to capture
|
1 | @name
@@ -223,9 +223,9 @@ fn capture_at_start_of_alternation() {
[@x (a)]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: unexpected token; not valid inside alternation — try `(node)` or close with `]`
|
1 | [@x (a)]
@@ -239,9 +239,9 @@ fn mixed_valid_invalid_captures() {
(a) @ok @ @name
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: `@` must follow an expression to capture
|
1 | (a) @ok @ @name
@@ -260,9 +260,9 @@ fn field_equals_typo_missing_value() {
(call name = )
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: use `:` for field constraints, not `=`; this isn't a definition
|
1 | (call name = )
@@ -285,9 +285,9 @@ fn field_equals_typo_missing_value() {
fn lowercase_branch_label_missing_expression() {
let input = "[label:]";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: branch labels must be capitalized; branch labels map to enum variants
|
1 | [label:]
diff --git a/crates/plotnik-lib/src/parser/tests/recovery/unclosed_tests.rs b/crates/plotnik-lib/src/parser/tests/recovery/unclosed_tests.rs
index deeb308b..0b27aacd 100644
--- a/crates/plotnik-lib/src/parser/tests/recovery/unclosed_tests.rs
+++ b/crates/plotnik-lib/src/parser/tests/recovery/unclosed_tests.rs
@@ -7,9 +7,9 @@ fn missing_paren() {
(identifier
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: missing closing `)`; expected `)`
|
1 | (identifier
@@ -25,9 +25,9 @@ fn missing_bracket() {
[(identifier) (string)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: missing closing `]`; expected `]`
|
1 | [(identifier) (string)
@@ -43,9 +43,9 @@ fn missing_brace() {
{(a) (b)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: missing closing `}`; expected `}`
|
1 | {(a) (b)
@@ -61,9 +61,9 @@ fn nested_unclosed() {
(a (b (c)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: missing closing `)`; expected `)`
|
1 | (a (b (c)
@@ -79,9 +79,9 @@ fn deeply_nested_unclosed() {
(a (b (c (d
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: missing closing `)`; expected `)`
|
1 | (a (b (c (d
@@ -97,9 +97,9 @@ fn unclosed_alternation_nested() {
[(a) (b
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: missing closing `)`; expected `)`
|
1 | [(a) (b
@@ -115,9 +115,9 @@ fn empty_parens() {
()
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: empty parentheses are not allowed
|
1 | ()
@@ -132,9 +132,9 @@ fn unclosed_tree_shows_open_location() {
(identifier)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: missing closing `)`; expected `)`
|
1 | (call
@@ -154,9 +154,9 @@ fn unclosed_alternation_shows_open_location() {
(b)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: missing closing `]`; expected `]`
|
1 | [
@@ -177,9 +177,9 @@ fn unclosed_sequence_shows_open_location() {
(b)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: missing closing `}`; expected `}`
|
1 | {
@@ -196,9 +196,9 @@ fn unclosed_sequence_shows_open_location() {
fn unclosed_double_quote_string() {
let input = r#"(call "foo)"#;
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r#"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r#"
error: missing closing `)`; expected `)`
|
1 | (call "foo)
@@ -212,9 +212,9 @@ fn unclosed_double_quote_string() {
fn unclosed_single_quote_string() {
let input = "(call 'foo)";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: missing closing `)`; expected `)`
|
1 | (call 'foo)
diff --git a/crates/plotnik-lib/src/parser/tests/recovery/unexpected_tests.rs b/crates/plotnik-lib/src/parser/tests/recovery/unexpected_tests.rs
index 540d8a31..ce8e6779 100644
--- a/crates/plotnik-lib/src/parser/tests/recovery/unexpected_tests.rs
+++ b/crates/plotnik-lib/src/parser/tests/recovery/unexpected_tests.rs
@@ -7,9 +7,9 @@ fn unexpected_token() {
(identifier) ^^^ (string)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r#"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r#"
error: unexpected token; try `(node)`, `[a b]`, `{a b}`, `"literal"`, or `_`
|
1 | (identifier) ^^^ (string)
@@ -23,9 +23,9 @@ fn multiple_consecutive_garbage() {
^^^ $$$ %%% (ok)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r#"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r#"
error: unexpected token; try `(node)`, `[a b]`, `{a b}`, `"literal"`, or `_`
|
1 | ^^^ $$$ %%% (ok)
@@ -39,9 +39,9 @@ fn garbage_at_start() {
^^^ (a)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r#"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r#"
error: unexpected token; try `(node)`, `[a b]`, `{a b}`, `"literal"`, or `_`
|
1 | ^^^ (a)
@@ -55,9 +55,9 @@ fn only_garbage() {
^^^ $$$
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r#"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r#"
error: unexpected token; try `(node)`, `[a b]`, `{a b}`, `"literal"`, or `_`
|
1 | ^^^ $$$
@@ -71,9 +71,9 @@ fn garbage_inside_alternation() {
[(a) ^^^ (b)]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: unexpected token; not valid inside alternation — try `(node)` or close with `]`
|
1 | [(a) ^^^ (b)]
@@ -87,9 +87,9 @@ fn garbage_inside_node() {
(a (b) @@@ (c)) (d)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: expected name after `@`
|
1 | (a (b) @@@ (c)) (d)
@@ -103,9 +103,9 @@ fn xml_tag_garbage() {
(identifier)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r#"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r#"
error: unexpected token; try `(node)`, `[a b]`, `{a b}`, `"literal"`, or `_`
|
1 | (identifier)
@@ -124,9 +124,9 @@ fn xml_self_closing() {
(a)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r#"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r#"
error: unexpected token; try `(node)`, `[a b]`, `{a b}`, `"literal"`, or `_`
|
1 |
(a)
@@ -140,9 +140,9 @@ fn predicate_unsupported() {
(a (#eq? @x "foo") b)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r#"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r#"
error: predicates like `#match?` are not supported
|
1 | (a (#eq? @x "foo") b)
@@ -166,9 +166,9 @@ fn predicate_match() {
(identifier) #match? @name "test"
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r#"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r#"
error: predicates like `#match?` are not supported
|
1 | (identifier) #match? @name "test"
@@ -185,9 +185,9 @@ fn predicate_match() {
fn predicate_in_tree() {
let input = "(function #eq? @name \"test\")";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r#"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r#"
error: predicates like `#match?` are not supported
|
1 | (function #eq? @name "test")
@@ -206,9 +206,9 @@ fn predicate_in_alternation() {
[(a) #eq? (b)]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: unexpected token; not valid inside alternation — try `(node)` or close with `]`
|
1 | [(a) #eq? (b)]
@@ -222,9 +222,9 @@ fn predicate_in_sequence() {
{(a) #set! (b)}
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: predicates like `#match?` are not supported
|
1 | {(a) #set! (b)}
@@ -240,9 +240,9 @@ fn multiline_garbage_recovery() {
b)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: unexpected token; not valid inside a node — try `(child)` or close with `)`
|
2 | ^^^
@@ -261,9 +261,9 @@ fn top_level_garbage_recovery() {
Expr = (a) ^^^ Expr2 = (b)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r#"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r#"
error: unexpected token; try `(node)`, `[a b]`, `{a b}`, `"literal"`, or `_`
|
1 | Expr = (a) ^^^ Expr2 = (b)
@@ -281,9 +281,9 @@ fn multiple_definitions_with_garbage_between() {
C = (c)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r#"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r#"
error: unexpected token; try `(node)`, `[a b]`, `{a b}`, `"literal"`, or `_`
|
2 | ^^^
@@ -302,9 +302,9 @@ fn alternation_recovery_to_capture() {
[^^^ @name]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: unexpected token; not valid inside alternation — try `(node)` or close with `]`
|
1 | [^^^ @name]
@@ -323,9 +323,9 @@ fn comma_between_defs() {
A = (a), B = (b)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r#"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r#"
error: unexpected token; try `(node)`, `[a b]`, `{a b}`, `"literal"`, or `_`
|
1 | A = (a), B = (b)
@@ -337,9 +337,9 @@ fn comma_between_defs() {
fn bare_colon_in_tree() {
let input = "(a : (b))";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: unexpected token; not valid inside a node — try `(child)` or close with `)`
|
1 | (a : (b))
@@ -351,9 +351,9 @@ fn bare_colon_in_tree() {
fn paren_close_inside_alternation() {
let input = "[(a) ) (b)]";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r#"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r#"
error: unexpected token; expected closing ']' for alternation
|
1 | [(a) ) (b)]
@@ -370,9 +370,9 @@ fn paren_close_inside_alternation() {
fn bracket_close_inside_sequence() {
let input = "{(a) ] (b)}";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r#"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r#"
error: unexpected token; expected closing '}' for sequence
|
1 | {(a) ] (b)}
@@ -389,9 +389,9 @@ fn bracket_close_inside_sequence() {
fn paren_close_inside_sequence() {
let input = "{(a) ) (b)}";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r#"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r#"
error: unexpected token; expected closing '}' for sequence
|
1 | {(a) ) (b)}
@@ -408,9 +408,9 @@ fn paren_close_inside_sequence() {
fn single_colon_type_annotation_followed_by_non_id() {
let input = "(a) @x : (b)";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r#"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r#"
error: unexpected token; try `(node)`, `[a b]`, `{a b}`, `"literal"`, or `_`
|
1 | (a) @x : (b)
@@ -422,9 +422,9 @@ fn single_colon_type_annotation_followed_by_non_id() {
fn single_colon_type_annotation_at_eof() {
let input = "(a) @x :";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r#"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r#"
error: unexpected token; try `(node)`, `[a b]`, `{a b}`, `"literal"`, or `_`
|
1 | (a) @x :
diff --git a/crates/plotnik-lib/src/parser/tests/recovery/validation_tests.rs b/crates/plotnik-lib/src/parser/tests/recovery/validation_tests.rs
index 6967e70b..f8c8e151 100644
--- a/crates/plotnik-lib/src/parser/tests/recovery/validation_tests.rs
+++ b/crates/plotnik-lib/src/parser/tests/recovery/validation_tests.rs
@@ -8,9 +8,9 @@ fn ref_with_children_error() {
(Expr (child))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: `Expr` is a reference and cannot have children
|
2 | (Expr (child))
@@ -25,9 +25,9 @@ fn ref_with_multiple_children_error() {
(Expr (a) (b) @cap)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: `Expr` is a reference and cannot have children
|
2 | (Expr (a) (b) @cap)
@@ -42,9 +42,9 @@ fn ref_with_field_children_error() {
(Expr name: (identifier))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: `Expr` is a reference and cannot have children
|
2 | (Expr name: (identifier))
@@ -56,9 +56,9 @@ fn ref_with_field_children_error() {
fn reference_with_supertype_syntax_error() {
let input = "(RefName/subtype)";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: supertype syntax not allowed on references
|
1 | (RefName/subtype)
@@ -72,9 +72,9 @@ fn mixed_tagged_and_untagged() {
[Tagged: (a) (b) Another: (c)]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: cannot mix labeled and unlabeled branches
|
1 | [Tagged: (a) (b) Another: (c)]
@@ -90,9 +90,9 @@ fn error_with_unexpected_content() {
(ERROR (something))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: `(ERROR)` cannot have child nodes
|
1 | (ERROR (something))
@@ -106,9 +106,9 @@ fn bare_error_keyword() {
ERROR
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: `ERROR` and `MISSING` must be wrapped in parentheses
|
1 | ERROR
@@ -122,9 +122,9 @@ fn bare_missing_keyword() {
MISSING
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: `ERROR` and `MISSING` must be wrapped in parentheses
|
1 | MISSING
@@ -138,9 +138,9 @@ fn upper_ident_in_alternation_not_followed_by_colon() {
[(Expr) (Statement)]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: `Expr` is not defined
|
1 | [(Expr) (Statement)]
@@ -159,9 +159,9 @@ fn upper_ident_not_followed_by_equals_is_expression() {
(Expr)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: `Expr` is not defined
|
1 | (Expr)
@@ -175,9 +175,9 @@ fn bare_upper_ident_not_followed_by_equals_is_error() {
Expr
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: bare identifier is not a valid expression; wrap in parentheses: `(identifier)`
|
1 | Expr
@@ -191,9 +191,9 @@ fn named_def_missing_equals() {
Expr (identifier)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: bare identifier is not a valid expression; wrap in parentheses: `(identifier)`
|
1 | Expr (identifier)
@@ -209,9 +209,9 @@ fn unnamed_def_not_allowed_in_middle() {
(last)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: definitions must be named — give it a name like `Name = (first)`
|
1 | (first)
@@ -232,9 +232,9 @@ fn multiple_unnamed_defs_errors_for_all_but_last() {
(third)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: definitions must be named — give it a name like `Name = (first)`
|
1 | (first)
@@ -258,9 +258,9 @@ fn capture_space_after_dot_is_anchor() {
(identifier) @foo . (other)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: definitions must be named — give it a name like `Name = (identifier) @foo`
|
1 | (identifier) @foo . (other)
@@ -282,9 +282,9 @@ fn capture_space_after_dot_is_anchor() {
fn def_name_lowercase_error() {
let input = "lowercase = (x)";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: definition names must start uppercase; definitions map to types
|
1 | lowercase = (x)
@@ -304,9 +304,9 @@ fn def_name_snake_case_suggests_pascal() {
my_expr = (identifier)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: definition names must start uppercase; definitions map to types
|
1 | my_expr = (identifier)
@@ -326,9 +326,9 @@ fn def_name_kebab_case_suggests_pascal() {
my-expr = (identifier)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: definition names must start uppercase; definitions map to types
|
1 | my-expr = (identifier)
@@ -348,9 +348,9 @@ fn def_name_dotted_suggests_pascal() {
my.expr = (identifier)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: definition names must start uppercase; definitions map to types
|
1 | my.expr = (identifier)
@@ -368,9 +368,9 @@ fn def_name_dotted_suggests_pascal() {
fn def_name_with_underscores_error() {
let input = "Some_Thing = (x)";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: definition names must be PascalCase; definitions map to types
|
1 | Some_Thing = (x)
@@ -388,9 +388,9 @@ fn def_name_with_underscores_error() {
fn def_name_with_hyphens_error() {
let input = "Some-Thing = (x)";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: definition names must be PascalCase; definitions map to types
|
1 | Some-Thing = (x)
@@ -410,9 +410,9 @@ fn capture_name_pascal_case_error() {
(a) @Name
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: capture names must be lowercase; captures become struct fields
|
1 | (a) @Name
@@ -432,9 +432,9 @@ fn capture_name_pascal_case_with_hyphens_error() {
(a) @My-Name
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: capture names cannot contain `-`; captures become struct fields
|
1 | (a) @My-Name
@@ -454,9 +454,9 @@ fn capture_name_with_hyphens_error() {
(a) @my-name
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: capture names cannot contain `-`; captures become struct fields
|
1 | (a) @my-name
@@ -476,9 +476,9 @@ fn capture_dotted_error() {
(identifier) @foo.bar
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: capture names cannot contain `.`; captures become struct fields
|
1 | (identifier) @foo.bar
@@ -498,9 +498,9 @@ fn capture_dotted_multiple_parts() {
(identifier) @foo.bar.baz
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: capture names cannot contain `.`; captures become struct fields
|
1 | (identifier) @foo.bar.baz
@@ -520,9 +520,9 @@ fn capture_dotted_followed_by_field() {
(node) @foo.bar name: (other)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: capture names cannot contain `.`; captures become struct fields
|
1 | (node) @foo.bar name: (other)
@@ -542,9 +542,9 @@ fn capture_space_after_dot_breaks_chain() {
(identifier) @foo. bar
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: capture names cannot contain `.`; captures become struct fields
|
1 | (identifier) @foo. bar
@@ -569,9 +569,9 @@ fn capture_hyphenated_error() {
(identifier) @foo-bar
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: capture names cannot contain `-`; captures become struct fields
|
1 | (identifier) @foo-bar
@@ -591,9 +591,9 @@ fn capture_hyphenated_multiple() {
(identifier) @foo-bar-baz
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: capture names cannot contain `-`; captures become struct fields
|
1 | (identifier) @foo-bar-baz
@@ -613,9 +613,9 @@ fn capture_mixed_dots_and_hyphens() {
(identifier) @foo.bar-baz
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: capture names cannot contain `.`; captures become struct fields
|
1 | (identifier) @foo.bar-baz
@@ -635,9 +635,9 @@ fn field_name_pascal_case_error() {
(call Name: (a))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: field names must be lowercase; field names become struct fields
|
1 | (call Name: (a))
@@ -655,9 +655,9 @@ fn field_name_pascal_case_error() {
fn field_name_with_dots_error() {
let input = "(call foo.bar: (x))";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: field names cannot contain `.`; field names become struct fields
|
1 | (call foo.bar: (x))
@@ -675,9 +675,9 @@ fn field_name_with_dots_error() {
fn field_name_with_hyphens_error() {
let input = "(call foo-bar: (x))";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: field names cannot contain `-`; field names become struct fields
|
1 | (call foo-bar: (x))
@@ -697,9 +697,9 @@ fn negated_field_with_upper_ident_parses() {
(call !Arguments)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: field names must be lowercase; field names become struct fields
|
1 | (call !Arguments)
@@ -719,9 +719,9 @@ fn branch_label_snake_case_suggests_pascal() {
[My_branch: (a) Other: (b)]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: branch labels must be PascalCase; branch labels map to enum variants
|
1 | [My_branch: (a) Other: (b)]
@@ -741,9 +741,9 @@ fn branch_label_kebab_case_suggests_pascal() {
[My-branch: (a) Other: (b)]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: branch labels must be PascalCase; branch labels map to enum variants
|
1 | [My-branch: (a) Other: (b)]
@@ -763,9 +763,9 @@ fn branch_label_dotted_suggests_pascal() {
[My.branch: (a) Other: (b)]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: branch labels must be PascalCase; branch labels map to enum variants
|
1 | [My.branch: (a) Other: (b)]
@@ -783,9 +783,9 @@ fn branch_label_dotted_suggests_pascal() {
fn branch_label_with_underscores_error() {
let input = "[Some_Label: (x)]";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: branch labels must be PascalCase; branch labels map to enum variants
|
1 | [Some_Label: (x)]
@@ -803,9 +803,9 @@ fn branch_label_with_underscores_error() {
fn branch_label_with_hyphens_error() {
let input = "[Some-Label: (x)]";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: branch labels must be PascalCase; branch labels map to enum variants
|
1 | [Some-Label: (x)]
@@ -828,9 +828,9 @@ fn lowercase_branch_label() {
]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: branch labels must be capitalized; branch labels map to enum variants
|
2 | left: (a)
@@ -861,9 +861,9 @@ fn lowercase_branch_label_suggests_capitalized() {
[first: (a) Second: (b)]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: branch labels must be capitalized; branch labels map to enum variants
|
1 | [first: (a) Second: (b)]
@@ -881,9 +881,9 @@ fn lowercase_branch_label_suggests_capitalized() {
fn mixed_case_branch_labels() {
let input = "[foo: (a) Bar: (b)]";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: branch labels must be capitalized; branch labels map to enum variants
|
1 | [foo: (a) Bar: (b)]
@@ -903,9 +903,9 @@ fn type_annotation_dotted_suggests_pascal() {
(a) @x :: My.Type
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: type names cannot contain `.` or `-`; type annotations map to types
|
1 | (a) @x :: My.Type
@@ -925,9 +925,9 @@ fn type_annotation_kebab_suggests_pascal() {
(a) @x :: My-Type
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: type names cannot contain `.` or `-`; type annotations map to types
|
1 | (a) @x :: My-Type
@@ -945,9 +945,9 @@ fn type_annotation_kebab_suggests_pascal() {
fn type_name_with_dots_error() {
let input = "(x) @name :: Some.Type";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: type names cannot contain `.` or `-`; type annotations map to types
|
1 | (x) @name :: Some.Type
@@ -965,9 +965,9 @@ fn type_name_with_dots_error() {
fn type_name_with_hyphens_error() {
let input = "(x) @name :: Some-Type";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: type names cannot contain `.` or `-`; type annotations map to types
|
1 | (x) @name :: Some-Type
@@ -985,9 +985,9 @@ fn type_name_with_hyphens_error() {
fn comma_in_node_children() {
let input = "(node (a), (b))";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: separators are not needed; plotnik uses whitespace, not `,`
|
1 | (node (a), (b))
@@ -1005,9 +1005,9 @@ fn comma_in_node_children() {
fn comma_in_alternation() {
let input = "[(a), (b), (c)]";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: separators are not needed; plotnik uses whitespace, not `,`
|
1 | [(a), (b), (c)]
@@ -1036,9 +1036,9 @@ fn comma_in_alternation() {
fn comma_in_sequence() {
let input = "{(a), (b)}";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: separators are not needed; plotnik uses whitespace, not `,`
|
1 | {(a), (b)}
@@ -1056,9 +1056,9 @@ fn comma_in_sequence() {
fn pipe_in_alternation() {
let input = "[(a) | (b) | (c)]";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: separators are not needed; plotnik uses whitespace, not `|`
|
1 | [(a) | (b) | (c)]
@@ -1089,9 +1089,9 @@ fn pipe_between_branches() {
[(a) | (b)]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: separators are not needed; plotnik uses whitespace, not `|`
|
1 | [(a) | (b)]
@@ -1109,9 +1109,9 @@ fn pipe_between_branches() {
fn pipe_in_tree() {
let input = "(a | b)";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: separators are not needed; plotnik uses whitespace, not `|`
|
1 | (a | b)
@@ -1134,9 +1134,9 @@ fn pipe_in_tree() {
fn pipe_in_sequence() {
let input = "{(a) | (b)}";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: separators are not needed; plotnik uses whitespace, not `|`
|
1 | {(a) | (b)}
@@ -1154,9 +1154,9 @@ fn pipe_in_sequence() {
fn field_equals_typo() {
let input = "(node name = (identifier))";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: use `:` for field constraints, not `=`; this isn't a definition
|
1 | (node name = (identifier))
@@ -1174,9 +1174,9 @@ fn field_equals_typo() {
fn field_equals_typo_no_space() {
let input = "(node name=(identifier))";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: use `:` for field constraints, not `=`; this isn't a definition
|
1 | (node name=(identifier))
@@ -1194,9 +1194,9 @@ fn field_equals_typo_no_space() {
fn field_equals_typo_no_expression() {
let input = "(call name=)";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: use `:` for field constraints, not `=`; this isn't a definition
|
1 | (call name=)
@@ -1216,9 +1216,9 @@ fn field_equals_typo_in_tree() {
(call name = (identifier))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: use `:` for field constraints, not `=`; this isn't a definition
|
1 | (call name = (identifier))
@@ -1236,9 +1236,9 @@ fn field_equals_typo_in_tree() {
fn single_colon_type_annotation() {
let input = "(identifier) @name : Type";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: type annotations use `::`, not `:` — single `:` looks like a field
|
1 | (identifier) @name : Type
@@ -1255,9 +1255,9 @@ fn single_colon_type_annotation() {
fn single_colon_type_annotation_no_space() {
let input = "(identifier) @name:Type";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: type annotations use `::`, not `:` — single `:` looks like a field
|
1 | (identifier) @name:Type
@@ -1276,9 +1276,9 @@ fn single_colon_type_annotation_with_space() {
(a) @x : Type
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: type annotations use `::`, not `:` — single `:` looks like a field
|
1 | (a) @x : Type
@@ -1295,9 +1295,9 @@ fn single_colon_type_annotation_with_space() {
fn single_colon_primitive_type() {
let input = "@val : string";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: `@` must follow an expression to capture
|
1 | @val : string
diff --git a/crates/plotnik-lib/src/query/alt_kinds_tests.rs b/crates/plotnik-lib/src/query/alt_kinds_tests.rs
index 02e2bc05..0c39d963 100644
--- a/crates/plotnik-lib/src/query/alt_kinds_tests.rs
+++ b/crates/plotnik-lib/src/query/alt_kinds_tests.rs
@@ -2,9 +2,11 @@ use crate::Query;
#[test]
fn tagged_alternation_valid() {
- let query = Query::try_from("Q = [A: (a) B: (b)]").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
+ let input = "Q = [A: (a) B: (b)]";
+
+ let res = Query::expect_valid_ast(input);
+
+ insta::assert_snapshot!(res, @r"
Root
Def Q
Alt
@@ -17,9 +19,11 @@ fn tagged_alternation_valid() {
#[test]
fn untagged_alternation_valid() {
- let query = Query::try_from("Q = [(a) (b)]").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
+ let input = "Q = [(a) (b)]";
+
+ let res = Query::expect_valid_ast(input);
+
+ insta::assert_snapshot!(res, @r"
Root
Def Q
Alt
@@ -32,9 +36,11 @@ fn untagged_alternation_valid() {
#[test]
fn mixed_alternation_tagged_first() {
- let query = Query::try_from("Q = [A: (a) (b)]").unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let input = "Q = [A: (a) (b)]";
+
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: cannot mix labeled and unlabeled branches
|
1 | Q = [A: (a) (b)]
@@ -46,17 +52,16 @@ fn mixed_alternation_tagged_first() {
#[test]
fn mixed_alternation_untagged_first() {
- let query = Query::try_from(
- r#"
+ let input = r#"
Q = [
(a)
B: (b)
]
- "#,
- )
- .unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ "#;
+
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: cannot mix labeled and unlabeled branches
|
3 | (a)
@@ -68,9 +73,11 @@ fn mixed_alternation_untagged_first() {
#[test]
fn nested_mixed_alternation() {
- let query = Query::try_from("Q = (call [A: (a) (b)])").unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let input = "Q = (call [A: (a) (b)])";
+
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: cannot mix labeled and unlabeled branches
|
1 | Q = (call [A: (a) (b)])
@@ -82,9 +89,11 @@ fn nested_mixed_alternation() {
#[test]
fn multiple_mixed_alternations() {
- let query = Query::try_from("Q = (foo [A: (a) (b)] [C: (c) (d)])").unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let input = "Q = (foo [A: (a) (b)] [C: (c) (d)])";
+
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: cannot mix labeled and unlabeled branches
|
1 | Q = (foo [A: (a) (b)] [C: (c) (d)])
@@ -103,9 +112,11 @@ fn multiple_mixed_alternations() {
#[test]
fn single_branch_no_error() {
- let query = Query::try_from("Q = [A: (a)]").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
+ let input = "Q = [A: (a)]";
+
+ let res = Query::expect_valid_ast(input);
+
+ insta::assert_snapshot!(res, @r"
Root
Def Q
Alt
diff --git a/crates/plotnik-lib/src/query/dependencies_tests.rs b/crates/plotnik-lib/src/query/dependencies_tests.rs
index 98a1c747..73385b6f 100644
--- a/crates/plotnik-lib/src/query/dependencies_tests.rs
+++ b/crates/plotnik-lib/src/query/dependencies_tests.rs
@@ -3,32 +3,29 @@ use indoc::indoc;
#[test]
fn valid_recursion_with_alternation_base_case() {
- let query = Query::try_from("E = [(x) (call (E))]").unwrap();
-
- assert!(query.is_valid());
+ let input = "E = [(x) (call (E))]";
+ Query::expect_valid(input);
}
#[test]
fn valid_recursion_with_optional() {
- let query = Query::try_from("E = (call (E)?)").unwrap();
-
- assert!(query.is_valid());
+ let input = "E = (call (E)?)";
+ Query::expect_valid(input);
}
#[test]
fn valid_recursion_with_star() {
- let query = Query::try_from("E = (call (E)*)").unwrap();
-
- assert!(query.is_valid());
+ let input = "E = (call (E)*)";
+ Query::expect_valid(input);
}
#[test]
fn invalid_recursion_with_plus() {
- let query = Query::try_from("E = (call (E)+)").unwrap();
+ let input = "E = (call (E)+)";
- assert!(!query.is_valid());
+ let res = Query::expect_invalid(input);
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: infinite recursion: cycle has no escape path
|
1 | E = (call (E)+)
@@ -40,11 +37,11 @@ fn invalid_recursion_with_plus() {
#[test]
fn invalid_unguarded_recursion_in_alternation() {
- let query = Query::try_from("E = [(call) (E)]").unwrap();
+ let input = "E = [(call) (E)]";
- assert!(!query.is_valid());
+ let res = Query::expect_invalid(input);
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: infinite recursion: cycle consumes no input
|
1 | E = [(call) (E)]
@@ -56,18 +53,18 @@ fn invalid_unguarded_recursion_in_alternation() {
#[test]
fn validity_of_lazy_quantifiers_matches_greedy() {
- assert!(Query::try_from("E = (call (E)??)").unwrap().is_valid());
- assert!(Query::try_from("E = (call (E)*?)").unwrap().is_valid());
- assert!(!Query::try_from("E = (call (E)+?)").unwrap().is_valid());
+ Query::expect_valid("E = (call (E)??)");
+ Query::expect_valid("E = (call (E)*?)");
+ Query::expect_invalid("E = (call (E)+?)");
}
#[test]
fn invalid_mandatory_recursion_in_tree_child() {
- let query = Query::try_from("E = (call (E))").unwrap();
+ let input = "E = (call (E))";
- assert!(!query.is_valid());
+ let res = Query::expect_invalid(input);
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: infinite recursion: cycle has no escape path
|
1 | E = (call (E))
@@ -79,11 +76,11 @@ fn invalid_mandatory_recursion_in_tree_child() {
#[test]
fn invalid_mandatory_recursion_in_field() {
- let query = Query::try_from("E = (call body: (E))").unwrap();
+ let input = "E = (call body: (E))";
- assert!(!query.is_valid());
+ let res = Query::expect_invalid(input);
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: infinite recursion: cycle has no escape path
|
1 | E = (call body: (E))
@@ -95,11 +92,11 @@ fn invalid_mandatory_recursion_in_field() {
#[test]
fn invalid_mandatory_recursion_in_capture() {
- let query = Query::try_from("E = (call (E) @inner)").unwrap();
+ let input = "E = (call (E) @inner)";
- assert!(!query.is_valid());
+ let res = Query::expect_invalid(input);
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: infinite recursion: cycle has no escape path
|
1 | E = (call (E) @inner)
@@ -111,11 +108,11 @@ fn invalid_mandatory_recursion_in_capture() {
#[test]
fn invalid_mandatory_recursion_in_sequence() {
- let query = Query::try_from("E = (call {(a) (E)})").unwrap();
+ let input = "E = (call {(a) (E)})";
- assert!(!query.is_valid());
+ let res = Query::expect_invalid(input);
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: infinite recursion: cycle has no escape path
|
1 | E = (call {(a) (E)})
@@ -127,9 +124,8 @@ fn invalid_mandatory_recursion_in_sequence() {
#[test]
fn valid_recursion_with_base_case_and_descent() {
- let query = Query::try_from("E = [(x) (call (a) (E))]").unwrap();
-
- assert!(query.is_valid());
+ let input = "E = [(x) (call (a) (E))]";
+ Query::expect_valid(input);
}
#[test]
@@ -138,11 +134,10 @@ fn invalid_mutual_recursion_without_base_case() {
A = (foo (B))
B = (bar (A))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
+ let res = Query::expect_invalid(input);
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: infinite recursion: cycle has no escape path
|
1 | A = (foo (B))
@@ -161,9 +156,7 @@ fn valid_mutual_recursion_with_base_case() {
A = [(x) (foo (B))]
B = (bar (A))
"#};
- let query = Query::try_from(input).unwrap();
-
- assert!(query.is_valid());
+ Query::expect_valid(input);
}
#[test]
@@ -173,11 +166,10 @@ fn invalid_three_way_mutual_recursion() {
B = (b (C))
C = (c (A))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
+ let res = Query::expect_invalid(input);
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: infinite recursion: cycle has no escape path
|
1 | A = (a (B))
@@ -199,9 +191,7 @@ fn valid_three_way_mutual_recursion_with_base_case() {
B = (b (C))
C = (c (A))
"#};
- let query = Query::try_from(input).unwrap();
-
- assert!(query.is_valid());
+ Query::expect_valid(input);
}
#[test]
@@ -212,11 +202,10 @@ fn invalid_diamond_dependency_recursion() {
C = (c (D))
D = (d (A))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
+ let res = Query::expect_invalid(input);
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: infinite recursion: cycle has no escape path
|
1 | A = (a [(B) (C)])
@@ -238,11 +227,10 @@ fn invalid_mutual_recursion_via_field() {
A = (foo body: (B))
B = (bar (A))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
+ let res = Query::expect_invalid(input);
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: infinite recursion: cycle has no escape path
|
1 | A = (foo body: (B))
@@ -261,11 +249,10 @@ fn invalid_mutual_recursion_via_capture() {
A = (foo (B) @cap)
B = (bar (A))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
+ let res = Query::expect_invalid(input);
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: infinite recursion: cycle has no escape path
|
1 | A = (foo (B) @cap)
@@ -284,11 +271,10 @@ fn invalid_mutual_recursion_via_sequence() {
A = (foo {(x) (B)})
B = (bar (A))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
+ let res = Query::expect_invalid(input);
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: infinite recursion: cycle has no escape path
|
1 | A = (foo {(x) (B)})
@@ -307,9 +293,7 @@ fn valid_mutual_recursion_with_optional_quantifier() {
A = (foo (B)?)
B = (bar (A))
"#};
- let query = Query::try_from(input).unwrap();
-
- assert!(query.is_valid());
+ Query::expect_valid(input);
}
#[test]
@@ -318,11 +302,10 @@ fn invalid_mutual_recursion_with_plus_quantifier() {
A = (foo (B)+)
B = (bar (A))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
+ let res = Query::expect_invalid(input);
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: infinite recursion: cycle has no escape path
|
1 | A = (foo (B)+)
@@ -341,9 +324,7 @@ fn valid_non_recursive_reference() {
Leaf = (identifier)
Tree = (call (Leaf))
"#};
- let query = Query::try_from(input).unwrap();
-
- assert!(query.is_valid());
+ Query::expect_valid(input);
}
#[test]
@@ -352,18 +333,16 @@ fn valid_entry_point_using_recursive_def() {
E = [(x) (call (E))]
Q = (program (E))
"#};
- let query = Query::try_from(input).unwrap();
-
- assert!(query.is_valid());
+ Query::expect_valid(input);
}
#[test]
fn invalid_direct_left_recursion_in_alternation() {
- let query = Query::try_from("E = [(E) (x)]").unwrap();
+ let input = "E = [(E) (x)]";
- assert!(!query.is_valid());
+ let res = Query::expect_invalid(input);
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: infinite recursion: cycle consumes no input
|
1 | E = [(E) (x)]
@@ -375,11 +354,11 @@ fn invalid_direct_left_recursion_in_alternation() {
#[test]
fn invalid_direct_right_recursion_in_alternation() {
- let query = Query::try_from("E = [(x) (E)]").unwrap();
+ let input = "E = [(x) (E)]";
- assert!(!query.is_valid());
+ let res = Query::expect_invalid(input);
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: infinite recursion: cycle consumes no input
|
1 | E = [(x) (E)]
@@ -391,11 +370,11 @@ fn invalid_direct_right_recursion_in_alternation() {
#[test]
fn invalid_direct_left_recursion_in_tagged_alternation() {
- let query = Query::try_from("E = [Left: (E) Right: (x)]").unwrap();
+ let input = "E = [Left: (E) Right: (x)]";
- assert!(!query.is_valid());
+ let res = Query::expect_invalid(input);
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: infinite recursion: cycle consumes no input
|
1 | E = [Left: (E) Right: (x)]
@@ -410,11 +389,10 @@ fn invalid_unguarded_left_recursion_branch() {
let input = indoc! {r#"
A = [(A) 'escape']
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
+ let res = Query::expect_invalid(input);
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: infinite recursion: cycle consumes no input
|
1 | A = [(A) 'escape']
@@ -429,11 +407,10 @@ fn invalid_unguarded_left_recursion_with_wildcard_alt() {
let input = indoc! {r#"
A = [(A) _]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
+ let res = Query::expect_invalid(input);
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: infinite recursion: cycle consumes no input
|
1 | A = [(A) _]
@@ -448,11 +425,10 @@ fn invalid_unguarded_left_recursion_with_tree_alt() {
let input = indoc! {r#"
A = [(A) (leaf)]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
+ let res = Query::expect_invalid(input);
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: infinite recursion: cycle consumes no input
|
1 | A = [(A) (leaf)]
@@ -467,9 +443,7 @@ fn valid_recursion_guarded_by_anchor() {
let input = indoc! {r#"
A = (foo . [(A) (x)])
"#};
- let query = Query::try_from(input).unwrap();
-
- assert!(query.is_valid());
+ Query::expect_valid(input);
}
#[test]
@@ -477,11 +451,10 @@ fn invalid_mandatory_recursion_direct_child() {
let input = indoc! {r#"
A = (foo (A))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
+ let res = Query::expect_invalid(input);
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: infinite recursion: cycle has no escape path
|
1 | A = (foo (A))
@@ -496,9 +469,7 @@ fn valid_recursion_with_capture_base_case() {
let input = indoc! {r#"
A = [(x)@cap (foo (A))]
"#};
- let query = Query::try_from(input).unwrap();
-
- assert!(query.is_valid());
+ Query::expect_valid(input);
}
#[test]
@@ -506,9 +477,17 @@ fn invalid_mandatory_recursion_nested_plus() {
let input = indoc! {r#"
A = (foo (A)+)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
+ error: infinite recursion: cycle has no escape path
+ |
+ 1 | A = (foo (A)+)
+ | ^
+ | |
+ | A references itself
+ ");
}
#[test]
@@ -519,11 +498,10 @@ fn invalid_simple_unguarded_recursion() {
(A)
]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
+ let res = Query::expect_invalid(input);
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: infinite recursion: cycle consumes no input
|
3 | (A)
@@ -539,11 +517,10 @@ fn invalid_unguarded_mutual_recursion_chain() {
A = [(B) (x)]
B = (A)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
+ let res = Query::expect_invalid(input);
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: infinite recursion: cycle consumes no input
|
1 | A = [(B) (x)]
diff --git a/crates/plotnik-lib/src/query/expr_arity_tests.rs b/crates/plotnik-lib/src/query/expr_arity_tests.rs
index ce146b35..8f2ca208 100644
--- a/crates/plotnik-lib/src/query/expr_arity_tests.rs
+++ b/crates/plotnik-lib/src/query/expr_arity_tests.rs
@@ -3,9 +3,11 @@ use indoc::indoc;
#[test]
fn tree_is_one() {
- let query = Query::try_from("Q = (identifier)").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
+ let input = "Q = (identifier)";
+
+ let res = Query::expect_valid_arities(input);
+
+ insta::assert_snapshot!(res, @r"
Root¹
Def¹ Q
NamedNode¹ identifier
@@ -14,9 +16,11 @@ fn tree_is_one() {
#[test]
fn singleton_seq_is_one() {
- let query = Query::try_from("Q = {(identifier)}").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
+ let input = "Q = {(identifier)}";
+
+ let res = Query::expect_valid_arities(input);
+
+ insta::assert_snapshot!(res, @r"
Root¹
Def¹ Q
Seq¹
@@ -26,9 +30,11 @@ fn singleton_seq_is_one() {
#[test]
fn nested_singleton_seq_is_one() {
- let query = Query::try_from("Q = {{{(identifier)}}}").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
+ let input = "Q = {{{(identifier)}}}";
+
+ let res = Query::expect_valid_arities(input);
+
+ insta::assert_snapshot!(res, @r"
Root¹
Def¹ Q
Seq¹
@@ -40,9 +46,11 @@ fn nested_singleton_seq_is_one() {
#[test]
fn multi_seq_is_many() {
- let query = Query::try_from("Q = {(a) (b)}").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
+ let input = "Q = {(a) (b)}";
+
+ let res = Query::expect_valid_arities(input);
+
+ insta::assert_snapshot!(res, @r"
Root¹
Def⁺ Q
Seq⁺
@@ -53,9 +61,11 @@ fn multi_seq_is_many() {
#[test]
fn alt_is_one() {
- let query = Query::try_from("Q = [(a) (b)]").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
+ let input = "Q = [(a) (b)]";
+
+ let res = Query::expect_valid_arities(input);
+
+ insta::assert_snapshot!(res, @r"
Root¹
Def¹ Q
Alt¹
@@ -71,9 +81,10 @@ fn alt_with_seq_branches() {
let input = indoc! {r#"
Q = [{(a) (b)} (c)]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
+
+ let res = Query::expect_valid_arities(input);
+
+ insta::assert_snapshot!(res, @r"
Root¹
Def¹ Q
Alt¹
@@ -92,9 +103,10 @@ fn ref_to_tree_is_one() {
X = (identifier)
Q = (call (X))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
+
+ let res = Query::expect_valid_arities(input);
+
+ insta::assert_snapshot!(res, @r"
Root⁺
Def¹ X
NamedNode¹ identifier
@@ -110,9 +122,10 @@ fn ref_to_seq_is_many() {
X = {(a) (b)}
Q = (call (X))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
+
+ let res = Query::expect_valid_arities(input);
+
+ insta::assert_snapshot!(res, @r"
Root⁺
Def⁺ X
Seq⁺
@@ -126,9 +139,11 @@ fn ref_to_seq_is_many() {
#[test]
fn field_with_tree() {
- let query = Query::try_from("Q = (call name: (identifier))").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
+ let input = "Q = (call name: (identifier))";
+
+ let res = Query::expect_valid_arities(input);
+
+ insta::assert_snapshot!(res, @r"
Root¹
Def¹ Q
NamedNode¹ call
@@ -139,9 +154,11 @@ fn field_with_tree() {
#[test]
fn field_with_alt() {
- let query = Query::try_from("Q = (call name: [(identifier) (string)])").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
+ let input = "Q = (call name: [(identifier) (string)])";
+
+ let res = Query::expect_valid_arities(input);
+
+ insta::assert_snapshot!(res, @r"
Root¹
Def¹ Q
NamedNode¹ call
@@ -156,18 +173,11 @@ fn field_with_alt() {
#[test]
fn field_with_seq_error() {
- let query = Query::try_from("Q = (call name: {(a) (b)})").unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
- Root¹
- Def¹ Q
- NamedNode¹ call
- FieldExpr¹ name:
- Seq⁺
- NamedNode¹ a
- NamedNode¹ b
- ");
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let input = "Q = (call name: {(a) (b)})";
+
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: field `name` must match exactly one node, not a sequence
|
1 | Q = (call name: {(a) (b)})
@@ -181,20 +191,10 @@ fn field_with_ref_to_seq_error() {
X = {(a) (b)}
Q = (call name: (X))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
- Root⁺
- Def⁺ X
- Seq⁺
- NamedNode¹ a
- NamedNode¹ b
- Def¹ Q
- NamedNode¹ call
- FieldExpr¹ name:
- Ref⁺ X
- ");
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: field `name` must match exactly one node, not a sequence
|
2 | Q = (call name: (X))
@@ -204,9 +204,11 @@ fn field_with_ref_to_seq_error() {
#[test]
fn quantifier_preserves_inner_arity() {
- let query = Query::try_from("Q = (identifier)*").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
+ let input = "Q = (identifier)*";
+
+ let res = Query::expect_valid_arities(input);
+
+ insta::assert_snapshot!(res, @r"
Root¹
Def¹ Q
QuantifiedExpr¹ *
@@ -216,9 +218,11 @@ fn quantifier_preserves_inner_arity() {
#[test]
fn capture_preserves_inner_arity() {
- let query = Query::try_from("Q = (identifier) @name").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
+ let input = "Q = (identifier) @name";
+
+ let res = Query::expect_valid_arities(input);
+
+ insta::assert_snapshot!(res, @r"
Root¹
Def¹ Q
CapturedExpr¹ @name
@@ -228,9 +232,11 @@ fn capture_preserves_inner_arity() {
#[test]
fn capture_on_seq() {
- let query = Query::try_from("Q = {(a) (b)} @items").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
+ let input = "Q = {(a) (b)} @items";
+
+ let res = Query::expect_valid_arities(input);
+
+ insta::assert_snapshot!(res, @r"
Root¹
Def⁺ Q
CapturedExpr⁺ @items
@@ -248,9 +254,10 @@ fn complex_nested_arities() {
name: (identifier) @name
body: (block (Stmt)* @stmts))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
+
+ let res = Query::expect_valid_arities(input);
+
+ insta::assert_snapshot!(res, @r"
Root⁺
Def¹ Stmt
Alt¹
@@ -276,9 +283,10 @@ fn tagged_alt_arities() {
let input = indoc! {r#"
Q = [Ident: (identifier) Num: (number)]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
+
+ let res = Query::expect_valid_arities(input);
+
+ insta::assert_snapshot!(res, @r"
Root¹
Def¹ Q
Alt¹
@@ -291,9 +299,11 @@ fn tagged_alt_arities() {
#[test]
fn anchor_has_no_arity() {
- let query = Query::try_from("Q = (block . (statement))").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
+ let input = "Q = (block . (statement))";
+
+ let res = Query::expect_valid_arities(input);
+
+ insta::assert_snapshot!(res, @r"
Root¹
Def¹ Q
NamedNode¹ block
@@ -304,9 +314,11 @@ fn anchor_has_no_arity() {
#[test]
fn negated_field_has_no_arity() {
- let query = Query::try_from("Q = (function !async)").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
+ let input = "Q = (function !async)";
+
+ let res = Query::expect_valid_arities(input);
+
+ insta::assert_snapshot!(res, @r"
Root¹
Def¹ Q
NamedNode¹ function
@@ -316,9 +328,11 @@ fn negated_field_has_no_arity() {
#[test]
fn tree_with_wildcard_type() {
- let query = Query::try_from("Q = (_)").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
+ let input = "Q = (_)";
+
+ let res = Query::expect_valid_arities(input);
+
+ insta::assert_snapshot!(res, @r"
Root¹
Def¹ Q
NamedNode¹ (any)
@@ -327,9 +341,11 @@ fn tree_with_wildcard_type() {
#[test]
fn bare_wildcard_is_one() {
- let query = Query::try_from("Q = _").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
+ let input = "Q = _";
+
+ let res = Query::expect_valid_arities(input);
+
+ insta::assert_snapshot!(res, @r"
Root¹
Def¹ Q
AnonymousNode¹ (any)
@@ -338,9 +354,11 @@ fn bare_wildcard_is_one() {
#[test]
fn empty_seq_is_one() {
- let query = Query::try_from("Q = {}").unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
+ let input = "Q = {}";
+
+ let res = Query::expect_valid_arities(input);
+
+ insta::assert_snapshot!(res, @r"
Root¹
Def¹ Q
Seq¹
@@ -349,9 +367,13 @@ fn empty_seq_is_one() {
#[test]
fn literal_is_one() {
- let query = Query::try_from(r#"Q = "if""#).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r#"
+ let input = r#"
+ Q = "if"
+ "#;
+
+ let res = Query::expect_valid_arities(input);
+
+ insta::assert_snapshot!(res, @r#"
Root¹
Def¹ Q
AnonymousNode¹ "if"
@@ -360,42 +382,43 @@ fn literal_is_one() {
#[test]
fn invalid_error_node() {
- let query = Query::try_from("Q = (foo %)").unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_cst_with_arities(), @r#"
- Root¹
- Def¹
- Id "Q"
- Equals "="
- Tree¹
- ParenOpen "("
- Id "foo"
- Error⁻
- Garbage "%"
- ParenClose ")"
- "#);
+ let input = "Q = (foo %)";
+
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
+ error: unexpected token; not valid inside a node — try `(child)` or close with `)`
+ |
+ 1 | Q = (foo %)
+ | ^
+ ");
}
#[test]
fn invalid_undefined_ref() {
- let query = Query::try_from("Q = (Undefined)").unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
- Root¹
- Def⁻ Q
- Ref⁻ Undefined
+ let input = "Q = (Undefined)";
+
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
+ error: `Undefined` is not defined
+ |
+ 1 | Q = (Undefined)
+ | ^^^^^^^^^
");
}
#[test]
fn invalid_branch_without_body() {
- let query = Query::try_from("Q = [A:]").unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
- Root¹
- Def¹ Q
- Alt¹
- Branchˣ A:
+ let input = "Q = [A:]";
+
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
+ error: expected an expression; after `Label:`
+ |
+ 1 | Q = [A:]
+ | ^
");
}
@@ -405,29 +428,30 @@ fn invalid_ref_to_bodyless_def() {
X = %
Q = (X)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
- Root⁺
- Defˣ X
- Defˣ
- Def⁻ Q
- Ref⁻ X
+
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
+ error: expected an expression; after `=` in definition
+ |
+ 1 | X = %
+ | ^
+
+ error: `X` is not defined
+ |
+ 2 | Q = (X)
+ | ^
");
}
#[test]
fn invalid_capture_without_inner() {
// Error recovery: `extra` is invalid, but `@y` still creates a Capture node
- let query = Query::try_from("Q = (call extra @y)").unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
- Root¹
- Def¹ Q
- NamedNode¹ call
- CapturedExpr⁻ @y
- ");
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let input = "Q = (call extra @y)";
+
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: bare identifier is not a valid expression; wrap in parentheses: `(identifier)`
|
1 | Q = (call extra @y)
@@ -438,9 +462,11 @@ fn invalid_capture_without_inner() {
#[test]
fn invalid_capture_without_inner_standalone() {
// Standalone capture without preceding expression
- let query = Query::try_from("Q = @x").unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let input = "Q = @x";
+
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: expected an expression; after `=` in definition
|
1 | Q = @x
@@ -450,30 +476,31 @@ fn invalid_capture_without_inner_standalone() {
#[test]
fn invalid_multiple_captures_with_error() {
- let query = Query::try_from("Q = (call (Undefined) @x extra @y)").unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
- Root¹
- Def¹ Q
- NamedNode¹ call
- CapturedExpr⁻ @x
- Ref⁻ Undefined
- CapturedExpr⁻ @y
+ let input = "Q = (call (Undefined) @x extra @y)";
+
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
+ error: `Undefined` is not defined
+ |
+ 1 | Q = (call (Undefined) @x extra @y)
+ | ^^^^^^^^^
+
+ error: bare identifier is not a valid expression; wrap in parentheses: `(identifier)`
+ |
+ 1 | Q = (call (Undefined) @x extra @y)
+ | ^^^^^
");
}
#[test]
fn invalid_quantifier_without_inner() {
// Error recovery: `extra` is invalid, but `*` still creates a Quantifier node
- let query = Query::try_from("Q = (foo extra*)").unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_with_arities(), @r"
- Root¹
- Def¹ Q
- NamedNode¹ foo
- QuantifiedExpr⁻ *
- ");
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let input = "Q = (foo extra*)";
+
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: bare identifier is not a valid expression; wrap in parentheses: `(identifier)`
|
1 | Q = (foo extra*)
diff --git a/crates/plotnik-lib/src/query/link_tests.rs b/crates/plotnik-lib/src/query/link_tests.rs
index 4df387f5..1599dfb1 100644
--- a/crates/plotnik-lib/src/query/link_tests.rs
+++ b/crates/plotnik-lib/src/query/link_tests.rs
@@ -1,5 +1,9 @@
use crate::Query;
use indoc::indoc;
+use plotnik_langs::Lang;
+use std::sync::LazyLock;
+
+static LANG: LazyLock = LazyLock::new(|| plotnik_langs::javascript());
#[test]
fn valid_query_with_field() {
@@ -7,21 +11,7 @@ fn valid_query_with_field() {
Q = (function_declaration
name: (identifier) @name) @fn
"#};
-
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::javascript());
-
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
- Root
- Def Q
- CapturedExpr @fn
- NamedNode function_declaration
- CapturedExpr @name
- FieldExpr name:
- NamedNode identifier
- ");
+ Query::expect_valid_linking(input, &LANG);
}
#[test]
@@ -30,12 +20,9 @@ fn unknown_node_type_with_suggestion() {
Q = (function_declaraton) @fn
"#};
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::javascript());
+ let res = Query::expect_invalid_linking(input, &LANG);
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: `function_declaraton` is not a valid node type
|
1 | Q = (function_declaraton) @fn
@@ -51,12 +38,9 @@ fn unknown_node_type_no_suggestion() {
Q = (xyzzy_foobar_baz) @fn
"#};
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::javascript());
+ let res = Query::expect_invalid_linking(input, &LANG);
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: `xyzzy_foobar_baz` is not a valid node type
|
1 | Q = (xyzzy_foobar_baz) @fn
@@ -71,12 +55,9 @@ fn unknown_field_with_suggestion() {
nme: (identifier) @name) @fn
"#};
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::javascript());
+ let res = Query::expect_invalid_linking(input, &LANG);
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: `nme` is not a valid field
|
2 | nme: (identifier) @name) @fn
@@ -93,12 +74,9 @@ fn unknown_field_no_suggestion() {
xyzzy: (identifier) @name) @fn
"#};
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::javascript());
+ let res = Query::expect_invalid_linking(input, &LANG);
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: `xyzzy` is not a valid field
|
2 | xyzzy: (identifier) @name) @fn
@@ -113,12 +91,9 @@ fn field_not_on_node_type() {
condition: (identifier) @name) @fn
"#};
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::javascript());
+ let res = Query::expect_invalid_linking(input, &LANG);
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: field `condition` is not valid on this node type
|
1 | Q = (function_declaration
@@ -134,24 +109,22 @@ fn field_not_on_node_type() {
fn field_not_on_node_type_with_suggestion() {
let input = indoc! {r#"
Q = (function_declaration
- parameter: (formal_parameters) @params) @fn
+ parameter: (formal_parameters) @params
+ ) @fn
"#};
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::typescript());
+ let res = Query::expect_invalid_linking(input, &LANG);
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: field `parameter` is not valid on this node type
|
1 | Q = (function_declaration
| -------------------- on `function_declaration`
- 2 | parameter: (formal_parameters) @params) @fn
+ 2 | parameter: (formal_parameters) @params
| ^^^^^^^^^
|
help: did you mean `parameters`?
- help: valid fields for `function_declaration`: `body`, `name`, `parameters`, `return_type`, `type_parameters`
+ help: valid fields for `function_declaration`: `body`, `name`, `parameters`
");
}
@@ -161,12 +134,9 @@ fn negated_field_unknown() {
Q = (function_declaration !nme) @fn
"#};
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::javascript());
+ let res = Query::expect_invalid_linking(input, &LANG);
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: `nme` is not a valid field
|
1 | Q = (function_declaration !nme) @fn
@@ -182,12 +152,9 @@ fn negated_field_not_on_node_type() {
Q = (function_declaration !condition) @fn
"#};
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::javascript());
+ let res = Query::expect_invalid_linking(input, &LANG);
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: field `condition` is not valid on this node type
|
1 | Q = (function_declaration !condition) @fn
@@ -205,12 +172,9 @@ fn negated_field_not_on_node_type_with_suggestion() {
Q = (function_declaration !parameter) @fn
"#};
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::typescript());
+ let res = Query::expect_invalid_linking(input, &LANG);
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: field `parameter` is not valid on this node type
|
1 | Q = (function_declaration !parameter) @fn
@@ -219,7 +183,7 @@ fn negated_field_not_on_node_type_with_suggestion() {
| on `function_declaration`
|
help: did you mean `parameters`?
- help: valid fields for `function_declaration`: `body`, `name`, `parameters`, `return_type`, `type_parameters`
+ help: valid fields for `function_declaration`: `body`, `name`, `parameters`
");
}
@@ -229,18 +193,7 @@ fn negated_field_valid() {
Q = (function_declaration !name) @fn
"#};
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::javascript());
-
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
- Root
- Def Q
- CapturedExpr @fn
- NamedNode function_declaration
- NegatedField !name
- ");
+ Query::expect_valid_linking(input, &LANG);
}
#[test]
@@ -249,12 +202,9 @@ fn anonymous_node_unknown() {
Q = (function_declaration "xyzzy_fake_token") @fn
"#};
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::javascript());
+ let res = Query::expect_invalid_linking(input, &LANG);
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r#"
+ insta::assert_snapshot!(res, @r#"
error: `xyzzy_fake_token` is not a valid node type
|
1 | Q = (function_declaration "xyzzy_fake_token") @fn
@@ -263,26 +213,19 @@ fn anonymous_node_unknown() {
}
#[test]
-fn error_and_missing_nodes_skip_validation() {
+fn error_nodes_skip_validation() {
let input = indoc! {r#"
Q = (ERROR) @err
"#};
+ Query::expect_valid_linking(input, &LANG);
+}
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::javascript());
-
- assert!(query.is_valid());
-
- let input2 = indoc! {r#"
+#[test]
+fn missing_nodes_skip_validation() {
+ let input = indoc! {r#"
Q = (MISSING) @miss
"#};
-
- let query2 = Query::try_from(input2)
- .unwrap()
- .link(&plotnik_langs::javascript());
-
- assert!(query2.is_valid());
+ Query::expect_valid_linking(input, &LANG);
}
#[test]
@@ -292,12 +235,9 @@ fn multiple_errors_in_query() {
nme: (identifer) @name) @fn
"#};
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::javascript());
+ let res = Query::expect_invalid_linking(input, &LANG);
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: `function_declaraton` is not a valid node type
|
1 | Q = (function_declaraton
@@ -329,22 +269,7 @@ fn nested_field_validation() {
(return_statement) @ret) @body) @fn
"#};
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::javascript());
-
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
- Root
- Def Q
- CapturedExpr @fn
- NamedNode function_declaration
- CapturedExpr @body
- FieldExpr body:
- NamedNode statement_block
- CapturedExpr @ret
- NamedNode return_statement
- ");
+ Query::expect_valid_linking(input, &LANG);
}
#[test]
@@ -354,12 +279,9 @@ fn alternation_with_link_errors() {
(class_declaraton)] @decl
"#};
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::javascript());
+ let res = Query::expect_invalid_linking(input, &LANG);
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: `function_declaraton` is not a valid node type
|
1 | Q = [(function_declaraton)
@@ -383,20 +305,7 @@ fn quantified_expr_validation() {
(function_declaration)+ @fns) @block
"#};
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::javascript());
-
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
- Root
- Def Q
- CapturedExpr @block
- NamedNode statement_block
- CapturedExpr @fns
- QuantifiedExpr +
- NamedNode function_declaration
- ");
+ Query::expect_valid_linking(input, &LANG);
}
#[test]
@@ -405,11 +314,7 @@ fn wildcard_node_skips_validation() {
Q = (_) @any
"#};
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::javascript());
-
- assert!(query.is_valid());
+ Query::expect_valid_linking(input, &LANG);
}
#[test]
@@ -420,24 +325,7 @@ fn def_reference_with_link() {
Q = (program (Func)+)
"#};
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::javascript());
-
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_ast(), @r"
- Root
- Def Func
- CapturedExpr @fn
- NamedNode function_declaration
- CapturedExpr @name
- FieldExpr name:
- NamedNode identifier
- Def Q
- NamedNode program
- QuantifiedExpr +
- Ref Func
- ");
+ Query::expect_valid_linking(input, &LANG);
}
#[test]
@@ -447,12 +335,9 @@ fn field_on_node_without_fields() {
name: (identifier) @inner) @id
"#};
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::javascript());
+ let res = Query::expect_invalid_linking(input, &LANG);
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ insta::assert_snapshot!(res, @r"
error: field `name` is not valid on this node type
|
1 | Q = (identifier
@@ -471,11 +356,7 @@ fn valid_child_via_supertype() {
(function_declaration)) @block
"#};
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::javascript());
-
- assert!(query.is_valid());
+ Query::expect_valid_linking(input, &LANG);
}
#[test]
@@ -485,11 +366,7 @@ fn valid_child_via_nested_supertype() {
(function_declaration)) @prog
"#};
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::javascript());
-
- assert!(query.is_valid());
+ Query::expect_valid_linking(input, &LANG);
}
#[test]
@@ -498,11 +375,7 @@ fn deeply_nested_sequences_valid() {
Q = (statement_block {{{(function_declaration)}}}) @block
"#};
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::javascript());
-
- assert!(query.is_valid());
+ Query::expect_valid_linking(input, &LANG);
}
#[test]
@@ -511,11 +384,7 @@ fn deeply_nested_alternations_in_field_valid() {
Q = (function_declaration name: [[[(identifier)]]]) @fn
"#};
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::javascript());
-
- assert!(query.is_valid());
+ Query::expect_valid_linking(input, &LANG);
}
#[test]
@@ -525,31 +394,5 @@ fn ref_followed_valid_case() {
Q = (function_declaration name: (Foo))
"#};
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::javascript());
-
- assert!(query.is_valid());
-}
-
-#[test]
-fn ref_followed_recursive_valid() {
- let input = indoc! {r#"
- Foo = [(identifier) (Foo)]
- Q = (function_declaration name: (Foo))
- "#};
-
- let query = Query::try_from(input)
- .unwrap()
- .link(&plotnik_langs::javascript());
-
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
- error: infinite recursion: cycle consumes no input
- |
- 1 | Foo = [(identifier) (Foo)]
- | ^^^
- | |
- | references itself
- ");
+ Query::expect_valid_linking(input, &LANG);
}
diff --git a/crates/plotnik-lib/src/query/mod.rs b/crates/plotnik-lib/src/query/mod.rs
index ff0b2dc5..e67ce71b 100644
--- a/crates/plotnik-lib/src/query/mod.rs
+++ b/crates/plotnik-lib/src/query/mod.rs
@@ -23,8 +23,8 @@ mod expr_arity_tests;
#[cfg(all(test, feature = "plotnik-langs"))]
mod link_tests;
#[cfg(test)]
-mod mod_tests;
-#[cfg(test)]
mod printer_tests;
#[cfg(test)]
+mod query_tests;
+#[cfg(test)]
mod symbol_table_tests;
diff --git a/crates/plotnik-lib/src/query/mod_tests.rs b/crates/plotnik-lib/src/query/mod_tests.rs
deleted file mode 100644
index 06273236..00000000
--- a/crates/plotnik-lib/src/query/mod_tests.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-use super::*;
-
-#[test]
-fn valid_query() {
- let q = Query::try_from("Expr = (expression)").unwrap();
- assert!(q.is_valid());
-}
-
-#[test]
-fn parse_error() {
- let q = Query::try_from("(unclosed").unwrap();
- assert!(!q.is_valid());
- insta::assert_snapshot!(q.dump_diagnostics(), @r"
- error: missing closing `)`; expected `)`
- |
- 1 | (unclosed
- | -^^^^^^^^
- | |
- | tree started here
- ");
-}
-
-#[test]
-fn resolution_error() {
- let q = Query::try_from("(call (Undefined))").unwrap();
- assert!(!q.is_valid());
- insta::assert_snapshot!(q.dump_diagnostics(), @r"
- error: `Undefined` is not defined
- |
- 1 | (call (Undefined))
- | ^^^^^^^^^
- ");
-}
-
-#[test]
-fn combined_errors() {
- let q = Query::try_from("(call (Undefined) extra)").unwrap();
- assert!(!q.is_valid());
- insta::assert_snapshot!(q.dump_diagnostics(), @r"
- error: `Undefined` is not defined
- |
- 1 | (call (Undefined) extra)
- | ^^^^^^^^^
-
- error: bare identifier is not a valid expression; wrap in parentheses: `(identifier)`
- |
- 1 | (call (Undefined) extra)
- | ^^^^^
- ");
-}
diff --git a/crates/plotnik-lib/src/query/printer_tests.rs b/crates/plotnik-lib/src/query/printer_tests.rs
index 190d4ba3..88d23e57 100644
--- a/crates/plotnik-lib/src/query/printer_tests.rs
+++ b/crates/plotnik-lib/src/query/printer_tests.rs
@@ -3,52 +3,73 @@ use indoc::indoc;
#[test]
fn printer_with_spans() {
- let q = Query::try_from("(call)").unwrap();
- insta::assert_snapshot!(q.printer().with_spans(true).dump(), @r"
- Root [0..6]
- Def [0..6]
- NamedNode [0..6] call
+ let input = "Q = (call)";
+ let q = Query::expect(input);
+
+ let res = q.printer().with_spans(true).dump();
+
+ insta::assert_snapshot!(res, @r"
+ Root [0..10]
+ Def [0..10] Q
+ NamedNode [4..10] call
");
}
#[test]
fn printer_with_arities() {
- let q = Query::try_from("(call)").unwrap();
- insta::assert_snapshot!(q.printer().with_arities(true).dump(), @r"
+ let input = "Q = (call)";
+ let q = Query::expect(input);
+
+ let res = q.printer().with_arities(true).dump();
+
+ insta::assert_snapshot!(res, @r"
Root¹
- Def¹
+ Def¹ Q
NamedNode¹ call
");
}
#[test]
fn printer_cst_with_trivia() {
- let q = Query::try_from("(a) (b)").unwrap();
- insta::assert_snapshot!(q.printer().raw(true).with_trivia(true).dump(), @r#"
+ let input = "Q = {(a) (b)}";
+ let q = Query::expect(input);
+
+ let res = q.printer().raw(true).with_trivia(true).dump();
+
+ insta::assert_snapshot!(res, @r#"
Root
Def
- Tree
- ParenOpen "("
- Id "a"
- ParenClose ")"
- Whitespace " "
- Def
- Tree
- ParenOpen "("
- Id "b"
- ParenClose ")"
+ Id "Q"
+ Whitespace " "
+ Equals "="
+ Whitespace " "
+ Seq
+ BraceOpen "{"
+ Tree
+ ParenOpen "("
+ Id "a"
+ ParenClose ")"
+ Whitespace " "
+ Tree
+ ParenOpen "("
+ Id "b"
+ ParenClose ")"
+ BraceClose "}"
"#);
}
#[test]
fn printer_alt_branches() {
let input = indoc! {r#"
- [A: (a) B: (b)]
+ Q = [A: (a) B: (b)]
"#};
- let q = Query::try_from(input).unwrap();
- insta::assert_snapshot!(q.printer().dump(), @r"
+ let q = Query::expect(input);
+
+ let res = q.printer().dump();
+
+ insta::assert_snapshot!(res, @r"
Root
- Def
+ Def Q
Alt
Branch A:
NamedNode a
@@ -59,10 +80,14 @@ fn printer_alt_branches() {
#[test]
fn printer_capture_with_type() {
- let q = Query::try_from("(call)@x :: T").unwrap();
- insta::assert_snapshot!(q.printer().dump(), @r"
+ let input = "Q = (call) @x :: T";
+ let q = Query::expect(input);
+
+ let res = q.printer().dump();
+
+ insta::assert_snapshot!(res, @r"
Root
- Def
+ Def Q
CapturedExpr @x :: T
NamedNode call
");
@@ -70,27 +95,34 @@ fn printer_capture_with_type() {
#[test]
fn printer_quantifiers() {
- let q = Query::try_from("(a)* (b)+ (c)?").unwrap();
- insta::assert_snapshot!(q.printer().dump(), @r"
+ let input = "Q = { (a)* (b)+ (c)? }";
+ let q = Query::expect(input);
+
+ let res = q.printer().dump();
+
+ insta::assert_snapshot!(res, @r"
Root
- Def
- QuantifiedExpr *
- NamedNode a
- Def
- QuantifiedExpr +
- NamedNode b
- Def
- QuantifiedExpr ?
- NamedNode c
+ Def Q
+ Seq
+ QuantifiedExpr *
+ NamedNode a
+ QuantifiedExpr +
+ NamedNode b
+ QuantifiedExpr ?
+ NamedNode c
");
}
#[test]
fn printer_field() {
- let q = Query::try_from("(call name: (id))").unwrap();
- insta::assert_snapshot!(q.printer().dump(), @r"
+ let input = "Q = (call name: (id))";
+ let q = Query::expect(input);
+
+ let res = q.printer().dump();
+
+ insta::assert_snapshot!(res, @r"
Root
- Def
+ Def Q
NamedNode call
FieldExpr name:
NamedNode id
@@ -99,10 +131,14 @@ fn printer_field() {
#[test]
fn printer_negated_field() {
- let q = Query::try_from("(call !name)").unwrap();
- insta::assert_snapshot!(q.printer().dump(), @r"
+ let input = "Q = (call !name)";
+ let q = Query::expect(input);
+
+ let res = q.printer().dump();
+
+ insta::assert_snapshot!(res, @r"
Root
- Def
+ Def Q
NamedNode call
NegatedField !name
");
@@ -110,10 +146,14 @@ fn printer_negated_field() {
#[test]
fn printer_wildcard_and_anchor() {
- let q = Query::try_from("(call _ . (arg))").unwrap();
- insta::assert_snapshot!(q.printer().dump(), @r"
+ let input = "Q = (call _ . (arg))";
+ let q = Query::expect(input);
+
+ let res = q.printer().dump();
+
+ insta::assert_snapshot!(res, @r"
Root
- Def
+ Def Q
NamedNode call
AnonymousNode (any)
.
@@ -123,10 +163,14 @@ fn printer_wildcard_and_anchor() {
#[test]
fn printer_string_literal() {
- let q = Query::try_from(r#"(call "foo")"#).unwrap();
- insta::assert_snapshot!(q.printer().dump(), @r#"
+ let input = r#"Q = (call "foo")"#;
+ let q = Query::expect(input);
+
+ let res = q.printer().dump();
+
+ insta::assert_snapshot!(res, @r#"
Root
- Def
+ Def Q
NamedNode call
AnonymousNode "foo"
"#);
@@ -136,14 +180,17 @@ fn printer_string_literal() {
fn printer_ref() {
let input = indoc! {r#"
Expr = (call)
- (func (Expr))
+ Q = (func (Expr))
"#};
- let q = Query::try_from(input).unwrap();
- insta::assert_snapshot!(q.printer().dump(), @r"
+ let q = Query::expect(input);
+
+ let res = q.printer().dump();
+
+ insta::assert_snapshot!(res, @r"
Root
Def Expr
NamedNode call
- Def
+ Def Q
NamedNode func
Ref Expr
");
@@ -154,13 +201,16 @@ fn printer_symbols_with_arities() {
let input = indoc! {r#"
A = (a)
B = {(b) (c)}
- (entry (A) (B))
+ Q = (entry (A) (B))
"#};
- let q = Query::try_from(input).unwrap();
- insta::assert_snapshot!(q.printer().only_symbols(true).with_arities(true).dump(), @r"
+ let q = Query::expect(input);
+
+ let res = q.printer().only_symbols(true).with_arities(true).dump();
+
+ insta::assert_snapshot!(res, @r"
A¹
B⁺
- _
+ Q¹
A¹
B⁺
");
@@ -171,14 +221,17 @@ fn printer_symbols_with_refs() {
let input = indoc! {r#"
A = (a)
B = (b (A))
- (entry (B))
+ Q = (entry (B))
"#};
- let q = Query::try_from(input).unwrap();
- insta::assert_snapshot!(q.printer().only_symbols(true).dump(), @r"
+ let q = Query::expect(input);
+
+ let res = q.printer().only_symbols(true).dump();
+
+ insta::assert_snapshot!(res, @r"
A
B
A
- _
+ Q
B
A
");
@@ -189,17 +242,20 @@ fn printer_symbols_cycle() {
let input = indoc! {r#"
A = [(a) (B)]
B = [(b) (A)]
- (entry (A))
+ Q = (entry (A))
"#};
- let q = Query::try_from(input).unwrap();
- insta::assert_snapshot!(q.printer().only_symbols(true).dump(), @r"
+ let q = Query::expect(input);
+
+ let res = q.printer().only_symbols(true).dump();
+
+ insta::assert_snapshot!(res, @r"
A
B
A (cycle)
B
A
B (cycle)
- _
+ Q
A
B
A (cycle)
@@ -208,10 +264,13 @@ fn printer_symbols_cycle() {
#[test]
fn printer_symbols_undefined_ref() {
- let input = "(call (Undefined))";
- let q = Query::try_from(input).unwrap();
- insta::assert_snapshot!(q.printer().only_symbols(true).dump(), @r"
- _
+ let input = "Q = (call (Undefined))";
+ let q = Query::expect(input);
+
+ let res = q.printer().only_symbols(true).dump();
+
+ insta::assert_snapshot!(res, @r"
+ Q
Undefined?
");
}
@@ -219,8 +278,11 @@ fn printer_symbols_undefined_ref() {
#[test]
fn printer_symbols_broken_ref() {
let input = "A = (foo (Undefined))";
- let q = Query::try_from(input).unwrap();
- insta::assert_snapshot!(q.printer().only_symbols(true).dump(), @r"
+ let q = Query::expect(input);
+
+ let res = q.printer().only_symbols(true).dump();
+
+ insta::assert_snapshot!(res, @r"
A
Undefined?
");
@@ -230,61 +292,76 @@ fn printer_symbols_broken_ref() {
fn printer_spans_comprehensive() {
let input = indoc! {r#"
Foo = (call name: (id) !bar)
- [(a) (b)]
+ Q = [(a) (b)]
"#};
- let q = Query::try_from(input).unwrap();
- insta::assert_snapshot!(q.printer().with_spans(true).dump(), @r"
- Root [0..39]
+ let q = Query::expect(input);
+
+ let res = q.printer().with_spans(true).dump();
+
+ insta::assert_snapshot!(res, @r"
+ Root [0..43]
Def [0..28] Foo
NamedNode [6..28] call
FieldExpr [12..22] name:
NamedNode [18..22] id
NegatedField [23..27] !bar
- Def [29..38]
- Alt [29..38]
- Branch [30..33]
- NamedNode [30..33] a
+ Def [29..42] Q
+ Alt [33..42]
Branch [34..37]
- NamedNode [34..37] b
+ NamedNode [34..37] a
+ Branch [38..41]
+ NamedNode [38..41] b
");
}
#[test]
fn printer_spans_seq() {
- let q = Query::try_from("{(a) (b)}").unwrap();
- insta::assert_snapshot!(q.printer().with_spans(true).dump(), @r"
- Root [0..9]
- Def [0..9]
- Seq [0..9]
- NamedNode [1..4] a
- NamedNode [5..8] b
+ let input = "Q = {(a) (b)}";
+ let q = Query::expect(input);
+
+ let res = q.printer().with_spans(true).dump();
+
+ insta::assert_snapshot!(res, @r"
+ Root [0..13]
+ Def [0..13] Q
+ Seq [4..13]
+ NamedNode [5..8] a
+ NamedNode [9..12] b
");
}
#[test]
fn printer_spans_quantifiers() {
- let q = Query::try_from("(a)* (b)+").unwrap();
- insta::assert_snapshot!(q.printer().with_spans(true).dump(), @r"
- Root [0..9]
- Def [0..4]
- QuantifiedExpr [0..4] *
- NamedNode [0..3] a
- Def [5..9]
- QuantifiedExpr [5..9] +
- NamedNode [5..8] b
+ let input = "Q = { (a)* (b)+ }";
+ let q = Query::expect(input);
+
+ let res = q.printer().with_spans(true).dump();
+
+ insta::assert_snapshot!(res, @r"
+ Root [0..17]
+ Def [0..17] Q
+ Seq [4..17]
+ QuantifiedExpr [6..10] *
+ NamedNode [6..9] a
+ QuantifiedExpr [11..15] +
+ NamedNode [11..14] b
");
}
#[test]
fn printer_spans_alt_branches() {
- let q = Query::try_from("[A: (a) B: (b)]").unwrap();
- insta::assert_snapshot!(q.printer().with_spans(true).dump(), @r"
- Root [0..15]
- Def [0..15]
- Alt [0..15]
- Branch [1..7] A:
- NamedNode [4..7] a
- Branch [8..14] B:
- NamedNode [11..14] b
+ let input = "Q = [A: (a) B: (b)]";
+ let q = Query::expect(input);
+
+ let res = q.printer().with_spans(true).dump();
+
+ insta::assert_snapshot!(res, @r"
+ Root [0..19]
+ Def [0..19] Q
+ Alt [4..19]
+ Branch [5..11] A:
+ NamedNode [8..11] a
+ Branch [12..18] B:
+ NamedNode [15..18] b
");
}
diff --git a/crates/plotnik-lib/src/query/query.rs b/crates/plotnik-lib/src/query/query.rs
index f199238d..66b1917c 100644
--- a/crates/plotnik-lib/src/query/query.rs
+++ b/crates/plotnik-lib/src/query/query.rs
@@ -88,7 +88,7 @@ impl<'q> QueryParsed<'q> {
}
impl<'q> QueryParsed<'q> {
- pub fn analyze(mut self) -> crate::Result> {
+ pub fn analyze(mut self) -> QueryAnalyzed<'q> {
let symbol_table = resolve_names(&self.ast, self.src, &mut self.diag);
let dependency_analysis = dependencies::analyze_dependencies(&symbol_table);
@@ -101,12 +101,12 @@ impl<'q> QueryParsed<'q> {
let arity_table = infer_arities(&self.ast, &symbol_table, &mut self.diag);
- Ok(QueryAnalyzed {
+ QueryAnalyzed {
query_parsed: self,
symbol_table,
dependency_analysis,
arity_table,
- })
+ }
}
pub fn source(&self) -> &'q str {
@@ -184,7 +184,7 @@ impl<'q> TryFrom<&'q str> for QueryAnalyzed<'q> {
type Error = crate::Error;
fn try_from(src: &'q str) -> crate::Result {
- QueryBuilder::new(src).parse()?.analyze()
+ Ok(QueryBuilder::new(src).parse()?.analyze())
}
}
diff --git a/crates/plotnik-lib/src/query/query_tests.rs b/crates/plotnik-lib/src/query/query_tests.rs
new file mode 100644
index 00000000..364be15c
--- /dev/null
+++ b/crates/plotnik-lib/src/query/query_tests.rs
@@ -0,0 +1,137 @@
+use plotnik_langs::Lang;
+
+use crate::query::query::{LinkedQuery, QueryAnalyzed, QueryBuilder};
+
+impl<'q> QueryAnalyzed<'q> {
+ #[track_caller]
+ pub fn expect(src: &'q str) -> Self {
+ QueryBuilder::new(src).parse().unwrap().analyze()
+ }
+
+ #[track_caller]
+ pub fn expect_valid(src: &'q str) -> Self {
+ let query = QueryBuilder::new(src).parse().unwrap().analyze();
+ if !query.is_valid() {
+ panic!(
+ "Expected valid query, got error:\n{}",
+ query.dump_diagnostics()
+ );
+ }
+
+ query
+ }
+
+ #[track_caller]
+ pub fn expect_valid_cst(src: &'q str) -> String {
+ let query = QueryBuilder::new(src).parse().unwrap().analyze();
+ if !query.is_valid() {
+ panic!(
+ "Expected valid query, got error:\n{}",
+ query.dump_diagnostics()
+ );
+ }
+
+ query.dump_cst()
+ }
+
+ #[track_caller]
+ pub fn expect_valid_cst_full(src: &'q str) -> String {
+ let query = QueryBuilder::new(src).parse().unwrap().analyze();
+ if !query.is_valid() {
+ panic!(
+ "Expected valid query, got error:\n{}",
+ query.dump_diagnostics()
+ );
+ }
+
+ query.dump_cst_full()
+ }
+
+ #[track_caller]
+ pub fn expect_valid_ast(src: &'q str) -> String {
+ let query = QueryBuilder::new(src).parse().unwrap().analyze();
+ if !query.is_valid() {
+ panic!(
+ "Expected valid query, got error:\n{}",
+ query.dump_diagnostics()
+ );
+ }
+
+ query.dump_ast()
+ }
+
+ #[track_caller]
+ pub fn expect_valid_arities(src: &'q str) -> String {
+ let query = QueryBuilder::new(src).parse().unwrap().analyze();
+ if !query.is_valid() {
+ panic!(
+ "Expected valid query, got error:\n{}",
+ query.dump_diagnostics()
+ );
+ }
+
+ query.dump_with_arities()
+ }
+
+ #[track_caller]
+ pub fn expect_valid_symbols(src: &'q str) -> String {
+ let query = QueryBuilder::new(src).parse().unwrap().analyze();
+ if !query.is_valid() {
+ panic!(
+ "Expected valid query, got error:\n{}",
+ query.dump_diagnostics()
+ );
+ }
+
+ query.dump_symbols()
+ }
+
+ #[track_caller]
+ pub fn expect_valid_linking(src: &'q str, lang: &Lang) -> LinkedQuery<'q> {
+ let query = QueryBuilder::new(src).parse().unwrap().analyze();
+ if !query.is_valid() {
+ panic!(
+ "Expected valid query, got error:\n{}",
+ query.dump_diagnostics()
+ );
+ }
+
+ let query = query.link(lang);
+ if !query.is_valid() {
+ panic!(
+ "Expected valid linking, got error:\n{}",
+ query.dump_diagnostics()
+ );
+ }
+
+ query
+ }
+
+ #[track_caller]
+ pub fn expect_invalid_linking(src: &'q str, lang: &Lang) -> String {
+ let query = QueryBuilder::new(src).parse().unwrap().analyze();
+ if !query.is_valid() {
+ panic!(
+ "Expected valid query, got error:\n{}",
+ query.dump_diagnostics()
+ );
+ }
+
+ let query = query.link(lang);
+ if query.is_valid() {
+ panic!("Expected failed linking, got valid",);
+ }
+
+ query.dump_diagnostics()
+ }
+
+ #[track_caller]
+ pub fn expect_invalid(src: &'q str) -> String {
+ let query = QueryBuilder::new(src).parse().unwrap().analyze();
+ if query.is_valid() {
+ panic!("Expected invalid query, got valid:\n{}", query.dump_cst());
+ }
+
+ query.dump_diagnostics()
+ }
+}
diff --git a/crates/plotnik-lib/src/query/symbol_table_tests.rs b/crates/plotnik-lib/src/query/symbol_table_tests.rs
index f01394a6..f842358c 100644
--- a/crates/plotnik-lib/src/query/symbol_table_tests.rs
+++ b/crates/plotnik-lib/src/query/symbol_table_tests.rs
@@ -4,9 +4,9 @@ use indoc::indoc;
#[test]
fn single_definition() {
let input = "Expr = (expression)";
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_symbols(), @"Expr");
+ let res = Query::expect_valid_symbols(input);
+
+ insta::assert_snapshot!(res, @"Expr");
}
#[test]
@@ -17,9 +17,9 @@ fn multiple_definitions() {
Decl = (declaration)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_symbols(), @r"
+ let res = Query::expect_valid_symbols(input);
+
+ insta::assert_snapshot!(res, @r"
Expr
Stmt
Decl
@@ -33,9 +33,9 @@ fn valid_reference() {
Call = (call_expression function: (Expr))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_symbols(), @r"
+ let res = Query::expect_valid_symbols(input);
+
+ insta::assert_snapshot!(res, @r"
Expr
Call
Expr
@@ -46,9 +46,9 @@ fn valid_reference() {
fn undefined_reference() {
let input = "Call = (call_expression function: (Undefined))";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: `Undefined` is not defined
|
1 | Call = (call_expression function: (Undefined))
@@ -60,9 +60,9 @@ fn undefined_reference() {
fn self_reference() {
let input = "Expr = [(identifier) (call (Expr))]";
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_symbols(), @r"
+ let res = Query::expect_valid_symbols(input);
+
+ insta::assert_snapshot!(res, @r"
Expr
Expr (cycle)
");
@@ -75,9 +75,9 @@ fn mutual_recursion() {
B = (bar (A))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: infinite recursion: cycle has no escape path
|
1 | A = (foo (B))
@@ -97,9 +97,9 @@ fn duplicate_definition() {
Expr = (other)
"#};
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: `Expr` is already defined
|
2 | Expr = (other)
@@ -114,9 +114,9 @@ fn reference_in_alternation() {
Value = [(Expr) (literal)]
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_symbols(), @r"
+ let res = Query::expect_valid_symbols(input);
+
+ insta::assert_snapshot!(res, @r"
Expr
Value
Expr
@@ -130,9 +130,9 @@ fn reference_in_sequence() {
Pair = {(Expr) (Expr)}
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_symbols(), @r"
+ let res = Query::expect_valid_symbols(input);
+
+ insta::assert_snapshot!(res, @r"
Expr
Pair
Expr
@@ -146,9 +146,9 @@ fn reference_in_quantifier() {
List = (Expr)*
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_symbols(), @r"
+ let res = Query::expect_valid_symbols(input);
+
+ insta::assert_snapshot!(res, @r"
Expr
List
Expr
@@ -162,9 +162,9 @@ fn reference_in_capture() {
Named = (Expr) @e
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_symbols(), @r"
+ let res = Query::expect_valid_symbols(input);
+
+ insta::assert_snapshot!(res, @r"
Expr
Named
Expr
@@ -178,9 +178,9 @@ fn entry_point_reference() {
Q = (call function: (Expr))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_symbols(), @r"
+ let res = Query::expect_valid_symbols(input);
+
+ insta::assert_snapshot!(res, @r"
Expr
Q
Expr
@@ -191,9 +191,9 @@ fn entry_point_reference() {
fn entry_point_undefined_reference() {
let input = "Q = (call function: (Unknown))";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: `Unknown` is not defined
|
1 | Q = (call function: (Unknown))
@@ -204,9 +204,9 @@ fn entry_point_undefined_reference() {
#[test]
fn no_definitions() {
let input = "Q = (identifier)";
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_symbols(), @"Q");
+ let res = Query::expect_valid_symbols(input);
+
+ insta::assert_snapshot!(res, @"Q");
}
#[test]
@@ -218,9 +218,9 @@ fn nested_references() {
D = (d (C) (A))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_symbols(), @r"
+ let res = Query::expect_valid_symbols(input);
+
+ insta::assert_snapshot!(res, @r"
A
B
A
@@ -239,9 +239,9 @@ fn nested_references() {
fn multiple_undefined() {
let input = "Q = (foo (X) (Y) (Z))";
- let query = Query::try_from(input).unwrap();
- assert!(!query.is_valid());
- insta::assert_snapshot!(query.dump_diagnostics(), @r"
+ let res = Query::expect_invalid(input);
+
+ insta::assert_snapshot!(res, @r"
error: `X` is not defined
|
1 | Q = (foo (X) (Y) (Z))
@@ -266,9 +266,9 @@ fn reference_inside_tree_child() {
B = (b (A))
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_symbols(), @r"
+ let res = Query::expect_valid_symbols(input);
+
+ insta::assert_snapshot!(res, @r"
A
B
A
@@ -282,9 +282,9 @@ fn reference_inside_capture() {
B = (A)@x
"#};
- let query = Query::try_from(input).unwrap();
- assert!(query.is_valid());
- insta::assert_snapshot!(query.dump_symbols(), @r"
+ let res = Query::expect_valid_symbols(input);
+
+ insta::assert_snapshot!(res, @r"
A
B
A