qlty_analysis/code/
query.rs1use crate::code::{File, NodeFilter};
2use tree_sitter::{Node, Query};
3
4pub const QUERY_MATCH_LIMIT: usize = 256;
5
6pub fn matches_count(query: &Query, node: &Node, capture_name: &str, filter: &NodeFilter) -> usize {
7 let mut cursor = tree_sitter::QueryCursor::new();
8 cursor.set_match_limit(QUERY_MATCH_LIMIT as u32);
9 let all_matches = cursor.matches(query, *node, "".as_bytes());
10
11 let mut count = 0;
12
13 for each_match in all_matches {
14 let capture = capture_by_name(query, capture_name, &each_match);
15 let node = capture.node;
16
17 if !filter.exclude(&node) {
18 count += 1;
19 }
20 }
21
22 count
23}
24
25pub fn all_captured_nodes<'a>(
26 query_source: &'a str,
27 source_file: &'a File,
28 node: &'a Node,
29) -> Vec<Node<'a>> {
30 let query_with_capture = format!("{} @the-capture", query_source);
31 let query = source_file.query(&query_with_capture);
32
33 let mut cursor = tree_sitter::QueryCursor::new();
34 cursor.set_match_limit(QUERY_MATCH_LIMIT as u32);
35
36 cursor
37 .matches(&query, *node, source_file.contents.as_bytes())
38 .flat_map(|each_match| each_match.captures)
39 .map(|capture| capture.node)
40 .collect()
41}
42
43pub fn capture_source<'a>(
44 query: &'a Query,
45 name: &'a str,
46 query_match: &'a tree_sitter::QueryMatch,
47 source_file: &File,
48) -> String {
49 let capture = capture_by_name(query, name, query_match);
50 node_source(&capture.node, source_file)
51}
52
53pub fn child_source(parent: &tree_sitter::Node, name: &str, source_file: &File) -> String {
54 let child = parent.child_by_field_name(name).unwrap();
55 node_source(&child, source_file)
56}
57
58pub fn node_source(node: &tree_sitter::Node, source_file: &File) -> String {
59 node.utf8_text(source_file.contents.as_bytes())
60 .unwrap()
61 .to_string()
62}
63
64pub fn capture_by_name_option<'a>(
65 query: &'a Query,
66 name: &'a str,
67 query_match: &'a tree_sitter::QueryMatch,
68) -> Option<&'a tree_sitter::QueryCapture<'a>> {
69 let index = query.capture_index_for_name(name)?;
70
71 query_match
72 .captures
73 .iter()
74 .find(|capture| capture.index == index)
75}
76
77pub fn capture_by_name<'a>(
78 query: &'a Query,
79 name: &'a str,
80 query_match: &'a tree_sitter::QueryMatch,
81) -> &'a tree_sitter::QueryCapture<'a> {
82 let index = query.capture_index_for_name(name).unwrap();
83
84 query_match
85 .captures
86 .iter()
87 .find(|capture| capture.index == index)
88 .unwrap()
89}