debtmap/analyzers/
traits.rs

1//! Local analyzer traits to decouple analyzer modules
2
3use anyhow::Result;
4use std::path::Path;
5
6/// Trait for language-specific analyzers
7pub trait LanguageAnalyzer: Send + Sync {
8    /// Analyze a file and return metrics
9    fn analyze_file(&self, path: &Path, content: &str) -> Result<crate::core::FileMetrics>;
10
11    /// Get the language this analyzer handles
12    fn language(&self) -> crate::core::Language;
13
14    /// Check if this analyzer can handle a file
15    fn can_handle(&self, path: &Path) -> bool {
16        crate::core::Language::from_path(path) == self.language()
17    }
18}
19
20/// Trait for call graph analysis
21pub trait CallGraphAnalyzer: Send + Sync {
22    /// Build a call graph for the given content
23    fn build_call_graph(&self, content: &str, path: &Path) -> Result<CallGraph>;
24
25    /// Find dependencies for a function
26    fn find_dependencies(&self, function: &str, graph: &CallGraph) -> Vec<String>;
27}
28
29/// Simple call graph representation
30#[derive(Debug, Clone)]
31pub struct CallGraph {
32    pub nodes: Vec<CallNode>,
33    pub edges: Vec<CallEdge>,
34}
35
36#[derive(Debug, Clone)]
37pub struct CallNode {
38    pub name: String,
39    pub file: std::path::PathBuf,
40    pub line: usize,
41}
42
43#[derive(Debug, Clone)]
44pub struct CallEdge {
45    pub from: String,
46    pub to: String,
47    pub call_type: CallType,
48}
49
50#[derive(Debug, Clone)]
51pub enum CallType {
52    Direct,
53    Trait,
54    Generic,
55    Closure,
56}
57
58/// Trait for type tracking
59pub trait TypeTracker: Send + Sync {
60    /// Track type information for a symbol
61    fn track_type(&mut self, symbol: &str, type_info: TypeInfo);
62
63    /// Get type information for a symbol
64    fn get_type(&self, symbol: &str) -> Option<&TypeInfo>;
65
66    /// Clear all tracked types
67    fn clear(&mut self);
68}
69
70#[derive(Debug, Clone)]
71pub struct TypeInfo {
72    pub name: String,
73    pub kind: TypeKind,
74    pub generic_params: Vec<String>,
75}
76
77#[derive(Debug, Clone)]
78pub enum TypeKind {
79    Struct,
80    Enum,
81    Trait,
82    Function,
83    Primitive,
84    Generic,
85}
86
87/// Trait for test detection
88pub trait TestDetector: Send + Sync {
89    /// Check if a function is a test
90    fn is_test_function(&self, name: &str, attributes: &[String]) -> bool;
91
92    /// Check if a module is a test module
93    fn is_test_module(&self, path: &Path) -> bool;
94
95    /// Extract test metadata
96    fn extract_test_metadata(&self, content: &str) -> TestMetadata;
97}
98
99#[derive(Debug, Clone, Default)]
100pub struct TestMetadata {
101    pub test_count: usize,
102    pub assertion_count: usize,
103    pub has_setup: bool,
104    pub has_teardown: bool,
105    pub test_frameworks: Vec<String>,
106}
107
108/// Trait for purity analysis
109pub trait PurityAnalyzer: Send + Sync {
110    /// Check if a function is pure
111    fn is_pure(&self, function: &str, body: &str) -> (bool, f32);
112
113    /// Identify side effects in code
114    fn find_side_effects(&self, body: &str) -> Vec<SideEffect>;
115}
116
117#[derive(Debug, Clone)]
118pub struct SideEffect {
119    pub kind: SideEffectKind,
120    pub location: usize,
121    pub description: String,
122}
123
124#[derive(Debug, Clone)]
125pub enum SideEffectKind {
126    IO,
127    Mutation,
128    GlobalState,
129    ExternalCall,
130    Unsafe,
131}