From 5f6cbcedf39254be0b0808da821179868d874b32 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 23 Jan 2025 12:42:08 +0200 Subject: [PATCH] Omit `tsdk_path` from the servers' options if it does not exist --- Cargo.lock | 1 + crates/language/src/language.rs | 4 ++ crates/language_extension/Cargo.toml | 1 + .../src/extension_lsp_adapter.rs | 3 ++ crates/languages/src/css.rs | 2 + crates/languages/src/go.rs | 2 + crates/languages/src/json.rs | 4 +- crates/languages/src/python.rs | 3 ++ crates/languages/src/tailwind.rs | 4 +- crates/languages/src/typescript.rs | 20 +++++++-- crates/languages/src/vtsls.rs | 18 ++++++-- crates/languages/src/yaml.rs | 3 +- crates/project/src/lsp_store.rs | 45 +++++++++++++++---- crates/project/src/project.rs | 2 + 14 files changed, 92 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d834076f79810d749230ab2ffad10d0d3346df5c..dbce600c392d7252be1cb70b1484377a8a176eb8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6663,6 +6663,7 @@ dependencies = [ "async-trait", "collections", "extension", + "fs", "futures 0.3.31", "gpui", "language", diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index 8061c7efa9879ed11dadea87c25fe80a22be1a0d..4176afca5b25cac688e948154b60b13ab0ef5fc0 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -25,6 +25,7 @@ use crate::language_settings::SoftWrap; use anyhow::{anyhow, Context, Result}; use async_trait::async_trait; use collections::{HashMap, HashSet}; +use fs::Fs; use futures::Future; use gpui::{AppContext, AsyncAppContext, Model, SharedString, Task}; pub use highlight_map::HighlightMap; @@ -464,6 +465,7 @@ pub trait LspAdapter: 'static + Send + Sync { /// Returns initialization options that are going to be sent to a LSP server as a part of [`lsp::InitializeParams`] async fn initialization_options( self: Arc, + _: &dyn Fs, _: &Arc, ) -> Result> { Ok(None) @@ -471,6 +473,7 @@ pub trait LspAdapter: 'static + Send + Sync { async fn workspace_configuration( self: Arc, + _: &dyn Fs, _: &Arc, _: Arc, _cx: &mut AsyncAppContext, @@ -1854,6 +1857,7 @@ impl LspAdapter for FakeLspAdapter { async fn initialization_options( self: Arc, + _: &dyn Fs, _: &Arc, ) -> Result> { Ok(self.initialization_options.clone()) diff --git a/crates/language_extension/Cargo.toml b/crates/language_extension/Cargo.toml index 3d1e4d0a64d240f336a83f334e5650287dc93874..81e0f96ef226236154b990f1a7efc0c534eab0eb 100644 --- a/crates/language_extension/Cargo.toml +++ b/crates/language_extension/Cargo.toml @@ -17,6 +17,7 @@ async-trait.workspace = true collections.workspace = true extension.workspace = true futures.workspace = true +fs.workspace = true gpui.workspace = true language.workspace = true lsp.workspace = true diff --git a/crates/language_extension/src/extension_lsp_adapter.rs b/crates/language_extension/src/extension_lsp_adapter.rs index 3286e09e2d6ff621bf27978d09c00ff50691cd34..ec9ea1e0e5f028ef1fccaeed383b68231952f174 100644 --- a/crates/language_extension/src/extension_lsp_adapter.rs +++ b/crates/language_extension/src/extension_lsp_adapter.rs @@ -8,6 +8,7 @@ use anyhow::{Context, Result}; use async_trait::async_trait; use collections::HashMap; use extension::{Extension, ExtensionLanguageServerProxy, WorktreeDelegate}; +use fs::Fs; use futures::{Future, FutureExt}; use gpui::AsyncAppContext; use language::{ @@ -224,6 +225,7 @@ impl LspAdapter for ExtensionLspAdapter { async fn initialization_options( self: Arc, + _: &dyn Fs, delegate: &Arc, ) -> Result> { let delegate = Arc::new(WorktreeDelegateAdapter(delegate.clone())) as _; @@ -246,6 +248,7 @@ impl LspAdapter for ExtensionLspAdapter { async fn workspace_configuration( self: Arc, + _: &dyn Fs, delegate: &Arc, _: Arc, _cx: &mut AsyncAppContext, diff --git a/crates/languages/src/css.rs b/crates/languages/src/css.rs index 148f6acced679fcb7f8d25cac741c47c559690d7..50e34cea40b572025362d8da7a4d3a9495877705 100644 --- a/crates/languages/src/css.rs +++ b/crates/languages/src/css.rs @@ -4,6 +4,7 @@ use futures::StreamExt; use language::{LspAdapter, LspAdapterDelegate}; use lsp::{LanguageServerBinary, LanguageServerName}; use node_runtime::NodeRuntime; +use project::Fs; use serde_json::json; use smol::fs; use std::{ @@ -107,6 +108,7 @@ impl LspAdapter for CssLspAdapter { async fn initialization_options( self: Arc, + _: &dyn Fs, _: &Arc, ) -> Result> { Ok(Some(json!({ diff --git a/crates/languages/src/go.rs b/crates/languages/src/go.rs index d56c720eb0ec3a93ab2a1237e06284913698016e..ca17f13e26ce838c00687692b1e10c701f6e2e3b 100644 --- a/crates/languages/src/go.rs +++ b/crates/languages/src/go.rs @@ -6,6 +6,7 @@ use gpui::{AppContext, AsyncAppContext, Task}; use http_client::github::latest_github_release; pub use language::*; use lsp::{LanguageServerBinary, LanguageServerName}; +use project::Fs; use regex::Regex; use serde_json::json; use smol::fs; @@ -197,6 +198,7 @@ impl super::LspAdapter for GoLspAdapter { async fn initialization_options( self: Arc, + _: &dyn Fs, _: &Arc, ) -> Result> { Ok(Some(json!({ diff --git a/crates/languages/src/json.rs b/crates/languages/src/json.rs index a783195db32bbdd4335e9420f879ffb10fb9926f..95aefd405aff2b98c6a13c37f1d291495f474631 100644 --- a/crates/languages/src/json.rs +++ b/crates/languages/src/json.rs @@ -9,7 +9,7 @@ use http_client::github::{latest_github_release, GitHubLspBinaryVersion}; use language::{LanguageRegistry, LanguageToolchainStore, LspAdapter, LspAdapterDelegate}; use lsp::{LanguageServerBinary, LanguageServerName}; use node_runtime::NodeRuntime; -use project::{lsp_store::language_server_settings, ContextProviderWithTasks}; +use project::{lsp_store::language_server_settings, ContextProviderWithTasks, Fs}; use serde_json::{json, Value}; use settings::{KeymapFile, SettingsJsonSchemaParams, SettingsStore}; use smol::{ @@ -208,6 +208,7 @@ impl LspAdapter for JsonLspAdapter { async fn initialization_options( self: Arc, + _: &dyn Fs, _: &Arc, ) -> Result> { Ok(Some(json!({ @@ -217,6 +218,7 @@ impl LspAdapter for JsonLspAdapter { async fn workspace_configuration( self: Arc, + _: &dyn Fs, delegate: &Arc, _: Arc, cx: &mut AsyncAppContext, diff --git a/crates/languages/src/python.rs b/crates/languages/src/python.rs index be9cef8651479a0fe524d241d2b7429d7c8c3b73..a3cf24cf57dae808dab7d4a7275288904f343fd0 100644 --- a/crates/languages/src/python.rs +++ b/crates/languages/src/python.rs @@ -18,6 +18,7 @@ use pet_core::os_environment::Environment; use pet_core::python_environment::PythonEnvironmentKind; use pet_core::Configuration; use project::lsp_store::language_server_settings; +use project::Fs; use serde_json::{json, Value}; use smol::lock::OnceCell; use std::cmp::Ordering; @@ -250,6 +251,7 @@ impl LspAdapter for PythonLspAdapter { async fn workspace_configuration( self: Arc, + _: &dyn Fs, adapter: &Arc, toolchains: Arc, cx: &mut AsyncAppContext, @@ -931,6 +933,7 @@ impl LspAdapter for PyLspAdapter { async fn workspace_configuration( self: Arc, + _: &dyn Fs, adapter: &Arc, toolchains: Arc, cx: &mut AsyncAppContext, diff --git a/crates/languages/src/tailwind.rs b/crates/languages/src/tailwind.rs index 02c3dbefc2c1cae605b8a78ef6e51a6527203f8f..328cf51279e8464866b0572a366658d00d389a1f 100644 --- a/crates/languages/src/tailwind.rs +++ b/crates/languages/src/tailwind.rs @@ -6,7 +6,7 @@ use gpui::AsyncAppContext; use language::{LanguageToolchainStore, LspAdapter, LspAdapterDelegate}; use lsp::{LanguageServerBinary, LanguageServerName}; use node_runtime::NodeRuntime; -use project::lsp_store::language_server_settings; +use project::{lsp_store::language_server_settings, Fs}; use serde_json::{json, Value}; use smol::fs; use std::{ @@ -116,6 +116,7 @@ impl LspAdapter for TailwindLspAdapter { async fn initialization_options( self: Arc, + _: &dyn Fs, _: &Arc, ) -> Result> { Ok(Some(json!({ @@ -131,6 +132,7 @@ impl LspAdapter for TailwindLspAdapter { async fn workspace_configuration( self: Arc, + _: &dyn Fs, delegate: &Arc, _: Arc, cx: &mut AsyncAppContext, diff --git a/crates/languages/src/typescript.rs b/crates/languages/src/typescript.rs index edfdbf5f55a28c833469fd92a6399cf130669e6c..b14f3dc2379ef80a96354c406b836aca13631f62 100644 --- a/crates/languages/src/typescript.rs +++ b/crates/languages/src/typescript.rs @@ -8,8 +8,8 @@ use http_client::github::{build_asset_url, AssetKind, GitHubLspBinaryVersion}; use language::{LanguageToolchainStore, LspAdapter, LspAdapterDelegate}; use lsp::{CodeActionKind, LanguageServerBinary, LanguageServerName}; use node_runtime::NodeRuntime; -use project::lsp_store::language_server_settings; use project::ContextProviderWithTasks; +use project::{lsp_store::language_server_settings, Fs}; use serde_json::{json, Value}; use smol::{fs, io::BufReader, stream::StreamExt}; use std::{ @@ -77,16 +77,25 @@ impl TypeScriptLspAdapter { pub fn new(node: NodeRuntime) -> Self { TypeScriptLspAdapter { node } } - async fn tsdk_path(adapter: &Arc) -> &'static str { + async fn tsdk_path(fs: &dyn Fs, adapter: &Arc) -> Option<&'static str> { let is_yarn = adapter .read_text_file(PathBuf::from(".yarn/sdks/typescript/lib/typescript.js")) .await .is_ok(); - if is_yarn { + let tsdk_path = if is_yarn { ".yarn/sdks/typescript/lib" } else { "node_modules/typescript/lib" + }; + + if fs + .is_dir(&adapter.worktree_root_path().join(tsdk_path)) + .await + { + Some(tsdk_path) + } else { + None } } } @@ -233,9 +242,10 @@ impl LspAdapter for TypeScriptLspAdapter { async fn initialization_options( self: Arc, + fs: &dyn Fs, adapter: &Arc, ) -> Result> { - let tsdk_path = Self::tsdk_path(adapter).await; + let tsdk_path = Self::tsdk_path(fs, adapter).await; Ok(Some(json!({ "provideFormatter": true, "hostInfo": "zed", @@ -257,6 +267,7 @@ impl LspAdapter for TypeScriptLspAdapter { async fn workspace_configuration( self: Arc, + _: &dyn Fs, delegate: &Arc, _: Arc, cx: &mut AsyncAppContext, @@ -353,6 +364,7 @@ impl LspAdapter for EsLintLspAdapter { async fn workspace_configuration( self: Arc, + _: &dyn Fs, delegate: &Arc, _: Arc, cx: &mut AsyncAppContext, diff --git a/crates/languages/src/vtsls.rs b/crates/languages/src/vtsls.rs index 22718e410c221e51f1eafd5361853a70401b9d4d..33dea775409a3e800d9e1389765f3494a2ca6e7c 100644 --- a/crates/languages/src/vtsls.rs +++ b/crates/languages/src/vtsls.rs @@ -5,7 +5,7 @@ use gpui::AsyncAppContext; use language::{LanguageToolchainStore, LspAdapter, LspAdapterDelegate}; use lsp::{CodeActionKind, LanguageServerBinary, LanguageServerName}; use node_runtime::NodeRuntime; -use project::lsp_store::language_server_settings; +use project::{lsp_store::language_server_settings, Fs}; use serde_json::Value; use std::{ any::Any, @@ -34,16 +34,25 @@ impl VtslsLspAdapter { VtslsLspAdapter { node } } - async fn tsdk_path(adapter: &Arc) -> &'static str { + async fn tsdk_path(fs: &dyn Fs, adapter: &Arc) -> Option<&'static str> { let is_yarn = adapter .read_text_file(PathBuf::from(".yarn/sdks/typescript/lib/typescript.js")) .await .is_ok(); - if is_yarn { + let tsdk_path = if is_yarn { ".yarn/sdks/typescript/lib" } else { Self::TYPESCRIPT_TSDK_PATH + }; + + if fs + .is_dir(&adapter.worktree_root_path().join(tsdk_path)) + .await + { + Some(tsdk_path) + } else { + None } } } @@ -196,11 +205,12 @@ impl LspAdapter for VtslsLspAdapter { async fn workspace_configuration( self: Arc, + fs: &dyn Fs, delegate: &Arc, _: Arc, cx: &mut AsyncAppContext, ) -> Result { - let tsdk_path = Self::tsdk_path(delegate).await; + let tsdk_path = Self::tsdk_path(fs, delegate).await; let config = serde_json::json!({ "tsdk": tsdk_path, "suggest": { diff --git a/crates/languages/src/yaml.rs b/crates/languages/src/yaml.rs index 12878b8f936031cc098e421d61457c8e086503a7..91f6e48aaef8aaf10f06f102c37e2d70e9e88508 100644 --- a/crates/languages/src/yaml.rs +++ b/crates/languages/src/yaml.rs @@ -7,7 +7,7 @@ use language::{ }; use lsp::{LanguageServerBinary, LanguageServerName}; use node_runtime::NodeRuntime; -use project::lsp_store::language_server_settings; +use project::{lsp_store::language_server_settings, Fs}; use serde_json::Value; use settings::{Settings, SettingsLocation}; use smol::fs; @@ -128,6 +128,7 @@ impl LspAdapter for YamlLspAdapter { async fn workspace_configuration( self: Arc, + _: &dyn Fs, delegate: &Arc, _: Arc, cx: &mut AsyncAppContext, diff --git a/crates/project/src/lsp_store.rs b/crates/project/src/lsp_store.rs index f71b8cfd8d0c8880ded9576019510b9deb9af60a..dba5312f63cc9fd4868c19742eca5a9ded003314 100644 --- a/crates/project/src/lsp_store.rs +++ b/crates/project/src/lsp_store.rs @@ -245,7 +245,7 @@ impl LocalLspStore { let language = language.clone(); let key = key.clone(); let adapter = adapter.clone(); - + let fs = self.fs.clone(); cx.spawn(move |this, mut cx| async move { let result = { let delegate = delegate.clone(); @@ -261,13 +261,18 @@ impl LocalLspStore { let workspace_config = adapter .adapter .clone() - .workspace_configuration(&delegate, toolchains.clone(), &mut cx) + .workspace_configuration( + fs.as_ref(), + &delegate, + toolchains.clone(), + &mut cx, + ) .await?; let mut initialization_options = adapter .adapter .clone() - .initialization_options(&(delegate)) + .initialization_options(fs.as_ref(), &(delegate)) .await?; match (&mut initialization_options, override_options) { @@ -284,7 +289,13 @@ impl LocalLspStore { adapter.adapter.prepare_initialize_params(params) })??; - Self::setup_lsp_messages(this.clone(), &language_server, delegate, adapter); + Self::setup_lsp_messages( + this.clone(), + fs, + &language_server, + delegate, + adapter, + ); let did_change_configuration_params = Arc::new(lsp::DidChangeConfigurationParams { @@ -496,6 +507,7 @@ impl LocalLspStore { fn setup_lsp_messages( this: WeakModel, + fs: Arc, language_server: &LanguageServer, delegate: Arc, adapter: Arc, @@ -529,15 +541,17 @@ impl LocalLspStore { let adapter = adapter.adapter.clone(); let delegate = delegate.clone(); let this = this.clone(); + let fs = fs.clone(); move |params, mut cx| { let adapter = adapter.clone(); let delegate = delegate.clone(); let this = this.clone(); + let fs = fs.clone(); async move { let toolchains = this.update(&mut cx, |this, cx| this.toolchain_store(cx))?; let workspace_config = adapter - .workspace_configuration(&delegate, toolchains, &mut cx) + .workspace_configuration(fs.as_ref(), &delegate, toolchains, &mut cx) .await?; Ok(params .items @@ -2954,7 +2968,10 @@ impl LspStore { let _maintain_workspace_config = { let (sender, receiver) = watch::channel(); - (Self::maintain_workspace_config(receiver, cx), sender) + ( + Self::maintain_workspace_config(fs.clone(), receiver, cx), + sender, + ) }; Self { mode: LspStoreMode::Local(LocalLspStore { @@ -3017,6 +3034,7 @@ impl LspStore { }) } + #[allow(clippy::too_many_arguments)] pub(super) fn new_remote( buffer_store: Model, worktree_store: Model, @@ -3024,6 +3042,7 @@ impl LspStore { languages: Arc, upstream_client: AnyProtoClient, project_id: u64, + fs: Arc, cx: &mut ModelContext, ) -> Self { cx.subscribe(&buffer_store, Self::on_buffer_store_event) @@ -3032,7 +3051,7 @@ impl LspStore { .detach(); let _maintain_workspace_config = { let (sender, receiver) = watch::channel(); - (Self::maintain_workspace_config(receiver, cx), sender) + (Self::maintain_workspace_config(fs, receiver, cx), sender) }; Self { mode: LspStoreMode::Remote(RemoteLspStore { @@ -5125,6 +5144,7 @@ impl LspStore { pub(crate) async fn refresh_workspace_configurations( this: &WeakModel, + fs: Arc, mut cx: AsyncAppContext, ) { maybe!(async move { @@ -5171,7 +5191,12 @@ impl LspStore { .ok()?; for (adapter, server, delegate) in servers { let settings = adapter - .workspace_configuration(&delegate, toolchain_store.clone(), &mut cx) + .workspace_configuration( + fs.as_ref(), + &delegate, + toolchain_store.clone(), + &mut cx, + ) .await .ok()?; @@ -5194,6 +5219,7 @@ impl LspStore { } } fn maintain_workspace_config( + fs: Arc, external_refresh_requests: watch::Receiver<()>, cx: &mut ModelContext, ) -> Task> { @@ -5208,7 +5234,7 @@ impl LspStore { futures::stream::select(settings_changed_rx, external_refresh_requests); cx.spawn(move |this, cx| async move { while let Some(()) = joint_future.next().await { - Self::refresh_workspace_configurations(&this, cx.clone()).await; + Self::refresh_workspace_configurations(&this, fs.clone(), cx.clone()).await; } drop(settings_observation); @@ -8370,6 +8396,7 @@ impl LspAdapter for SshLspAdapter { async fn initialization_options( self: Arc, + _: &dyn Fs, _: &Arc, ) -> Result> { let Some(options) = &self.initialization_options else { diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index a4986dbc4cd8485cbfcf54108b2080574da34256..910df074feed355402bfb15cd26780173e93593c 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -800,6 +800,7 @@ impl Project { languages.clone(), ssh_proto.clone(), SSH_PROJECT_ID, + fs.clone(), cx, ) }); @@ -972,6 +973,7 @@ impl Project { languages.clone(), client.clone().into(), remote_id, + fs.clone(), cx, ); lsp_store.set_language_server_statuses_from_proto(response.payload.language_servers);