ricecoder_refactoring/providers/
lsp_integration.rs

1//! Integration with ricecoder-lsp for external LSP server support
2//!
3//! This module provides integration with the ricecoder-lsp crate to query
4//! available LSP servers and delegate refactoring operations to them.
5
6use crate::error::Result;
7use crate::types::{Refactoring, ValidationResult};
8use super::lsp::LspProvider;
9use std::sync::Arc;
10
11/// LSP integration for querying available LSP servers
12///
13/// This struct provides methods to query ricecoder-lsp for available LSP servers
14/// and create LSP providers for them.
15pub struct LspIntegration;
16
17impl LspIntegration {
18    /// Query ricecoder-lsp for available LSP servers
19    ///
20    /// Returns a map of language -> LSP server information
21    pub fn query_available_lsp_servers() -> Result<std::collections::HashMap<String, LspServerInfo>> {
22        // In a real implementation, this would query ricecoder-lsp
23        // For now, return an empty map (LSP servers can be registered manually)
24        Ok(std::collections::HashMap::new())
25    }
26
27    /// Create an LSP provider for a language
28    ///
29    /// This creates a wrapper that delegates refactoring operations to an external LSP server.
30    pub fn create_lsp_provider(
31        language: &str,
32        server_info: &LspServerInfo,
33    ) -> Result<Arc<dyn LspProvider>> {
34        Ok(Arc::new(ExternalLspRefactoringProvider::new(
35            language.to_string(),
36            server_info.clone(),
37        )))
38    }
39
40    /// Detect available LSP servers from the system
41    ///
42    /// This scans for common LSP servers installed on the system
43    /// (rust-analyzer, tsserver, pylsp, etc.)
44    pub fn detect_system_lsp_servers() -> Result<Vec<LspServerInfo>> {
45        // In a real implementation, this would scan for installed LSP servers
46        // For now, return an empty list
47        Ok(Vec::new())
48    }
49}
50
51/// Information about an LSP server
52#[derive(Debug, Clone)]
53pub struct LspServerInfo {
54    /// Language supported by this LSP server
55    pub language: String,
56    /// Name of the LSP server (e.g., "rust-analyzer", "tsserver")
57    pub name: String,
58    /// Command to start the LSP server
59    pub command: String,
60    /// Arguments for the LSP server
61    pub args: Vec<String>,
62}
63
64/// External LSP refactoring provider
65///
66/// This provider delegates refactoring operations to an external LSP server.
67#[allow(dead_code)]
68struct ExternalLspRefactoringProvider {
69    language: String,
70    server_info: LspServerInfo,
71    available: std::sync::Arc<std::sync::Mutex<bool>>,
72}
73
74impl ExternalLspRefactoringProvider {
75    /// Create a new external LSP refactoring provider
76    fn new(language: String, server_info: LspServerInfo) -> Self {
77        Self {
78            language,
79            server_info,
80            available: std::sync::Arc::new(std::sync::Mutex::new(true)),
81        }
82    }
83
84    /// Check if the LSP server is running
85    fn check_availability(&self) -> bool {
86        // In a real implementation, this would check if the LSP server is running
87        // For now, assume it's available
88        true
89    }
90}
91
92impl LspProvider for ExternalLspRefactoringProvider {
93    fn is_available(&self) -> bool {
94        self.check_availability()
95    }
96
97    fn perform_refactoring(
98        &self,
99        code: &str,
100        _language: &str,
101        _refactoring: &Refactoring,
102    ) -> Result<String> {
103        // In a real implementation, this would send a request to the LSP server
104        // For now, return the code unchanged
105        Ok(code.to_string())
106    }
107
108    fn validate_refactoring(
109        &self,
110        _original: &str,
111        _refactored: &str,
112        _language: &str,
113    ) -> Result<ValidationResult> {
114        // In a real implementation, this would validate via the LSP server
115        Ok(ValidationResult {
116            passed: true,
117            errors: vec![],
118            warnings: vec![],
119        })
120    }
121
122    fn on_availability_changed(&self, _callback: Box<dyn Fn(bool) + Send + Sync>) {
123        // In a real implementation, this would register a callback
124        // for when the LSP server becomes available/unavailable
125    }
126}
127
128#[cfg(test)]
129mod tests {
130    use super::*;
131
132    #[test]
133    fn test_query_available_lsp_servers() -> Result<()> {
134        let servers = LspIntegration::query_available_lsp_servers()?;
135        // Should return a map (may be empty if no LSP servers are configured)
136        assert!(servers.is_empty() || !servers.is_empty());
137        Ok(())
138    }
139
140    #[test]
141    fn test_detect_system_lsp_servers() -> Result<()> {
142        let servers = LspIntegration::detect_system_lsp_servers()?;
143        // Should return a list (may be empty if no LSP servers are installed)
144        assert!(servers.is_empty() || !servers.is_empty());
145        Ok(())
146    }
147
148    #[test]
149    fn test_create_lsp_provider() -> Result<()> {
150        let server_info = LspServerInfo {
151            language: "rust".to_string(),
152            name: "rust-analyzer".to_string(),
153            command: "rust-analyzer".to_string(),
154            args: vec![],
155        };
156
157        let provider = LspIntegration::create_lsp_provider("rust", &server_info)?;
158        assert!(provider.is_available());
159
160        Ok(())
161    }
162}