(
params: &LspParams,
path: &PathBuf,
line: u32,
character: u32,
ctx: &ToolContext,
)
| 145 | |
| 146 | #[cfg(feature = "lsp")] |
| 147 | async fn execute_with_lsp( |
| 148 | params: &LspParams, |
| 149 | path: &PathBuf, |
| 150 | line: u32, |
| 151 | character: u32, |
| 152 | ctx: &ToolContext, |
| 153 | ) -> Result<ToolResult, ToolError> { |
| 154 | use opencode_lsp::{detect_language, LspClientRegistry}; |
| 155 | use std::sync::Arc; |
| 156 | |
| 157 | let lsp_registry: Option<Arc<LspClientRegistry>> = ctx.lsp_registry.clone(); |
| 158 | |
| 159 | let output = match &lsp_registry { |
| 160 | Some(registry) => { |
| 161 | // Check if any LSP client can handle this file type (mirrors TS LSP.hasClients) |
| 162 | if !registry.has_clients(path).await { |
| 163 | return Err(ToolError::ExecutionError( |
| 164 | "No LSP server available for this file type.".to_string(), |
| 165 | )); |
| 166 | } |
| 167 | |
| 168 | // Touch the file to open/refresh it in all matching LSP clients, |
| 169 | // waiting for diagnostics (mirrors TS LSP.touchFile(file, true)) |
| 170 | registry.touch_file(path, true).await.map_err(|e| { |
| 171 | ToolError::ExecutionError(format!("Failed to touch file in LSP: {}", e)) |
| 172 | })?; |
| 173 | |
| 174 | let language = detect_language(path); |
| 175 | let clients = registry.list().await; |
| 176 | let client = clients |
| 177 | .iter() |
| 178 | .find(|(id, _)| id.contains(language)) |
| 179 | .map(|(_, c)| c.clone()); |
| 180 | |
| 181 | match client { |
| 182 | Some(client) => match ¶ms.operation { |
| 183 | LspOperation::GoToDefinition => { |
| 184 | match client.goto_definition(path, line, character).await { |
| 185 | Ok(Some(loc)) => format_location_result("Definition", loc), |
| 186 | Ok(None) => "No definition found.".to_string(), |
| 187 | Err(e) => format!("LSP error: {}", e), |
| 188 | } |
| 189 | } |
| 190 | LspOperation::FindReferences => { |
| 191 | match client.references(path, line, character).await { |
| 192 | Ok(locs) if !locs.is_empty() => locs |
| 193 | .iter() |
| 194 | .map(|l| format_location(l)) |
| 195 | .collect::<Vec<_>>() |
| 196 | .join("\n"), |
| 197 | Ok(_) => "No references found.".to_string(), |
| 198 | Err(e) => format!("LSP error: {}", e), |
| 199 | } |
| 200 | } |
| 201 | LspOperation::Hover => match client.hover(path, line, character).await { |
| 202 | Ok(Some(hover)) => format_hover_result(hover), |
| 203 | Ok(None) => "No hover information available.".to_string(), |
| 204 | Err(e) => format!("LSP error: {}", e), |
no test coverage detected