debtmap/analysis/patterns/
rust_traits.rs1use super::{Implementation, PatternInstance, PatternType, UsageSite};
8use crate::analysis::call_graph::TraitRegistry;
9use std::sync::Arc;
10
11pub struct RustTraitPatternRecognizer {
12 trait_registry: Arc<TraitRegistry>,
13}
14
15impl RustTraitPatternRecognizer {
16 pub fn new(trait_registry: Arc<TraitRegistry>) -> Self {
17 Self { trait_registry }
18 }
19
20 pub fn detect_trait_observer_patterns(&self) -> Vec<PatternInstance> {
22 let mut patterns = Vec::new();
23
24 let stats = self.trait_registry.get_statistics();
25 if stats.total_traits == 0 {
26 return patterns;
27 }
28
29 let unresolved_calls = self.trait_registry.get_unresolved_trait_calls();
30
31 let mut trait_names = std::collections::HashSet::new();
32 for call in unresolved_calls.iter() {
33 if call.trait_name != "Unknown" {
34 trait_names.insert(call.trait_name.clone());
35 }
36 }
37
38 for trait_name in &trait_names {
39 if let Some(implementations) = self.trait_registry.find_implementations(trait_name) {
40 if !implementations.is_empty() {
41 let impls: Vec<Implementation> = implementations
42 .iter()
43 .map(|impl_info| Implementation {
44 file: impl_info.method_id.file.clone(),
45 class_name: None,
46 function_name: impl_info.method_name.clone(),
47 line: impl_info.method_id.line,
48 })
49 .collect();
50
51 let usage_sites = self.find_trait_method_calls(trait_name);
52
53 patterns.push(PatternInstance {
54 pattern_type: PatternType::Observer,
55 confidence: 0.95,
56 base_class: Some(trait_name.clone()),
57 implementations: impls,
58 usage_sites,
59 reasoning: format!(
60 "Rust trait {} with {} implementations",
61 trait_name,
62 implementations.len()
63 ),
64 });
65 }
66 }
67 }
68
69 patterns
70 }
71
72 fn find_trait_method_calls(&self, trait_name: &str) -> Vec<UsageSite> {
73 self.trait_registry
74 .get_unresolved_trait_calls()
75 .iter()
76 .filter(|call| call.trait_name == trait_name || call.trait_name == "Unknown")
77 .map(|call| UsageSite {
78 file: call.caller.file.clone(),
79 line: call.line,
80 context: format!("Trait method call: {}", call.method_name),
81 })
82 .collect()
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[test]
91 fn test_rust_trait_recognizer_creation() {
92 let registry = Arc::new(TraitRegistry::new());
93 let recognizer = RustTraitPatternRecognizer::new(registry);
94 let patterns = recognizer.detect_trait_observer_patterns();
95 assert_eq!(patterns.len(), 0);
96 }
97}