rust_code_analysis_code_split/
find.rs1use std::path::PathBuf;
2
3use crate::node::Node;
4
5use crate::dump::*;
6use crate::traits::*;
7
8pub 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#[derive(Debug)]
42pub struct FindCfg {
43 pub path: PathBuf,
45 pub filters: Vec<String>,
47 pub line_start: Option<usize>,
52 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}