@@ -25,6 +25,35 @@ struct Position {
2525 column : u32 ,
2626}
2727
28+ /// Topiary often needs both the tree-sitter `Query` and the original content
29+ /// beloging to the file from which the query was parsed. This struct is a simple
30+ /// convenience wrapper that combines the `Query` with its original string.
31+ pub struct TopiaryQuery {
32+ pub query : Query ,
33+ pub query_content : String ,
34+ }
35+
36+ impl TopiaryQuery {
37+ /// Creates a new `TopiaryQuery` from a tree-sitter language/grammar and the
38+ /// contents of the query file.
39+ ///
40+ /// # Errors
41+ ///
42+ /// This function will return an error if tree-sitter failed to parse the query file.
43+ pub fn new (
44+ grammar : & tree_sitter_facade:: Language ,
45+ query_content : & str ,
46+ ) -> FormatterResult < TopiaryQuery > {
47+ let query = Query :: new ( grammar, query_content)
48+ . map_err ( |e| FormatterError :: Query ( "Error parsing query file" . into ( ) , Some ( e) ) ) ?;
49+
50+ Ok ( TopiaryQuery {
51+ query,
52+ query_content : query_content. to_owned ( ) ,
53+ } )
54+ }
55+ }
56+
2857impl From < Point > for Position {
2958 fn from ( point : Point ) -> Self {
3059 Self {
@@ -92,23 +121,21 @@ struct LocalQueryMatch<'a> {
92121/// - A unknown capture name was encountered in the query.
93122pub fn apply_query (
94123 input_content : & str ,
95- query_content : & str ,
124+ query : & TopiaryQuery ,
96125 grammar : & tree_sitter_facade:: Language ,
97126 tolerate_parsing_errors : bool ,
98127 should_check_input_exhaustivity : bool ,
99128) -> FormatterResult < AtomCollection > {
100129 let ( tree, grammar) = parse ( input_content, grammar, tolerate_parsing_errors) ?;
101130 let root = tree. root_node ( ) ;
102131 let source = input_content. as_bytes ( ) ;
103- let query = Query :: new ( grammar, query_content)
104- . map_err ( |e| FormatterError :: Query ( "Error parsing query file" . into ( ) , Some ( e) ) ) ?;
105132
106133 // Match queries
107134 let mut cursor = QueryCursor :: new ( ) ;
108135 let mut matches: Vec < LocalQueryMatch > = Vec :: new ( ) ;
109- let capture_names = query. capture_names ( ) ;
136+ let capture_names = query. query . capture_names ( ) ;
110137
111- for query_match in query. matches ( & root, source, & mut cursor) {
138+ for query_match in query. query . matches ( & root, source, & mut cursor) {
112139 let local_captures: Vec < QueryCapture > = query_match. captures ( ) . collect ( ) ;
113140
114141 matches. push ( LocalQueryMatch {
@@ -119,14 +146,7 @@ pub fn apply_query(
119146
120147 if should_check_input_exhaustivity {
121148 let ref_match_count = matches. len ( ) ;
122- check_input_exhaustivity (
123- ref_match_count,
124- & query,
125- query_content,
126- grammar,
127- & root,
128- source,
129- ) ?;
149+ check_input_exhaustivity ( ref_match_count, query, grammar, & root, source) ?;
130150 }
131151
132152 // Find the ids of all tree-sitter nodes that were identified as a leaf
@@ -152,7 +172,7 @@ pub fn apply_query(
152172
153173 let mut predicates = QueryPredicates :: default ( ) ;
154174
155- for p in query. general_predicates ( m. pattern_index ) {
175+ for p in query. query . general_predicates ( m. pattern_index ) {
156176 predicates = handle_predicate ( & p, & predicates) ?;
157177 }
158178 check_predicates ( & predicates) ?;
@@ -362,13 +382,13 @@ fn check_predicates(predicates: &QueryPredicates) -> FormatterResult<()> {
362382/// then that pattern originally matched nothing in the input.
363383fn check_input_exhaustivity (
364384 ref_match_count : usize ,
365- original_query : & Query ,
366- query_content : & str ,
385+ original_query : & TopiaryQuery ,
367386 grammar : & tree_sitter_facade:: Language ,
368387 root : & Node ,
369388 source : & [ u8 ] ,
370389) -> FormatterResult < ( ) > {
371- let pattern_count = original_query. pattern_count ( ) ;
390+ let pattern_count = original_query. query . pattern_count ( ) ;
391+ let query_content = & original_query. query_content ;
372392 // This particular test avoids a SIGSEGV error that occurs when trying
373393 // to count the matches of an empty query (see #481)
374394 if pattern_count == 1 {
@@ -379,6 +399,9 @@ fn check_input_exhaustivity(
379399 }
380400 }
381401 for i in 0 ..pattern_count {
402+ // We don't need to use TopiaryQuery in this test since we have no need
403+ // for duplicate versions of the query_content string, instead we create the query
404+ // manually.
382405 let mut query = Query :: new ( grammar, query_content)
383406 . map_err ( |e| FormatterError :: Query ( "Error parsing query file" . into ( ) , Some ( e) ) ) ?;
384407 query. disable_pattern ( i) ;
@@ -401,8 +424,7 @@ fn check_input_exhaustivity(
401424#[ cfg( target_arch = "wasm32" ) ]
402425fn check_input_exhaustivity (
403426 _ref_match_count : usize ,
404- _original_query : & Query ,
405- _query_content : & str ,
427+ _original_query : & TopiaryQuery ,
406428 _grammar : & tree_sitter_facade:: Language ,
407429 _root : & Node ,
408430 _source : & [ u8 ] ,
0 commit comments