From c1c8a74c7f46579450b7757a7c2c3453834d2727 Mon Sep 17 00:00:00 2001 From: Henrique Ferreiro Date: Tue, 16 Apr 2024 18:17:15 +0200 Subject: [PATCH] Add ability to specify binary path/args for clangd (#10608) This uses the language server settings added in #9293 to allow users to specify the binary path and arguments with which to start up `clangd`. Example user settings for `clangd`: ```json { "lsp": { "clangd": { "binary": { "path": "/usr/bin/clangd", "arguments": ["--log=verbose"] }, } } } ``` Constraints: * Right now this only allows ABSOLUTE paths. Release Notes: - Added ability to specify `clangd` binary `path` (must be absolute) and `arguments` in user settings. Example: `{"lsp": {"clangd": {"binary": {"path": "/usr/bin/clangd", "arguments": ["--log=verbose"] }}}}` --- crates/languages/src/c.rs | 59 ++++++++++++++++++++++++++++---------- crates/languages/src/go.rs | 2 +- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/crates/languages/src/c.rs b/crates/languages/src/c.rs index 1a6e8e113c381fc80139bac7c4b8858b61ced718..d9c54eb8b750f04c71a00307b9ac27665f664904 100644 --- a/crates/languages/src/c.rs +++ b/crates/languages/src/c.rs @@ -4,6 +4,8 @@ use futures::StreamExt; use gpui::AsyncAppContext; pub use language::*; use lsp::LanguageServerBinary; +use project::project_settings::{BinarySettings, ProjectSettings}; +use settings::Settings; use smol::fs::{self, File}; use std::{any::Any, env::consts, path::PathBuf, sync::Arc}; use util::{ @@ -14,10 +16,51 @@ use util::{ pub struct CLspAdapter; +impl CLspAdapter { + const SERVER_NAME: &'static str = "clangd"; +} + #[async_trait(?Send)] impl super::LspAdapter for CLspAdapter { fn name(&self) -> LanguageServerName { - LanguageServerName("clangd".into()) + LanguageServerName(Self::SERVER_NAME.into()) + } + + async fn check_if_user_installed( + &self, + delegate: &dyn LspAdapterDelegate, + cx: &AsyncAppContext, + ) -> Option { + let configured_binary = cx.update(|cx| { + ProjectSettings::get_global(cx) + .lsp + .get(Self::SERVER_NAME) + .and_then(|s| s.binary.clone()) + }); + + if let Ok(Some(BinarySettings { + path: Some(path), + arguments, + })) = configured_binary + { + Some(LanguageServerBinary { + path: path.into(), + arguments: arguments + .unwrap_or_default() + .iter() + .map(|arg| arg.into()) + .collect(), + env: None, + }) + } else { + let env = delegate.shell_env().await; + let path = delegate.which(Self::SERVER_NAME.as_ref()).await?; + Some(LanguageServerBinary { + path, + arguments: vec![], + env: Some(env), + }) + } } async fn fetch_latest_server_version( @@ -45,20 +88,6 @@ impl super::LspAdapter for CLspAdapter { Ok(Box::new(version) as Box<_>) } - async fn check_if_user_installed( - &self, - delegate: &dyn LspAdapterDelegate, - _: &AsyncAppContext, - ) -> Option { - let env = delegate.shell_env().await; - let path = delegate.which("clangd".as_ref()).await?; - Some(LanguageServerBinary { - path, - arguments: vec![], - env: Some(env), - }) - } - async fn fetch_server_binary( &self, version: Box, diff --git a/crates/languages/src/go.rs b/crates/languages/src/go.rs index 58477d34a2d5510f4d3bf12935541acd9008f120..8b591f7f128f536ca26780686226e5ab5639344f 100644 --- a/crates/languages/src/go.rs +++ b/crates/languages/src/go.rs @@ -88,7 +88,7 @@ impl super::LspAdapter for GoLspAdapter { }) } else { let env = delegate.shell_env().await; - let path = delegate.which("gopls".as_ref()).await?; + let path = delegate.which(Self::SERVER_NAME.as_ref()).await?; Some(LanguageServerBinary { path, arguments: server_binary_arguments(),