ryo_analysis/cascade/
impact.rs1use std::path::PathBuf;
7
8use crate::SymbolId;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
14pub enum ImpactLevel {
15 Local = 1,
18
19 Reference = 2,
22
23 Structural = 3,
26
27 Semantic = 4,
30}
31
32impl ImpactLevel {
33 pub fn description(&self) -> &'static str {
35 match self {
36 Self::Local => "Local (same file only)",
37 Self::Reference => "Reference (cross-file references)",
38 Self::Structural => "Structural (type structure changes)",
39 Self::Semantic => "Semantic (behavior changes)",
40 }
41 }
42}
43
44#[derive(Debug, Default)]
46pub struct ImpactSet {
47 pub symbols: Vec<SymbolId>,
49
50 pub files: Vec<PathBuf>,
52}
53
54impl ImpactSet {
55 pub fn new() -> Self {
57 Self::default()
58 }
59
60 pub fn add_symbol(&mut self, symbol: SymbolId) {
62 if !self.symbols.contains(&symbol) {
63 self.symbols.push(symbol);
64 }
65 }
66
67 pub fn add_file(&mut self, file: PathBuf) {
69 if !self.files.contains(&file) {
70 self.files.push(file);
71 }
72 }
73
74 pub fn is_empty(&self) -> bool {
76 self.symbols.is_empty() && self.files.is_empty()
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83
84 #[test]
85 fn test_impact_level_ordering() {
86 assert!(ImpactLevel::Local < ImpactLevel::Reference);
87 assert!(ImpactLevel::Reference < ImpactLevel::Structural);
88 assert!(ImpactLevel::Structural < ImpactLevel::Semantic);
89 }
90
91 #[test]
92 fn test_impact_set() {
93 let mut set = ImpactSet::new();
94 assert!(set.is_empty());
95
96 set.add_file(PathBuf::from("test.rs"));
97 assert!(!set.is_empty());
98 }
99}