ricecoder_lsp/diagnostics/
adapters.rs

1//! Adapter implementations for existing diagnostics engines to implement DiagnosticsProvider trait
2//!
3//! This module provides adapter wrappers that allow existing language-specific diagnostics
4//! to be used as pluggable providers in the configuration-driven architecture.
5
6use crate::config::LanguageConfig;
7use crate::diagnostics::{python_rules, rust_rules, typescript_rules};
8use crate::providers::{DiagnosticsProvider, ProviderResult};
9use crate::types::Diagnostic;
10
11/// Adapter for Rust diagnostics provider
12pub struct RustDiagnosticsAdapter {
13    config: Option<LanguageConfig>,
14}
15
16impl RustDiagnosticsAdapter {
17    /// Create a new Rust diagnostics adapter
18    pub fn new() -> Self {
19        Self { config: None }
20    }
21
22    /// Create with configuration
23    pub fn with_config(config: LanguageConfig) -> Self {
24        Self {
25            config: Some(config),
26        }
27    }
28}
29
30impl Default for RustDiagnosticsAdapter {
31    fn default() -> Self {
32        Self::new()
33    }
34}
35
36impl DiagnosticsProvider for RustDiagnosticsAdapter {
37    fn language(&self) -> &str {
38        "rust"
39    }
40
41    fn generate_diagnostics(&self, code: &str) -> ProviderResult<Vec<Diagnostic>> {
42        rust_rules::generate_rust_diagnostics(code)
43            .map_err(|e| crate::providers::ProviderError::Error(e.to_string()))
44    }
45
46    fn config(&self) -> Option<&LanguageConfig> {
47        self.config.as_ref()
48    }
49}
50
51/// Adapter for TypeScript diagnostics provider
52pub struct TypeScriptDiagnosticsAdapter {
53    config: Option<LanguageConfig>,
54}
55
56impl TypeScriptDiagnosticsAdapter {
57    /// Create a new TypeScript diagnostics adapter
58    pub fn new() -> Self {
59        Self { config: None }
60    }
61
62    /// Create with configuration
63    pub fn with_config(config: LanguageConfig) -> Self {
64        Self {
65            config: Some(config),
66        }
67    }
68}
69
70impl Default for TypeScriptDiagnosticsAdapter {
71    fn default() -> Self {
72        Self::new()
73    }
74}
75
76impl DiagnosticsProvider for TypeScriptDiagnosticsAdapter {
77    fn language(&self) -> &str {
78        "typescript"
79    }
80
81    fn generate_diagnostics(&self, code: &str) -> ProviderResult<Vec<Diagnostic>> {
82        typescript_rules::generate_typescript_diagnostics(code)
83            .map_err(|e| crate::providers::ProviderError::Error(e.to_string()))
84    }
85
86    fn config(&self) -> Option<&LanguageConfig> {
87        self.config.as_ref()
88    }
89}
90
91/// Adapter for Python diagnostics provider
92pub struct PythonDiagnosticsAdapter {
93    config: Option<LanguageConfig>,
94}
95
96impl PythonDiagnosticsAdapter {
97    /// Create a new Python diagnostics adapter
98    pub fn new() -> Self {
99        Self { config: None }
100    }
101
102    /// Create with configuration
103    pub fn with_config(config: LanguageConfig) -> Self {
104        Self {
105            config: Some(config),
106        }
107    }
108}
109
110impl Default for PythonDiagnosticsAdapter {
111    fn default() -> Self {
112        Self::new()
113    }
114}
115
116impl DiagnosticsProvider for PythonDiagnosticsAdapter {
117    fn language(&self) -> &str {
118        "python"
119    }
120
121    fn generate_diagnostics(&self, code: &str) -> ProviderResult<Vec<Diagnostic>> {
122        python_rules::generate_python_diagnostics(code)
123            .map_err(|e| crate::providers::ProviderError::Error(e.to_string()))
124    }
125
126    fn config(&self) -> Option<&LanguageConfig> {
127        self.config.as_ref()
128    }
129}
130
131#[cfg(test)]
132mod tests {
133    use super::*;
134
135    #[test]
136    fn test_rust_diagnostics_adapter_language() {
137        let adapter = RustDiagnosticsAdapter::new();
138        assert_eq!(adapter.language(), "rust");
139    }
140
141    #[test]
142    fn test_typescript_diagnostics_adapter_language() {
143        let adapter = TypeScriptDiagnosticsAdapter::new();
144        assert_eq!(adapter.language(), "typescript");
145    }
146
147    #[test]
148    fn test_python_diagnostics_adapter_language() {
149        let adapter = PythonDiagnosticsAdapter::new();
150        assert_eq!(adapter.language(), "python");
151    }
152
153    #[test]
154    fn test_rust_diagnostics_adapter_no_config() {
155        let adapter = RustDiagnosticsAdapter::new();
156        assert!(adapter.config().is_none());
157    }
158}