diff --git a/Cargo.lock b/Cargo.lock index d8f8939b5d..6c12bd886d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8653,7 +8653,6 @@ dependencies = [ "extension", "gpui", "language", - "lsp", "paths", "project", "schemars", diff --git a/crates/json_schema_store/Cargo.toml b/crates/json_schema_store/Cargo.toml index 2225b7c5aa..f973fe2ebf 100644 --- a/crates/json_schema_store/Cargo.toml +++ b/crates/json_schema_store/Cargo.toml @@ -20,7 +20,6 @@ dap.workspace = true extension.workspace = true gpui.workspace = true language.workspace = true -lsp.workspace = true paths.workspace = true project.workspace = true schemars.workspace = true @@ -31,11 +30,3 @@ snippet_provider.workspace = true task.workspace = true theme.workspace = true util.workspace = true - - - -# Uncomment other workspace dependencies as needed -# assistant.workspace = true -# client.workspace = true -# project.workspace = true -# settings.workspace = true diff --git a/crates/json_schema_store/src/json_schema_store.rs b/crates/json_schema_store/src/json_schema_store.rs index da576065dd..ca3fb20f01 100644 --- a/crates/json_schema_store/src/json_schema_store.rs +++ b/crates/json_schema_store/src/json_schema_store.rs @@ -3,8 +3,7 @@ use std::{str::FromStr, sync::Arc}; use anyhow::{Context as _, Result}; use gpui::{App, AsyncApp, BorrowAppContext as _, Entity, Task, WeakEntity}; -use language::{LanguageRegistry, language_settings::all_language_settings}; -use lsp::LanguageServerBinaryOptions; +use language::{LanguageRegistry, LspAdapterDelegate, language_settings::all_language_settings}; use project::{LspStore, lsp_store::LocalLspAdapterDelegate}; use settings::LSP_SETTINGS_SCHEMA_URL_PREFIX; use util::schemars::{AllowTrailingCommas, DefaultDenyUnknownFields}; @@ -123,18 +122,18 @@ pub async fn resolve_schema_request_inner( .find(|adapter| adapter.name().as_ref() as &str == lsp_name) .with_context(|| format!("LSP adapter not found: {}", lsp_name))?; - let delegate = cx + let delegate: Arc = cx .update(|inner_cx| { - lsp_store.update(inner_cx, |lsp_store, inner_cx| { + lsp_store.update(inner_cx, |lsp_store, cx| { let Some(local) = lsp_store.as_local() else { return None; }; - let Some(worktree) = local.worktree_store.read(inner_cx).worktrees().next() + let Some(worktree) = local.worktree_store.read(cx).worktrees().next() else { return None; }; Some(LocalLspAdapterDelegate::from_local_lsp( - local, &worktree, inner_cx, + local, &worktree, cx, )) }) })? @@ -143,36 +142,8 @@ pub async fn resolve_schema_request_inner( "either LSP store is not in local mode or no worktree is available" ))?; - let adapter_for_schema = adapter.clone(); - - let binary = adapter - .get_language_server_command( - delegate, - None, - LanguageServerBinaryOptions { - allow_path_lookup: true, - allow_binary_download: false, - pre_release: false, - }, - cx, - ) - .await - .await - .0 - .with_context(|| { - format!( - concat!( - "Failed to find language server {} ", - "to generate initialization params schema" - ), - lsp_name - ) - })?; - - adapter_for_schema - .adapter - .clone() - .initialization_options_schema(&binary) + adapter + .initialization_options_schema(&delegate, cx) .await .unwrap_or_else(|| { serde_json::json!({ diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index 8493d91ec4..6881779097 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -331,6 +331,21 @@ impl CachedLspAdapter { .unwrap_or_else(|| language_name.lsp_id()) } + pub async fn initialization_options_schema( + &self, + delegate: &Arc, + cx: &mut AsyncApp, + ) -> Option { + self.adapter + .clone() + .initialization_options_schema( + delegate, + self.cached_binary.clone().lock_owned().await, + cx, + ) + .await + } + pub fn process_prompt_response(&self, context: &PromptResponseContext, cx: &mut AsyncApp) { self.adapter.process_prompt_response(context, cx) } @@ -464,7 +479,9 @@ pub trait LspAdapter: 'static + Send + Sync + DynLspInstaller { /// Returns the JSON schema of the initialization_options for the language server. async fn initialization_options_schema( self: Arc, - _language_server_binary: &LanguageServerBinary, + _delegate: &Arc, + _cached_binary: OwnedMutexGuard>, + _cx: &mut AsyncApp, ) -> Option { None } @@ -591,6 +608,7 @@ pub trait DynLspInstaller { pre_release: bool, cx: &mut AsyncApp, ) -> Result; + fn get_language_server_command( self: Arc, delegate: Arc, @@ -686,6 +704,12 @@ where return (Ok(binary), None); } + if let Some((pre_release, cached_binary)) = cached_binary_deref + && *pre_release == binary_options.pre_release + { + return (Ok(cached_binary.clone()), None); + } + if !binary_options.allow_binary_download { return ( Err(anyhow::anyhow!("downloading language servers disabled")), @@ -693,12 +717,6 @@ where ); } - if let Some((pre_release, cached_binary)) = cached_binary_deref - && *pre_release == binary_options.pre_release - { - return (Ok(cached_binary.clone()), None); - } - let Some(container_dir) = delegate.language_server_download_dir(&self.name()).await else { return ( diff --git a/crates/languages/src/python.rs b/crates/languages/src/python.rs index 40825e30cb..23a067a623 100644 --- a/crates/languages/src/python.rs +++ b/crates/languages/src/python.rs @@ -2,16 +2,17 @@ use anyhow::{Context as _, ensure}; use anyhow::{Result, anyhow}; use async_trait::async_trait; use collections::HashMap; +use futures::lock::OwnedMutexGuard; use futures::{AsyncBufReadExt, StreamExt as _}; use gpui::{App, AsyncApp, SharedString, Task}; use http_client::github::{AssetKind, GitHubLspBinaryVersion, latest_github_release}; use language::language_settings::language_settings; -use language::{ContextLocation, LanguageToolchainStore, LspInstaller}; +use language::{ContextLocation, DynLspInstaller, LanguageToolchainStore, LspInstaller}; use language::{ContextProvider, LspAdapter, LspAdapterDelegate}; use language::{LanguageName, ManifestName, ManifestProvider, ManifestQuery}; use language::{Toolchain, ToolchainList, ToolchainLister, ToolchainMetadata}; -use lsp::LanguageServerName; use lsp::{LanguageServerBinary, Uri}; +use lsp::{LanguageServerBinaryOptions, LanguageServerName}; use node_runtime::{NodeRuntime, VersionStrategy}; use pet_core::Configuration; use pet_core::os_environment::Environment; @@ -2342,9 +2343,27 @@ impl LspAdapter for RuffLspAdapter { async fn initialization_options_schema( self: Arc, - language_server_binary: &LanguageServerBinary, + delegate: &Arc, + cached_binary: OwnedMutexGuard>, + cx: &mut AsyncApp, ) -> Option { - let mut command = util::command::new_smol_command(&language_server_binary.path); + let binary = self + .get_language_server_command( + delegate.clone(), + None, + LanguageServerBinaryOptions { + allow_path_lookup: true, + allow_binary_download: false, + pre_release: false, + }, + cached_binary, + cx.clone(), + ) + .await + .0 + .ok()?; + + let mut command = util::command::new_smol_command(&binary.path); command .args(&["config", "--output-format", "json"]) .stdout(Stdio::piped()) diff --git a/crates/languages/src/rust.rs b/crates/languages/src/rust.rs index d2b890a1db..f91679db85 100644 --- a/crates/languages/src/rust.rs +++ b/crates/languages/src/rust.rs @@ -2,12 +2,13 @@ use anyhow::{Context as _, Result}; use async_trait::async_trait; use collections::HashMap; use futures::StreamExt; +use futures::lock::OwnedMutexGuard; use gpui::{App, AppContext, AsyncApp, SharedString, Task}; use http_client::github::AssetKind; use http_client::github::{GitHubLspBinaryVersion, latest_github_release}; use http_client::github_download::{GithubBinaryMetadata, download_server_binary}; pub use language::*; -use lsp::{InitializeParams, LanguageServerBinary}; +use lsp::{InitializeParams, LanguageServerBinary, LanguageServerBinaryOptions}; use project::lsp_store::rust_analyzer_ext::CARGO_DIAGNOSTICS_SOURCE_NAME; use project::project_settings::ProjectSettings; use regex::Regex; @@ -513,9 +514,27 @@ impl LspAdapter for RustLspAdapter { async fn initialization_options_schema( self: Arc, - language_server_binary: &LanguageServerBinary, + delegate: &Arc, + cached_binary: OwnedMutexGuard>, + cx: &mut AsyncApp, ) -> Option { - let mut command = util::command::new_smol_command(&language_server_binary.path); + let binary = self + .get_language_server_command( + delegate.clone(), + None, + LanguageServerBinaryOptions { + allow_path_lookup: true, + allow_binary_download: false, + pre_release: false, + }, + cached_binary, + cx.clone(), + ) + .await + .0 + .ok()?; + + let mut command = util::command::new_smol_command(&binary.path); command .arg("--print-config-schema") .stdout(Stdio::piped())