Skip to main content

rust_code_analysis_code_split/
count.rs

1extern crate num_format;
2
3use num_format::{Locale, ToFormattedString};
4use std::fmt;
5use std::sync::{Arc, Mutex};
6
7use crate::traits::*;
8
9/// Counts the types of nodes specified in the input slice
10/// and the number of nodes in a code.
11pub fn count<T: ParserTrait>(parser: &T, filters: &[String]) -> (usize, usize) {
12    let filters = parser.get_filters(filters);
13    let node = parser.get_root();
14    let mut cursor = node.cursor();
15    let mut stack = Vec::new();
16    let mut good = 0;
17    let mut total = 0;
18
19    stack.push(node);
20
21    while let Some(node) = stack.pop() {
22        total += 1;
23        if filters.any(&node) {
24            good += 1;
25        }
26        cursor.reset(&node);
27        if cursor.goto_first_child() {
28            loop {
29                stack.push(cursor.node());
30                if !cursor.goto_next_sibling() {
31                    break;
32                }
33            }
34        }
35    }
36    (good, total)
37}
38
39/// Configuration options for counting different
40/// types of nodes in a code.
41#[derive(Debug)]
42pub struct CountCfg {
43    /// Types of nodes to count
44    pub filters: Vec<String>,
45    /// Number of nodes of a certain type counted by each thread
46    pub stats: Arc<Mutex<Count>>,
47}
48
49/// Count of different types of nodes in a code.
50#[derive(Debug, Default)]
51pub struct Count {
52    /// The number of specific types of nodes searched in a code
53    pub good: usize,
54    /// The total number of nodes in a code
55    pub total: usize,
56}
57
58impl Callback for Count {
59    type Res = std::io::Result<()>;
60    type Cfg = CountCfg;
61
62    fn call<T: ParserTrait>(cfg: Self::Cfg, parser: &T) -> Self::Res {
63        let (good, total) = count(parser, &cfg.filters);
64        let mut results = cfg.stats.lock().unwrap();
65        results.good += good;
66        results.total += total;
67        Ok(())
68    }
69}
70
71impl fmt::Display for Count {
72    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
73        writeln!(
74            f,
75            "Total nodes: {}",
76            self.total.to_formatted_string(&Locale::en)
77        )?;
78        writeln!(
79            f,
80            "Found nodes: {}",
81            self.good.to_formatted_string(&Locale::en)
82        )?;
83        write!(
84            f,
85            "Percentage: {:.2}%",
86            (self.good as f64) / (self.total as f64) * 100.
87        )
88    }
89}