ricecoder_lsp/semantic/
fallback_analyzer.rs

1//! Fallback semantic analyzer for unsupported languages
2//!
3//! Provides graceful degradation for languages that are not explicitly supported.
4//! Returns empty results and logs warnings when unsupported languages are encountered.
5
6use super::{SemanticAnalyzer, SemanticResult};
7use crate::types::{Language, Position, SemanticInfo, Symbol};
8
9/// Fallback analyzer for unsupported languages
10pub struct FallbackAnalyzer;
11
12impl FallbackAnalyzer {
13    /// Create a new fallback analyzer
14    pub fn new() -> Self {
15        Self
16    }
17}
18
19impl Default for FallbackAnalyzer {
20    fn default() -> Self {
21        Self::new()
22    }
23}
24
25impl SemanticAnalyzer for FallbackAnalyzer {
26    fn analyze(&self, _code: &str) -> SemanticResult<SemanticInfo> {
27        // Log warning about unsupported language
28        tracing::warn!("Analyzing code with unsupported language; returning empty semantic info");
29
30        // Return empty semantic information
31        Ok(SemanticInfo {
32            symbols: Vec::new(),
33            imports: Vec::new(),
34            definitions: Vec::new(),
35            references: Vec::new(),
36        })
37    }
38
39    fn extract_symbols(&self, _code: &str) -> SemanticResult<Vec<Symbol>> {
40        // Log warning about unsupported language
41        tracing::warn!("Extracting symbols from unsupported language; returning empty symbol list");
42
43        // Return empty symbol list
44        Ok(Vec::new())
45    }
46
47    fn get_hover_info(&self, _code: &str, _position: Position) -> SemanticResult<Option<String>> {
48        // Log warning about unsupported language
49        tracing::warn!("Getting hover info for unsupported language; returning None");
50
51        // Return no hover information
52        Ok(None)
53    }
54
55    fn language(&self) -> Language {
56        Language::Unknown
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63
64    #[test]
65    fn test_analyze_returns_empty() {
66        let analyzer = FallbackAnalyzer::new();
67        let code = "some code in unknown language";
68        let info = analyzer.analyze(code).unwrap();
69        assert!(info.symbols.is_empty());
70        assert!(info.imports.is_empty());
71        assert!(info.definitions.is_empty());
72        assert!(info.references.is_empty());
73    }
74
75    #[test]
76    fn test_extract_symbols_returns_empty() {
77        let analyzer = FallbackAnalyzer::new();
78        let code = "some code in unknown language";
79        let symbols = analyzer.extract_symbols(code).unwrap();
80        assert!(symbols.is_empty());
81    }
82
83    #[test]
84    fn test_get_hover_info_returns_none() {
85        let analyzer = FallbackAnalyzer::new();
86        let code = "some code in unknown language";
87        let position = Position::new(0, 0);
88        let hover = analyzer.get_hover_info(code, position).unwrap();
89        assert!(hover.is_none());
90    }
91
92    #[test]
93    fn test_language() {
94        let analyzer = FallbackAnalyzer::new();
95        assert_eq!(analyzer.language(), Language::Unknown);
96    }
97
98    #[test]
99    fn test_graceful_degradation() {
100        let analyzer = FallbackAnalyzer::new();
101        let code = "<?php echo 'hello'; ?>";
102
103        // Should not crash, just return empty results
104        let info = analyzer.analyze(code).unwrap();
105        assert!(info.symbols.is_empty());
106
107        let symbols = analyzer.extract_symbols(code).unwrap();
108        assert!(symbols.is_empty());
109
110        let hover = analyzer.get_hover_info(code, Position::new(0, 0)).unwrap();
111        assert!(hover.is_none());
112    }
113}