Skip to main content

rust_code_analysis_code_split/
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.cursor();
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);
24        if cursor.goto_first_child() {
25            loop {
26                children.push(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.
41#[derive(Debug)]
42pub struct FindCfg {
43    /// Path to the file containing the code
44    pub path: PathBuf,
45    /// Types of nodes to find
46    pub filters: Vec<String>,
47    /// The first line of code considered in the search
48    ///
49    /// If `None`, the search starts from the
50    /// first line of code in a file
51    pub line_start: Option<usize>,
52    /// The end line of code considered in the search
53    ///
54    /// If `None`, the search ends at the
55    /// last line of code in a file
56    pub line_end: Option<usize>,
57}
58
59pub struct Find {
60    _guard: (),
61}
62
63impl Callback for Find {
64    type Res = std::io::Result<()>;
65    type Cfg = FindCfg;
66
67    fn call<T: ParserTrait>(cfg: Self::Cfg, parser: &T) -> Self::Res {
68        if let Some(good) = find(parser, &cfg.filters)
69            && !good.is_empty()
70        {
71            println!("In file {}", cfg.path.to_str().unwrap());
72            for node in good {
73                dump_node(parser.get_code(), &node, 1, cfg.line_start, cfg.line_end)?;
74            }
75            println!();
76        }
77        Ok(())
78    }
79}