diff --git a/cli/src/tests/query_test.rs b/cli/src/tests/query_test.rs index 4293c568..d4ebd884 100644 --- a/cli/src/tests/query_test.rs +++ b/cli/src/tests/query_test.rs @@ -2,8 +2,8 @@ use super::helpers::allocations; use super::helpers::fixtures::get_language; use std::fmt::Write; use tree_sitter::{ - Node, Parser, Query, QueryCapture, QueryCursor, QueryError, QueryMatch, QueryPredicate, - QueryPredicateArg, QueryProperty, + Language, Node, Parser, Query, QueryCapture, QueryCursor, QueryError, QueryMatch, + QueryPredicate, QueryPredicateArg, QueryProperty, }; #[test] @@ -163,19 +163,13 @@ fn test_query_matches_with_simple_pattern() { ) .unwrap(); - let source = "function one() { two(); function three() {} }"; - let mut parser = Parser::new(); - parser.set_language(language).unwrap(); - let tree = parser.parse(source, None).unwrap(); - - let mut cursor = QueryCursor::new(); - let matches = cursor.matches(&query, tree.root_node(), to_callback(source)); - - assert_eq!( - collect_matches(matches, &query, source), + assert_query_matches( + language, + &query, + "function one() { two(); function three() {} }", &[ (0, vec![("fn-name", "one")]), - (0, vec![("fn-name", "three")]) + (0, vec![("fn-name", "three")]), ], ); }); @@ -195,7 +189,10 @@ fn test_query_matches_with_multiple_on_same_root() { ) .unwrap(); - let source = " + assert_query_matches( + language, + &query, + " class Person { // the constructor constructor(name) { this.name = name; } @@ -203,30 +200,21 @@ fn test_query_matches_with_multiple_on_same_root() { // the getter getFullName() { return this.name; } } - "; - - let mut parser = Parser::new(); - parser.set_language(language).unwrap(); - let tree = parser.parse(source, None).unwrap(); - let mut cursor = QueryCursor::new(); - let matches = cursor.matches(&query, tree.root_node(), to_callback(source)); - - assert_eq!( - collect_matches(matches, &query, source), + ", &[ ( 0, vec![ ("the-class-name", "Person"), - ("the-method-name", "constructor") - ] + ("the-method-name", "constructor"), + ], ), ( 0, vec![ ("the-class-name", "Person"), - ("the-method-name", "getFullName") - ] + ("the-method-name", "getFullName"), + ], ), ], ); @@ -246,20 +234,14 @@ fn test_query_matches_with_multiple_patterns_different_roots() { ) .unwrap(); - let source = " + assert_query_matches( + language, + &query, + " function f1() { f2(f3()); } - "; - - let mut parser = Parser::new(); - parser.set_language(language).unwrap(); - let tree = parser.parse(source, None).unwrap(); - let mut cursor = QueryCursor::new(); - let matches = cursor.matches(&query, tree.root_node(), to_callback(source)); - - assert_eq!( - collect_matches(matches, &query, source), + ", &[ (0, vec![("fn-def", "f1")]), (1, vec![("fn-ref", "f2")]), @@ -287,21 +269,15 @@ fn test_query_matches_with_multiple_patterns_same_root() { ) .unwrap(); - let source = " + assert_query_matches( + language, + &query, + " a = { b: () => { return c; }, d: function() { return d; } }; - "; - - let mut parser = Parser::new(); - parser.set_language(language).unwrap(); - let tree = parser.parse(source, None).unwrap(); - let mut cursor = QueryCursor::new(); - let matches = cursor.matches(&query, tree.root_node(), to_callback(source)); - - assert_eq!( - collect_matches(matches, &query, source), + ", &[ (1, vec![("method-def", "b")]), (0, vec![("method-def", "d")]), @@ -325,20 +301,14 @@ fn test_query_matches_with_nesting_and_no_fields() { ) .unwrap(); - let source = " + assert_query_matches( + language, + &query, + " [[a]]; [[c, d], [e, f, g, h]]; [[h], [i]]; - "; - - let mut parser = Parser::new(); - parser.set_language(language).unwrap(); - let tree = parser.parse(source, None).unwrap(); - let mut cursor = QueryCursor::new(); - let matches = cursor.matches(&query, tree.root_node(), to_callback(source)); - - assert_eq!( - collect_matches(matches, &query, source), + ", &[ (0, vec![("x1", "c"), ("x2", "d")]), (0, vec![("x1", "e"), ("x2", "f")]), @@ -358,17 +328,11 @@ fn test_query_matches_with_many() { let language = get_language("javascript"); let query = Query::new(language, "(array (identifier) @element)").unwrap(); - let source = "[hello];\n".repeat(50); - - let mut parser = Parser::new(); - parser.set_language(language).unwrap(); - let tree = parser.parse(&source, None).unwrap(); - let mut cursor = QueryCursor::new(); - let matches = cursor.matches(&query, tree.root_node(), to_callback(&source)); - - assert_eq!( - collect_matches(matches, &query, source.as_str()), - vec![(0, vec![("element", "hello")]); 50], + assert_query_matches( + language, + &query, + &"[hello];\n".repeat(50), + &vec![(0, vec![("element", "hello")]); 50], ); }); } @@ -385,20 +349,11 @@ fn test_query_matches_capturing_error_nodes() { ) .unwrap(); - let source = "function a(b,, c, d :e:) {}"; - - let mut parser = Parser::new(); - parser.set_language(language).unwrap(); - let tree = parser.parse(source, None).unwrap(); - let mut cursor = QueryCursor::new(); - let matches = cursor.matches(&query, tree.root_node(), to_callback(source)); - - assert_eq!( - collect_matches(matches, &query, source), - &[( - 0, - vec![("the-error", ":e:"), ("the-error-identifier", "e"),] - ),] + assert_query_matches( + language, + &query, + "function a(b,, c, d :e:) {}", + &[(0, vec![("the-error", ":e:"), ("the-error-identifier", "e")])], ); }); } @@ -439,10 +394,6 @@ fn test_query_matches_with_named_wildcard() { fn test_query_matches_with_wildcard_at_the_root() { allocations::record(|| { let language = get_language("javascript"); - let mut cursor = QueryCursor::new(); - let mut parser = Parser::new(); - parser.set_language(language).unwrap(); - let query = Query::new( language, " @@ -455,13 +406,11 @@ fn test_query_matches_with_wildcard_at_the_root() { ) .unwrap(); - let source = "/* one */ var x; /* two */ function y() {} /* three */ class Z {}"; - - let tree = parser.parse(source, None).unwrap(); - let matches = cursor.matches(&query, tree.root_node(), to_callback(source)); - assert_eq!( - collect_matches(matches, &query, source), - &[(0, vec![("doc", "/* two */"), ("name", "y")]),] + assert_query_matches( + language, + &query, + "/* one */ var x; /* two */ function y() {} /* three */ class Z {}", + &[(0, vec![("doc", "/* two */"), ("name", "y")])], ); let query = Query::new( @@ -475,17 +424,15 @@ fn test_query_matches_with_wildcard_at_the_root() { ) .unwrap(); - let source = "['hi', x(true), {y: false}]"; - - let tree = parser.parse(source, None).unwrap(); - let matches = cursor.matches(&query, tree.root_node(), to_callback(source)); - assert_eq!( - collect_matches(matches, &query, source), + assert_query_matches( + language, + &query, + "['hi', x(true), {y: false}]", &[ (0, vec![("a", "'hi'")]), (2, vec![("c", "true")]), (3, vec![("d", "false")]), - ] + ], ); }); } @@ -519,16 +466,10 @@ fn test_query_matches_with_immediate_siblings() { ) .unwrap(); - let source = "import a.b.c.d; return [w, [1, y], z]"; - - let mut parser = Parser::new(); - parser.set_language(language).unwrap(); - let tree = parser.parse(source, None).unwrap(); - let mut cursor = QueryCursor::new(); - let matches = cursor.matches(&query, tree.root_node(), to_callback(source)); - - assert_eq!( - collect_matches(matches, &query, source), + assert_query_matches( + language, + &query, + "import a.b.c.d; return [w, [1, y], z]", &[ (0, vec![("parent", "a"), ("child", "b")]), (0, vec![("parent", "b"), ("child", "c")]), @@ -536,7 +477,7 @@ fn test_query_matches_with_immediate_siblings() { (0, vec![("parent", "c"), ("child", "d")]), (2, vec![("first-element", "w")]), (2, vec![("first-element", "1")]), - ] + ], ); }); } @@ -564,7 +505,10 @@ fn test_query_matches_with_repeated_leaf_nodes() { ) .unwrap(); - let source = " + assert_query_matches( + language, + &query, + " // one // two a(); @@ -582,16 +526,7 @@ fn test_query_matches_with_repeated_leaf_nodes() { // eight function d() {} } - "; - - let mut parser = Parser::new(); - parser.set_language(language).unwrap(); - let tree = parser.parse(source, None).unwrap(); - let mut cursor = QueryCursor::new(); - let matches = cursor.matches(&query, tree.root_node(), to_callback(source)); - - assert_eq!( - collect_matches(matches, &query, source), + ", &[ ( 0, @@ -599,11 +534,31 @@ fn test_query_matches_with_repeated_leaf_nodes() { ("doc", "// four"), ("doc", "// five"), ("doc", "// six"), - ("name", "B") - ] + ("name", "B"), + ], ), (1, vec![("doc", "// eight"), ("name", "d")]), - ] + ], + ); + }); +} + +#[test] +fn test_query_matches_with_optional_nodes_inside_of_repetitions() { + allocations::record(|| { + let language = get_language("javascript"); + let query = Query::new(language, r#"(array (","? (number) @num)+)"#).unwrap(); + + assert_query_matches( + language, + &query, + r#" + var a = [1, 2, 3, 4] + "#, + &[( + 0, + vec![("num", "1"), ("num", "2"), ("num", "3"), ("num", "4")], + )], ); }); } @@ -625,43 +580,37 @@ fn test_query_matches_with_leading_optional_repeated_leaf_nodes() { ) .unwrap(); - let source = " - function a() { - // one - var b; + assert_query_matches( + language, + &query, + " + function a() { + // one + var b; - function c() {} + function c() {} - // two - // three - var d; + // two + // three + var d; - // four - // five - function e() { + // four + // five + function e() { + } } - } - // six - "; - - let mut parser = Parser::new(); - parser.set_language(language).unwrap(); - let tree = parser.parse(source, None).unwrap(); - let mut cursor = QueryCursor::new(); - let matches = cursor.matches(&query, tree.root_node(), to_callback(source)); - - assert_eq!( - collect_matches(matches, &query, source), + // six + ", &[ (0, vec![("name", "a")]), (0, vec![("name", "c")]), ( 0, - vec![("doc", "// four"), ("doc", "// five"), ("name", "e")] + vec![("doc", "// four"), ("doc", "// five"), ("name", "e")], ), - ] + ], ); }); } @@ -682,37 +631,21 @@ fn test_query_matches_with_optional_nodes() { ) .unwrap(); - let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + assert_query_matches(language, &query, "class A {}", &[(0, vec![("class", "A")])]); - let source = " - class A {} - "; - let tree = parser.parse(source, None).unwrap(); - let mut cursor = QueryCursor::new(); - let matches = cursor.matches(&query, tree.root_node(), to_callback(source)); - - assert_eq!( - collect_matches(matches, &query, source), - &[(0, vec![("class", "A")]),] - ); - - let source = " + assert_query_matches( + language, + &query, + " class A {} class B extends C {} class D extends (E.F) {} - "; - let tree = parser.parse(source, None).unwrap(); - let mut cursor = QueryCursor::new(); - let matches = cursor.matches(&query, tree.root_node(), to_callback(source)); - - assert_eq!( - collect_matches(matches, &query, source), + ", &[ (0, vec![("class", "A")]), (0, vec![("class", "B"), ("superclass", "C")]), (0, vec![("class", "D")]), - ] + ], ); }); } @@ -721,10 +654,6 @@ fn test_query_matches_with_optional_nodes() { fn test_query_matches_with_repeated_internal_nodes() { allocations::record(|| { let language = get_language("javascript"); - let mut parser = Parser::new(); - parser.set_language(language).unwrap(); - let mut cursor = QueryCursor::new(); - let query = Query::new( language, " @@ -735,18 +664,18 @@ fn test_query_matches_with_repeated_internal_nodes() { ", ) .unwrap(); - let source = " + + assert_query_matches( + language, + &query, + " class A { @c @d e() {} } - "; - let tree = parser.parse(source, None).unwrap(); - let matches = cursor.matches(&query, tree.root_node(), to_callback(source)); - assert_eq!( - collect_matches(matches, &query, source), - &[(0, vec![("deco", "c"), ("deco", "d"), ("name", "e")]),] + ", + &[(0, vec![("deco", "c"), ("deco", "d"), ("name", "e")])], ); }) } @@ -760,20 +689,16 @@ fn test_query_matches_in_language_with_simple_aliases() { // tag names, script tag names, and style tag names. All of // these tokens are aliased to `tag_name`. let query = Query::new(language, "(tag_name) @tag").unwrap(); - let source = " + + assert_query_matches( + language, + &query, + "