ricecoder_lsp/diagnostics/
generic_engine.rs1use crate::providers::{DiagnosticsProvider, DiagnosticsRegistry, ProviderResult};
7use crate::types::{Diagnostic, Range};
8
9pub struct GenericDiagnosticsEngine {
11 registry: DiagnosticsRegistry,
12}
13
14impl GenericDiagnosticsEngine {
15 pub fn new() -> Self {
17 Self {
18 registry: DiagnosticsRegistry::new(),
19 }
20 }
21
22 pub fn register_provider(&mut self, provider: Box<dyn DiagnosticsProvider>) {
24 self.registry.register(provider);
25 }
26
27 pub fn registry(&self) -> &DiagnosticsRegistry {
29 &self.registry
30 }
31
32 pub fn registry_mut(&mut self) -> &mut DiagnosticsRegistry {
34 &mut self.registry
35 }
36
37 pub fn generate_diagnostics(
39 &self,
40 code: &str,
41 language: &str,
42 ) -> ProviderResult<Vec<Diagnostic>> {
43 if let Some(provider) = self.registry.get(language) {
44 provider.generate_diagnostics(code)
45 } else {
46 tracing::debug!(
48 "No diagnostics provider found for language '{}', returning empty",
49 language
50 );
51 Ok(Vec::new())
52 }
53 }
54
55 pub fn generate_diagnostics_for_range(
57 &self,
58 code: &str,
59 language: &str,
60 range: Range,
61 ) -> ProviderResult<Vec<Diagnostic>> {
62 let all_diagnostics = self.generate_diagnostics(code, language)?;
63
64 let filtered = all_diagnostics
66 .into_iter()
67 .filter(|diag| {
68 diag.range.start.line >= range.start.line && diag.range.end.line <= range.end.line
69 })
70 .collect();
71
72 Ok(filtered)
73 }
74
75 pub fn has_provider(&self, language: &str) -> bool {
77 self.registry.has_provider(language)
78 }
79
80 pub fn languages(&self) -> Vec<&str> {
82 self.registry.languages()
83 }
84}
85
86impl Default for GenericDiagnosticsEngine {
87 fn default() -> Self {
88 Self::new()
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 struct MockDiagnosticsProvider;
97
98 impl DiagnosticsProvider for MockDiagnosticsProvider {
99 fn language(&self) -> &str {
100 "mock"
101 }
102
103 fn generate_diagnostics(&self, _code: &str) -> ProviderResult<Vec<Diagnostic>> {
104 Ok(vec![])
105 }
106
107 fn config(&self) -> Option<&crate::config::LanguageConfig> {
108 None
109 }
110 }
111
112 #[test]
113 fn test_generic_diagnostics_engine_with_provider() {
114 let mut engine = GenericDiagnosticsEngine::new();
115 engine.register_provider(Box::new(MockDiagnosticsProvider));
116
117 assert!(engine.has_provider("mock"));
118 assert!(engine.generate_diagnostics("test", "mock").is_ok());
119 }
120
121 #[test]
122 fn test_generic_diagnostics_engine_fallback() {
123 let engine = GenericDiagnosticsEngine::new();
124
125 assert!(!engine.has_provider("unknown"));
127 let result = engine.generate_diagnostics("test", "unknown");
128 assert!(result.is_ok());
129 assert!(result.unwrap().is_empty());
130 }
131
132 #[test]
133 fn test_generic_diagnostics_engine_languages() {
134 let mut engine = GenericDiagnosticsEngine::new();
135 engine.register_provider(Box::new(MockDiagnosticsProvider));
136
137 let languages = engine.languages();
138 assert!(languages.contains(&"mock"));
139 }
140}