(
config: &opencode_config::Config,
file_hint: Option<&Path>,
)
| 3317 | } |
| 3318 | |
| 3319 | fn select_lsp_server( |
| 3320 | config: &opencode_config::Config, |
| 3321 | file_hint: Option<&Path>, |
| 3322 | ) -> anyhow::Result<(String, ConfigLspServerConfig)> { |
| 3323 | let Some(lsp_config) = &config.lsp else { |
| 3324 | anyhow::bail!("No `lsp` configuration found in opencode.json(c)."); |
| 3325 | }; |
| 3326 | |
| 3327 | let servers = match lsp_config { |
| 3328 | LspConfig::Disabled(false) => { |
| 3329 | anyhow::bail!("LSP is disabled by config (`\"lsp\": false`)."); |
| 3330 | } |
| 3331 | LspConfig::Disabled(true) => { |
| 3332 | anyhow::bail!("Invalid `lsp: true` config. Use an object mapping LSP servers."); |
| 3333 | } |
| 3334 | LspConfig::Enabled(map) => map, |
| 3335 | }; |
| 3336 | |
| 3337 | let ext = file_hint |
| 3338 | .and_then(|p| p.extension().and_then(|x| x.to_str())) |
| 3339 | .map(|x| format!(".{}", x.to_ascii_lowercase())); |
| 3340 | |
| 3341 | let mut fallback: Option<(String, ConfigLspServerConfig)> = None; |
| 3342 | for (id, server) in servers { |
| 3343 | if server.disabled.unwrap_or(false) || server.command.is_empty() { |
| 3344 | continue; |
| 3345 | } |
| 3346 | if fallback.is_none() { |
| 3347 | fallback = Some((id.clone(), server.clone())); |
| 3348 | } |
| 3349 | |
| 3350 | if let Some(ref ext) = ext { |
| 3351 | if !server.extensions.is_empty() |
| 3352 | && !server |
| 3353 | .extensions |
| 3354 | .iter() |
| 3355 | .any(|value| value.eq_ignore_ascii_case(ext.as_str())) |
| 3356 | { |
| 3357 | continue; |
| 3358 | } |
| 3359 | } |
| 3360 | return Ok((id.clone(), server.clone())); |
| 3361 | } |
| 3362 | |
| 3363 | fallback |
| 3364 | .ok_or_else(|| anyhow::anyhow!("No enabled LSP server with an executable command found.")) |
| 3365 | } |
| 3366 | |
| 3367 | async fn create_lsp_client(file_hint: Option<&Path>) -> anyhow::Result<LspClient> { |
| 3368 | let cwd = std::env::current_dir()?; |
no test coverage detected