fob_graph/symbol/
statistics.rs

1//! Statistics and analysis helpers for symbols.
2
3use serde::{Deserialize, Serialize};
4
5use super::{SymbolKind, SymbolTable};
6
7/// Statistics about symbols across the entire graph.
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct SymbolStatistics {
10    /// Total number of symbols analyzed
11    pub total_symbols: usize,
12    /// Number of unused symbols detected
13    pub unused_symbols: usize,
14    /// Breakdown by symbol kind
15    pub by_kind: Vec<(SymbolKind, usize)>,
16}
17
18impl SymbolStatistics {
19    /// Create new symbol statistics.
20    pub fn new(total_symbols: usize, unused_symbols: usize) -> Self {
21        Self {
22            total_symbols,
23            unused_symbols,
24            by_kind: Vec::new(),
25        }
26    }
27
28    /// Create statistics from a collection of symbol tables.
29    pub fn from_tables<'a, I>(tables: I) -> Self
30    where
31        I: Iterator<Item = &'a SymbolTable>,
32    {
33        let mut total_symbols = 0;
34        let mut unused_symbols = 0;
35        let mut kind_counts: std::collections::HashMap<SymbolKind, usize> =
36            std::collections::HashMap::new();
37
38        for table in tables {
39            total_symbols += table.len();
40            unused_symbols += table.unused_symbols().len();
41
42            for symbol in &table.symbols {
43                *kind_counts.entry(symbol.kind).or_insert(0) += 1;
44            }
45        }
46
47        let by_kind = kind_counts.into_iter().collect();
48
49        Self {
50            total_symbols,
51            unused_symbols,
52            by_kind,
53        }
54    }
55
56    /// Calculate the percentage of unused symbols.
57    pub fn unused_percentage(&self) -> f64 {
58        if self.total_symbols == 0 {
59            0.0
60        } else {
61            (self.unused_symbols as f64 / self.total_symbols as f64) * 100.0
62        }
63    }
64}