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