rust_code_analysis/
find.rs

1use std::path::PathBuf;
2
3use crate::node::Node;
4
5use crate::dump::*;
6use crate::traits::*;
7
8/// Finds the types of nodes specified in the input slice.
9pub fn find<'a, T: ParserTrait>(parser: &'a T, filters: &[String]) -> Option<Vec<Node<'a>>> {
10    let filters = parser.get_filters(filters);
11    let node = parser.get_root();
12    let mut cursor = node.object().walk();
13    let mut stack = Vec::new();
14    let mut good = Vec::new();
15    let mut children = Vec::new();
16
17    stack.push(node);
18
19    while let Some(node) = stack.pop() {
20        if filters.any(&node) {
21            good.push(node);
22        }
23        cursor.reset(node.object());
24        if cursor.goto_first_child() {
25            loop {
26                children.push(Node::new(cursor.node()));
27                if !cursor.goto_next_sibling() {
28                    break;
29                }
30            }
31            for child in children.drain(..).rev() {
32                stack.push(child);
33            }
34        }
35    }
36    Some(good)
37}
38
39/// Configuration options for finding different
40/// types of nodes in a code.
41pub struct FindCfg {
42    /// Path to the file containing the code
43    pub path: PathBuf,
44    /// Types of nodes to find
45    pub filters: Vec<String>,
46    /// The first line of code considered in the search
47    ///
48    /// If `None`, the search starts from the
49    /// first line of code in a file
50    pub line_start: Option<usize>,
51    /// The end line of code considered in the search
52    ///
53    /// If `None`, the search ends at the
54    /// last line of code in a file
55    pub line_end: Option<usize>,
56}
57
58pub struct Find {
59    _guard: (),
60}
61
62impl Callback for Find {
63    type Res = std::io::Result<()>;
64    type Cfg = FindCfg;
65
66    fn call<T: ParserTrait>(cfg: Self::Cfg, parser: &T) -> Self::Res {
67        if let Some(good) = find(parser, &cfg.filters) {
68            if !good.is_empty() {
69                println!("In file {}", cfg.path.to_str().unwrap());
70                for node in good {
71                    dump_node(parser.get_code(), &node, 1, cfg.line_start, cfg.line_end)?;
72                }
73                println!();
74            }
75        }
76        Ok(())
77    }
78}