From a97ab5eb3df2307b31b0acb7997e8f6da1e53356 Mon Sep 17 00:00:00 2001 From: Thorsten Ball Date: Mon, 11 Nov 2024 10:18:38 +0100 Subject: [PATCH] language servers: Fix wrong language server name (#20428) This fixes the issue of multiple language servers showing up as `node` in the language server logs dropdown. It does this by changing `language_server.name()` to return the adapter's name, not the binary name, and changing types to make sure that we always use this. Release Notes: - Fixed language server names showing up only as `"node"` --------- Co-authored-by: Sam Rose Co-authored-by: Bennet --- Cargo.lock | 2 + crates/activity_indicator/Cargo.toml | 1 + .../src/activity_indicator.rs | 5 +- crates/collab/src/tests/integration_tests.rs | 5 +- crates/copilot/src/copilot.rs | 4 +- crates/editor/src/editor.rs | 6 +- crates/extension/src/extension_manifest.rs | 3 +- crates/extension_host/src/extension_host.rs | 10 +-- .../src/extension_lsp_adapter.rs | 5 +- crates/extension_host/src/wasm_host/wit.rs | 3 +- .../src/wasm_host/wit/since_v0_0_1.rs | 2 +- .../src/wasm_host/wit/since_v0_1_0.rs | 6 +- .../src/wasm_host/wit/since_v0_2_0.rs | 8 +- crates/extensions_ui/Cargo.toml | 1 + .../src/extension_registration_hooks.rs | 4 +- .../extensions_ui/src/extension_store_test.rs | 3 +- crates/language/src/language.rs | 53 +---------- crates/language_tools/src/lsp_log.rs | 6 +- crates/language_tools/src/lsp_log_tests.rs | 5 +- crates/languages/src/c.rs | 2 +- crates/languages/src/css.rs | 4 +- crates/languages/src/go.rs | 2 +- crates/languages/src/json.rs | 6 +- crates/languages/src/lib.rs | 1 + crates/languages/src/python.rs | 3 +- crates/languages/src/rust.rs | 2 +- crates/languages/src/tailwind.rs | 4 +- crates/languages/src/typescript.rs | 4 +- crates/languages/src/vtsls.rs | 4 +- crates/languages/src/yaml.rs | 5 +- crates/lsp/Cargo.toml | 1 + crates/lsp/src/lsp.rs | 90 ++++++++++++++++--- crates/prettier/src/prettier.rs | 15 ++-- crates/project/src/lsp_store.rs | 17 ++-- crates/project/src/prettier_store.rs | 4 +- crates/project/src/project.rs | 6 +- crates/project/src/project_settings.rs | 2 +- crates/project/src/project_tests.rs | 14 ++- .../remote_server/src/remote_editing_tests.rs | 5 +- 39 files changed, 172 insertions(+), 151 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 93dcbd050e515f66f6ca66669e1596f271a139d6..7aecdd8f33795b797073ba31a308f5a39b0e3613 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,6 +13,7 @@ dependencies = [ "futures 0.3.30", "gpui", "language", + "lsp", "project", "smallvec", "ui", @@ -6898,6 +6899,7 @@ dependencies = [ "parking_lot", "postage", "release_channel", + "schemars", "serde", "serde_json", "smol", diff --git a/crates/activity_indicator/Cargo.toml b/crates/activity_indicator/Cargo.toml index 6f026d7662ba055d2cf6863fad8c85eed5c93c8e..54c2f498445a1efb417f7dec465ccb9577b83b72 100644 --- a/crates/activity_indicator/Cargo.toml +++ b/crates/activity_indicator/Cargo.toml @@ -20,6 +20,7 @@ extension_host.workspace = true futures.workspace = true gpui.workspace = true language.workspace = true +lsp.workspace = true project.workspace = true smallvec.workspace = true ui.workspace = true diff --git a/crates/activity_indicator/src/activity_indicator.rs b/crates/activity_indicator/src/activity_indicator.rs index c9fc51ff1e022d03a265dc44a53eb81d9759e395..21f7bff6d3976183cc0338cc1895113b6c064d90 100644 --- a/crates/activity_indicator/src/activity_indicator.rs +++ b/crates/activity_indicator/src/activity_indicator.rs @@ -7,9 +7,8 @@ use gpui::{ InteractiveElement as _, Model, ParentElement as _, Render, SharedString, StatefulInteractiveElement, Styled, Transformation, View, ViewContext, VisualContext as _, }; -use language::{ - LanguageRegistry, LanguageServerBinaryStatus, LanguageServerId, LanguageServerName, -}; +use language::{LanguageRegistry, LanguageServerBinaryStatus, LanguageServerId}; +use lsp::LanguageServerName; use project::{EnvironmentErrorMessage, LanguageServerProgress, Project, WorktreeId}; use smallvec::SmallVec; use std::{cmp::Reverse, fmt::Write, sync::Arc, time::Duration}; diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs index 8c819d6da755a3eb9c00220f68e018ecd2a03a43..751469a7001f8a658b9eb8fd955529eb28515b86 100644 --- a/crates/collab/src/tests/integration_tests.rs +++ b/crates/collab/src/tests/integration_tests.rs @@ -5130,11 +5130,10 @@ async fn test_lsp_hover( }); let new_server_name = new_server.server.name(); assert!( - !servers_with_hover_requests.contains_key(new_server_name), + !servers_with_hover_requests.contains_key(&new_server_name), "Unexpected: initialized server with the same name twice. Name: `{new_server_name}`" ); - let new_server_name = new_server_name.to_string(); - match new_server_name.as_str() { + match new_server_name.as_ref() { "CrabLang-ls" => { servers_with_hover_requests.insert( new_server_name.clone(), diff --git a/crates/copilot/src/copilot.rs b/crates/copilot/src/copilot.rs index 15b6bf6083bd22e651cea8cfacb88de44cc74bc4..3004c4e985f1aef9f5a51eb8dc89033f379286e3 100644 --- a/crates/copilot/src/copilot.rs +++ b/crates/copilot/src/copilot.rs @@ -21,7 +21,7 @@ use language::{ point_from_lsp, point_to_lsp, Anchor, Bias, Buffer, BufferSnapshot, Language, PointUtf16, ToPointUtf16, }; -use lsp::{LanguageServer, LanguageServerBinary, LanguageServerId}; +use lsp::{LanguageServer, LanguageServerBinary, LanguageServerId, LanguageServerName}; use node_runtime::NodeRuntime; use parking_lot::Mutex; use request::StatusNotification; @@ -446,9 +446,11 @@ impl Copilot { Path::new("/") }; + let server_name = LanguageServerName("copilot".into()); let server = LanguageServer::new( Arc::new(Mutex::new(None)), new_server_id, + server_name, binary, root_path, None, diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 3fd0acd75382dfeaadff2c8f53c231a2c8ab6bfa..ea3c1ee7a6b70e85ceb8fe6bab415ab7990885fb 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -96,9 +96,7 @@ use language::{ CursorShape, Diagnostic, Documentation, IndentKind, IndentSize, Language, OffsetRangeExt, Point, Selection, SelectionGoal, TransactionId, }; -use language::{ - point_to_lsp, BufferRow, CharClassifier, LanguageServerName, Runnable, RunnableRange, -}; +use language::{point_to_lsp, BufferRow, CharClassifier, Runnable, RunnableRange}; use linked_editing_ranges::refresh_linked_ranges; pub use proposed_changes_editor::{ ProposedChangeLocation, ProposedChangesEditor, ProposedChangesEditorToolbar, @@ -111,7 +109,7 @@ use hover_links::{find_file, HoverLink, HoveredLinkState, InlayHighlight}; pub use lsp::CompletionContext; use lsp::{ CompletionItemKind, CompletionTriggerKind, DiagnosticSeverity, InsertTextFormat, - LanguageServerId, + LanguageServerId, LanguageServerName, }; use mouse_context_menu::MouseContextMenu; use movement::TextLayoutDetails; diff --git a/crates/extension/src/extension_manifest.rs b/crates/extension/src/extension_manifest.rs index 77be30c6c007a387bae52e8b181809032cc59f0f..53fe935c1b0d23ce50b386f35e13a0d134a3d695 100644 --- a/crates/extension/src/extension_manifest.rs +++ b/crates/extension/src/extension_manifest.rs @@ -1,7 +1,8 @@ use anyhow::{anyhow, Context, Result}; use collections::{BTreeMap, HashMap}; use fs::Fs; -use language::{LanguageName, LanguageServerName}; +use language::LanguageName; +use lsp::LanguageServerName; use semantic_version::SemanticVersion; use serde::{Deserialize, Serialize}; use std::{ diff --git a/crates/extension_host/src/extension_host.rs b/crates/extension_host/src/extension_host.rs index c10a435e2daebcd49e3f878d7dd9e241f933b19f..9700187f8ce753dce3a5f5c444edde815aa2aa85 100644 --- a/crates/extension_host/src/extension_host.rs +++ b/crates/extension_host/src/extension_host.rs @@ -28,6 +28,7 @@ use language::{ LanguageConfig, LanguageMatcher, LanguageName, LanguageQueries, LoadedLanguage, QUERY_FILENAME_PREFIXES, }; +use lsp::LanguageServerName; use node_runtime::NodeRuntime; use project::ContextProviderWithTasks; use release_channel::ReleaseChannel; @@ -121,12 +122,7 @@ pub trait ExtensionRegistrationHooks: Send + Sync + 'static { fn register_lsp_adapter(&self, _language: LanguageName, _adapter: ExtensionLspAdapter) {} - fn remove_lsp_adapter( - &self, - _language: &LanguageName, - _server_name: &language::LanguageServerName, - ) { - } + fn remove_lsp_adapter(&self, _language: &LanguageName, _server_name: &LanguageServerName) {} fn register_wasm_grammars(&self, _grammars: Vec<(Arc, PathBuf)>) {} @@ -167,7 +163,7 @@ pub trait ExtensionRegistrationHooks: Send + Sync + 'static { fn update_lsp_status( &self, - _server_name: language::LanguageServerName, + _server_name: lsp::LanguageServerName, _status: language::LanguageServerBinaryStatus, ) { } diff --git a/crates/extension_host/src/extension_lsp_adapter.rs b/crates/extension_host/src/extension_lsp_adapter.rs index 9d8cc90c1c825b5696c8efbf6a540bc1f1779cec..b15fa5adc404e4127235080b94147ac0c7ba7455 100644 --- a/crates/extension_host/src/extension_lsp_adapter.rs +++ b/crates/extension_host/src/extension_lsp_adapter.rs @@ -8,10 +8,9 @@ use collections::HashMap; use futures::{Future, FutureExt}; use gpui::AsyncAppContext; use language::{ - CodeLabel, HighlightId, Language, LanguageServerName, LanguageToolchainStore, LspAdapter, - LspAdapterDelegate, + CodeLabel, HighlightId, Language, LanguageToolchainStore, LspAdapter, LspAdapterDelegate, }; -use lsp::{CodeActionKind, LanguageServerBinary, LanguageServerBinaryOptions}; +use lsp::{CodeActionKind, LanguageServerBinary, LanguageServerBinaryOptions, LanguageServerName}; use serde::Serialize; use serde_json::Value; use std::ops::Range; diff --git a/crates/extension_host/src/wasm_host/wit.rs b/crates/extension_host/src/wasm_host/wit.rs index ae85c35e9416573e9b9f084cb5419bfd1c8c19e9..13a7ab042f44bc8c1e75b6ceb2b965981d2b232e 100644 --- a/crates/extension_host/src/wasm_host/wit.rs +++ b/crates/extension_host/src/wasm_host/wit.rs @@ -3,6 +3,7 @@ mod since_v0_0_4; mod since_v0_0_6; mod since_v0_1_0; mod since_v0_2_0; +use lsp::LanguageServerName; // use indexed_docs::IndexedDocsDatabase; use release_channel::ReleaseChannel; use since_v0_2_0 as latest; @@ -11,7 +12,7 @@ use crate::DocsDatabase; use super::{wasm_engine, WasmState}; use anyhow::{anyhow, Context, Result}; -use language::{LanguageServerName, LspAdapterDelegate}; +use language::LspAdapterDelegate; use semantic_version::SemanticVersion; use std::{ops::RangeInclusive, sync::Arc}; use wasmtime::{ diff --git a/crates/extension_host/src/wasm_host/wit/since_v0_0_1.rs b/crates/extension_host/src/wasm_host/wit/since_v0_0_1.rs index e3e951a4e104adc794c5f05d7d95010462b601bc..3493d2a74dc3528b07f5ec50e9b0a51bde900f5b 100644 --- a/crates/extension_host/src/wasm_host/wit/since_v0_0_1.rs +++ b/crates/extension_host/src/wasm_host/wit/since_v0_0_1.rs @@ -149,7 +149,7 @@ impl ExtensionImports for WasmState { self.host .registration_hooks - .update_lsp_status(language::LanguageServerName(server_name.into()), status); + .update_lsp_status(lsp::LanguageServerName(server_name.into()), status); Ok(()) } diff --git a/crates/extension_host/src/wasm_host/wit/since_v0_1_0.rs b/crates/extension_host/src/wasm_host/wit/since_v0_1_0.rs index 706a8ac22d094d1e603f6cabb9ac434fa5b848a3..d8743f2c9cf9d8c52c3c91621efca07964120090 100644 --- a/crates/extension_host/src/wasm_host/wit/since_v0_1_0.rs +++ b/crates/extension_host/src/wasm_host/wit/since_v0_1_0.rs @@ -8,10 +8,10 @@ use async_tar::Archive; use async_trait::async_trait; use futures::{io::BufReader, FutureExt as _}; use futures::{lock::Mutex, AsyncReadExt}; +use language::LanguageName; use language::{ language_settings::AllLanguageSettings, LanguageServerBinaryStatus, LspAdapterDelegate, }; -use language::{LanguageName, LanguageServerName}; use project::project_settings::ProjectSettings; use semantic_version::SemanticVersion; use std::{ @@ -469,7 +469,7 @@ impl ExtensionImports for WasmState { .and_then(|key| { ProjectSettings::get(location, cx) .lsp - .get(&LanguageServerName(key.into())) + .get(&::lsp::LanguageServerName(key.into())) }) .cloned() .unwrap_or_default(); @@ -513,7 +513,7 @@ impl ExtensionImports for WasmState { self.host .registration_hooks - .update_lsp_status(language::LanguageServerName(server_name.into()), status); + .update_lsp_status(::lsp::LanguageServerName(server_name.into()), status); Ok(()) } diff --git a/crates/extension_host/src/wasm_host/wit/since_v0_2_0.rs b/crates/extension_host/src/wasm_host/wit/since_v0_2_0.rs index f920b9215f28eb852a9dbd3f400a2526eb658f82..86ae7a1f12667e8c53666a5acbe42343cdc7a399 100644 --- a/crates/extension_host/src/wasm_host/wit/since_v0_2_0.rs +++ b/crates/extension_host/src/wasm_host/wit/since_v0_2_0.rs @@ -9,9 +9,9 @@ use async_trait::async_trait; use futures::{io::BufReader, FutureExt as _}; use futures::{lock::Mutex, AsyncReadExt}; use language::{ - language_settings::AllLanguageSettings, LanguageServerBinaryStatus, LspAdapterDelegate, + language_settings::AllLanguageSettings, LanguageName, LanguageServerBinaryStatus, + LspAdapterDelegate, }; -use language::{LanguageName, LanguageServerName}; use project::project_settings::ProjectSettings; use semantic_version::SemanticVersion; use std::{ @@ -416,7 +416,7 @@ impl ExtensionImports for WasmState { .and_then(|key| { ProjectSettings::get(location, cx) .lsp - .get(&LanguageServerName::from_proto(key)) + .get(&::lsp::LanguageServerName::from_proto(key)) }) .cloned() .unwrap_or_default(); @@ -460,7 +460,7 @@ impl ExtensionImports for WasmState { self.host .registration_hooks - .update_lsp_status(language::LanguageServerName(server_name.into()), status); + .update_lsp_status(::lsp::LanguageServerName(server_name.into()), status); Ok(()) } diff --git a/crates/extensions_ui/Cargo.toml b/crates/extensions_ui/Cargo.toml index 96c62d3bfb9186e6379b54dfb2a9f574f1c5363b..a13b52b78bfa9629c2f6c285c534ba01dc3704c1 100644 --- a/crates/extensions_ui/Cargo.toml +++ b/crates/extensions_ui/Cargo.toml @@ -30,6 +30,7 @@ fuzzy.workspace = true gpui.workspace = true indexed_docs.workspace = true language.workspace = true +lsp.workspace = true num-format.workspace = true picker.workspace = true project.workspace = true diff --git a/crates/extensions_ui/src/extension_registration_hooks.rs b/crates/extensions_ui/src/extension_registration_hooks.rs index 37fe658894b264f8d45f5d59809bee5fa14d29f1..5a6ca8db06ce8bb08d72085b873f2096ae0ee3cc 100644 --- a/crates/extensions_ui/src/extension_registration_hooks.rs +++ b/crates/extensions_ui/src/extension_registration_hooks.rs @@ -121,7 +121,7 @@ impl extension_host::ExtensionRegistrationHooks for ConcreteExtensionRegistratio fn update_lsp_status( &self, - server_name: language::LanguageServerName, + server_name: lsp::LanguageServerName, status: LanguageServerBinaryStatus, ) { self.language_registry @@ -140,7 +140,7 @@ impl extension_host::ExtensionRegistrationHooks for ConcreteExtensionRegistratio fn remove_lsp_adapter( &self, language_name: &language::LanguageName, - server_name: &language::LanguageServerName, + server_name: &lsp::LanguageServerName, ) { self.language_registry .remove_lsp_adapter(language_name, server_name); diff --git a/crates/extensions_ui/src/extension_store_test.rs b/crates/extensions_ui/src/extension_store_test.rs index 88730e8eee65f13d21e7ff5209927cb400fd46a3..9c5140272d3dd55f451775c89d3fec5cf3a56a28 100644 --- a/crates/extensions_ui/src/extension_store_test.rs +++ b/crates/extensions_ui/src/extension_store_test.rs @@ -14,7 +14,8 @@ use futures::{io::BufReader, AsyncReadExt, StreamExt}; use gpui::{Context, SemanticVersion, TestAppContext}; use http_client::{FakeHttpClient, Response}; use indexed_docs::IndexedDocsRegistry; -use language::{LanguageMatcher, LanguageRegistry, LanguageServerBinaryStatus, LanguageServerName}; +use language::{LanguageMatcher, LanguageRegistry, LanguageServerBinaryStatus}; +use lsp::LanguageServerName; use node_runtime::NodeRuntime; use parking_lot::Mutex; use project::{Project, DEFAULT_COMPLETION_CONTEXT}; diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index 48501114b006ecab1ad4f326c2f34e5834c0626b..580955a98b4461d17eb4ab265775fa741bf8bb73 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -30,7 +30,7 @@ use gpui::{AppContext, AsyncAppContext, Model, SharedString, Task}; pub use highlight_map::HighlightMap; use http_client::HttpClient; pub use language_registry::{LanguageName, LoadedLanguage}; -use lsp::{CodeActionKind, LanguageServerBinary, LanguageServerBinaryOptions}; +use lsp::{CodeActionKind, LanguageServerBinary, LanguageServerBinaryOptions, LanguageServerName}; use parking_lot::Mutex; use regex::Regex; use schemars::{ @@ -139,57 +139,6 @@ pub trait ToLspPosition { fn to_lsp_position(self) -> lsp::Position; } -/// A name of a language server. -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)] -pub struct LanguageServerName(pub SharedString); - -impl std::fmt::Display for LanguageServerName { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - std::fmt::Display::fmt(&self.0, f) - } -} - -impl AsRef for LanguageServerName { - fn as_ref(&self) -> &str { - self.0.as_ref() - } -} - -impl AsRef for LanguageServerName { - fn as_ref(&self) -> &OsStr { - self.0.as_ref().as_ref() - } -} - -impl JsonSchema for LanguageServerName { - fn schema_name() -> String { - "LanguageServerName".into() - } - - fn json_schema(_: &mut SchemaGenerator) -> Schema { - SchemaObject { - instance_type: Some(InstanceType::String.into()), - ..Default::default() - } - .into() - } -} -impl LanguageServerName { - pub const fn new_static(s: &'static str) -> Self { - Self(SharedString::new_static(s)) - } - - pub fn from_proto(s: String) -> Self { - Self(s.into()) - } -} - -impl<'a> From<&'a str> for LanguageServerName { - fn from(str: &'a str) -> LanguageServerName { - LanguageServerName(str.to_string().into()) - } -} - #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Location { pub buffer: Model, diff --git a/crates/language_tools/src/lsp_log.rs b/crates/language_tools/src/lsp_log.rs index e57d5dbc4a2ca630cc31c9b463bffddba84b39a9..16044f941f897722a3dcb404d9e9fef3e0397e81 100644 --- a/crates/language_tools/src/lsp_log.rs +++ b/crates/language_tools/src/lsp_log.rs @@ -7,10 +7,10 @@ use gpui::{ IntoElement, Model, ModelContext, ParentElement, Render, Styled, Subscription, View, ViewContext, VisualContext, WeakModel, WindowContext, }; -use language::{LanguageServerId, LanguageServerName}; +use language::LanguageServerId; use lsp::{ - notification::SetTrace, IoKind, LanguageServer, MessageType, ServerCapabilities, - SetTraceParams, TraceValue, + notification::SetTrace, IoKind, LanguageServer, LanguageServerName, MessageType, + ServerCapabilities, SetTraceParams, TraceValue, }; use project::{search::SearchQuery, Project, WorktreeId}; use std::{borrow::Cow, sync::Arc}; diff --git a/crates/language_tools/src/lsp_log_tests.rs b/crates/language_tools/src/lsp_log_tests.rs index 6b45cfc8dcb3ad8e532adef5d4b666e097515a11..79308b6e101ee6624f32cd9112f004bb4515992e 100644 --- a/crates/language_tools/src/lsp_log_tests.rs +++ b/crates/language_tools/src/lsp_log_tests.rs @@ -5,9 +5,8 @@ use crate::lsp_log::LogMenuItem; use super::*; use futures::StreamExt; use gpui::{Context, SemanticVersion, TestAppContext, VisualTestContext}; -use language::{ - tree_sitter_rust, FakeLspAdapter, Language, LanguageConfig, LanguageMatcher, LanguageServerName, -}; +use language::{tree_sitter_rust, FakeLspAdapter, Language, LanguageConfig, LanguageMatcher}; +use lsp::LanguageServerName; use lsp_log::LogKind; use project::{FakeFs, Project}; use serde_json::json; diff --git a/crates/languages/src/c.rs b/crates/languages/src/c.rs index 28a12b5310f38ad577f58369c3950eb508037345..a0e0f6dadba41be9efc7da2fba88813863be1cc2 100644 --- a/crates/languages/src/c.rs +++ b/crates/languages/src/c.rs @@ -4,7 +4,7 @@ use futures::StreamExt; use gpui::AsyncAppContext; use http_client::github::{latest_github_release, GitHubLspBinaryVersion}; pub use language::*; -use lsp::LanguageServerBinary; +use lsp::{LanguageServerBinary, LanguageServerName}; use smol::fs::{self, File}; use std::{any::Any, env::consts, path::PathBuf, sync::Arc}; use util::{fs::remove_matching, maybe, ResultExt}; diff --git a/crates/languages/src/css.rs b/crates/languages/src/css.rs index b4e5feaab76c992cee629a53fde6bf34c6a47a35..536f3396647931f0f4fe8e45735399802e04580c 100644 --- a/crates/languages/src/css.rs +++ b/crates/languages/src/css.rs @@ -1,8 +1,8 @@ use anyhow::{anyhow, Result}; use async_trait::async_trait; use futures::StreamExt; -use language::{LanguageServerName, LspAdapter, LspAdapterDelegate}; -use lsp::LanguageServerBinary; +use language::{LspAdapter, LspAdapterDelegate}; +use lsp::{LanguageServerBinary, LanguageServerName}; use node_runtime::NodeRuntime; use serde_json::json; use smol::fs; diff --git a/crates/languages/src/go.rs b/crates/languages/src/go.rs index fb895ed75375accd985d31dd5a9369dc90c40266..7d44a0c1287dcf357817e3594bfbf878f850f0a2 100644 --- a/crates/languages/src/go.rs +++ b/crates/languages/src/go.rs @@ -5,7 +5,7 @@ use futures::StreamExt; use gpui::{AppContext, AsyncAppContext, Task}; use http_client::github::latest_github_release; pub use language::*; -use lsp::LanguageServerBinary; +use lsp::{LanguageServerBinary, LanguageServerName}; use regex::Regex; use serde_json::json; use smol::{fs, process}; diff --git a/crates/languages/src/json.rs b/crates/languages/src/json.rs index 924d3977043cfdc0eabb84530beead418d66bc4d..c0c7e6f453a107797686f817b850a24b41c3cba6 100644 --- a/crates/languages/src/json.rs +++ b/crates/languages/src/json.rs @@ -6,10 +6,8 @@ use collections::HashMap; use futures::StreamExt; use gpui::{AppContext, AsyncAppContext}; use http_client::github::{latest_github_release, GitHubLspBinaryVersion}; -use language::{ - LanguageRegistry, LanguageServerName, LanguageToolchainStore, LspAdapter, LspAdapterDelegate, -}; -use lsp::LanguageServerBinary; +use language::{LanguageRegistry, LanguageToolchainStore, LspAdapter, LspAdapterDelegate}; +use lsp::{LanguageServerBinary, LanguageServerName}; use node_runtime::NodeRuntime; use project::ContextProviderWithTasks; use serde_json::{json, Value}; diff --git a/crates/languages/src/lib.rs b/crates/languages/src/lib.rs index 7bc9d5bd8ccdef3ca55fb39bc2a8227d86862f99..77c8531f3e0f54bc002523af91f7ae5d08483603 100644 --- a/crates/languages/src/lib.rs +++ b/crates/languages/src/lib.rs @@ -2,6 +2,7 @@ use anyhow::Context; use gpui::{AppContext, UpdateGlobal}; use json::json_task_context; pub use language::*; +use lsp::LanguageServerName; use node_runtime::NodeRuntime; use python::{PythonContextProvider, PythonToolchainProvider}; use rust_embed::RustEmbed; diff --git a/crates/languages/src/python.rs b/crates/languages/src/python.rs index cad2e3483a6f140d6592170c50e9eb60a91add80..60b514d3af3e1d074d1e8c2ccdfa105a6f0ad13d 100644 --- a/crates/languages/src/python.rs +++ b/crates/languages/src/python.rs @@ -8,8 +8,9 @@ use language::LanguageToolchainStore; use language::Toolchain; use language::ToolchainList; use language::ToolchainLister; -use language::{ContextProvider, LanguageServerName, LspAdapter, LspAdapterDelegate}; +use language::{ContextProvider, LspAdapter, LspAdapterDelegate}; use lsp::LanguageServerBinary; +use lsp::LanguageServerName; use node_runtime::NodeRuntime; use pet_core::os_environment::Environment; use pet_core::python_environment::PythonEnvironmentKind; diff --git a/crates/languages/src/rust.rs b/crates/languages/src/rust.rs index 1f040eb6476e59e3caf3fd9aa0105991e6e85db4..e6735ba96b09c16823d17af3cab49ea9c2559e35 100644 --- a/crates/languages/src/rust.rs +++ b/crates/languages/src/rust.rs @@ -6,7 +6,7 @@ use futures::{io::BufReader, StreamExt}; use gpui::{AppContext, AsyncAppContext}; use http_client::github::{latest_github_release, GitHubLspBinaryVersion}; pub use language::*; -use lsp::LanguageServerBinary; +use lsp::{LanguageServerBinary, LanguageServerName}; use regex::Regex; use smol::fs::{self, File}; use std::{ diff --git a/crates/languages/src/tailwind.rs b/crates/languages/src/tailwind.rs index 6d4416c7d95cc29ec25946a35454c33d2ae91f8c..f1b5b87a2c22d16b3c8fd42287ef5525ce11c53c 100644 --- a/crates/languages/src/tailwind.rs +++ b/crates/languages/src/tailwind.rs @@ -3,8 +3,8 @@ use async_trait::async_trait; use collections::HashMap; use futures::StreamExt; use gpui::AsyncAppContext; -use language::{LanguageServerName, LanguageToolchainStore, LspAdapter, LspAdapterDelegate}; -use lsp::LanguageServerBinary; +use language::{LanguageToolchainStore, LspAdapter, LspAdapterDelegate}; +use lsp::{LanguageServerBinary, LanguageServerName}; use node_runtime::NodeRuntime; use project::lsp_store::language_server_settings; use serde_json::{json, Value}; diff --git a/crates/languages/src/typescript.rs b/crates/languages/src/typescript.rs index 345a5f0694447d38839f6d141e991403f1e2c3a0..ffce5f82744b9aed04521b2ae7ca362ab5fe0f50 100644 --- a/crates/languages/src/typescript.rs +++ b/crates/languages/src/typescript.rs @@ -5,8 +5,8 @@ use async_trait::async_trait; use collections::HashMap; use gpui::AsyncAppContext; use http_client::github::{build_asset_url, AssetKind, GitHubLspBinaryVersion}; -use language::{LanguageServerName, LanguageToolchainStore, LspAdapter, LspAdapterDelegate}; -use lsp::{CodeActionKind, LanguageServerBinary}; +use language::{LanguageToolchainStore, LspAdapter, LspAdapterDelegate}; +use lsp::{CodeActionKind, LanguageServerBinary, LanguageServerName}; use node_runtime::NodeRuntime; use project::lsp_store::language_server_settings; use project::ContextProviderWithTasks; diff --git a/crates/languages/src/vtsls.rs b/crates/languages/src/vtsls.rs index 2d44d178e0346892da64b70afd19e049b1dee6ae..0ad9158003f5431b6c2144035be3768c6f5fe957 100644 --- a/crates/languages/src/vtsls.rs +++ b/crates/languages/src/vtsls.rs @@ -2,8 +2,8 @@ use anyhow::{anyhow, Result}; use async_trait::async_trait; use collections::HashMap; use gpui::AsyncAppContext; -use language::{LanguageServerName, LanguageToolchainStore, LspAdapter, LspAdapterDelegate}; -use lsp::{CodeActionKind, LanguageServerBinary}; +use language::{LanguageToolchainStore, LspAdapter, LspAdapterDelegate}; +use lsp::{CodeActionKind, LanguageServerBinary, LanguageServerName}; use node_runtime::NodeRuntime; use project::lsp_store::language_server_settings; use serde_json::Value; diff --git a/crates/languages/src/yaml.rs b/crates/languages/src/yaml.rs index d8f927b770ce2c5731c55f38493c40b42fa3f57e..6d34d9816c7d74ac2475d5a521f274c26917d187 100644 --- a/crates/languages/src/yaml.rs +++ b/crates/languages/src/yaml.rs @@ -3,10 +3,9 @@ use async_trait::async_trait; use futures::StreamExt; use gpui::AsyncAppContext; use language::{ - language_settings::AllLanguageSettings, LanguageServerName, LanguageToolchainStore, LspAdapter, - LspAdapterDelegate, + language_settings::AllLanguageSettings, LanguageToolchainStore, LspAdapter, LspAdapterDelegate, }; -use lsp::LanguageServerBinary; +use lsp::{LanguageServerBinary, LanguageServerName}; use node_runtime::NodeRuntime; use project::lsp_store::language_server_settings; use serde_json::Value; diff --git a/crates/lsp/Cargo.toml b/crates/lsp/Cargo.toml index 0cd4a8837acf0ab343570fe01c6eac2cd057166f..3460bf34dd20fcf4ba981354e05adf1d30143c3d 100644 --- a/crates/lsp/Cargo.toml +++ b/crates/lsp/Cargo.toml @@ -27,6 +27,7 @@ parking_lot.workspace = true postage.workspace = true serde.workspace = true serde_json.workspace = true +schemars.workspace = true smol.workspace = true util.workspace = true release_channel.workspace = true diff --git a/crates/lsp/src/lsp.rs b/crates/lsp/src/lsp.rs index df2ab35fc43377973998c38a6d78092de5e2e093..ca09ef4d1fc24e27c868514e8e658cafaebb91a7 100644 --- a/crates/lsp/src/lsp.rs +++ b/crates/lsp/src/lsp.rs @@ -6,9 +6,14 @@ pub use lsp_types::*; use anyhow::{anyhow, Context, Result}; use collections::HashMap; use futures::{channel::oneshot, io::BufWriter, select, AsyncRead, AsyncWrite, Future, FutureExt}; -use gpui::{AppContext, AsyncAppContext, BackgroundExecutor, Task}; +use gpui::{AppContext, AsyncAppContext, BackgroundExecutor, SharedString, Task}; use parking_lot::{Mutex, RwLock}; use postage::{barrier, prelude::Stream}; +use schemars::{ + gen::SchemaGenerator, + schema::{InstanceType, Schema, SchemaObject}, + JsonSchema, +}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde_json::{json, value::RawValue, Value}; use smol::{ @@ -21,7 +26,7 @@ use smol::{ use smol::process::windows::CommandExt; use std::{ - ffi::OsString, + ffi::{OsStr, OsString}, fmt, io::Write, ops::DerefMut, @@ -78,7 +83,8 @@ pub struct LanguageServer { server_id: LanguageServerId, next_id: AtomicI32, outbound_tx: channel::Sender, - name: Arc, + name: LanguageServerName, + process_name: Arc, capabilities: RwLock, code_action_kinds: Option>, notification_handlers: Arc>>, @@ -108,6 +114,58 @@ impl LanguageServerId { } } +/// A name of a language server. +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)] +pub struct LanguageServerName(pub SharedString); + +impl std::fmt::Display for LanguageServerName { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(&self.0, f) + } +} + +impl AsRef for LanguageServerName { + fn as_ref(&self) -> &str { + self.0.as_ref() + } +} + +impl AsRef for LanguageServerName { + fn as_ref(&self) -> &OsStr { + self.0.as_ref().as_ref() + } +} + +impl JsonSchema for LanguageServerName { + fn schema_name() -> String { + "LanguageServerName".into() + } + + fn json_schema(_: &mut SchemaGenerator) -> Schema { + SchemaObject { + instance_type: Some(InstanceType::String.into()), + ..Default::default() + } + .into() + } +} + +impl LanguageServerName { + pub const fn new_static(s: &'static str) -> Self { + Self(SharedString::new_static(s)) + } + + pub fn from_proto(s: String) -> Self { + Self(s.into()) + } +} + +impl<'a> From<&'a str> for LanguageServerName { + fn from(str: &'a str) -> LanguageServerName { + LanguageServerName(str.to_string().into()) + } +} + /// Handle to a language server RPC activity subscription. pub enum Subscription { Notification { @@ -269,6 +327,7 @@ impl LanguageServer { pub fn new( stderr_capture: Arc>>, server_id: LanguageServerId, + server_name: LanguageServerName, binary: LanguageServerBinary, root_path: &Path, code_action_kinds: Option>, @@ -310,6 +369,7 @@ impl LanguageServer { let stderr = server.stderr.take().unwrap(); let mut server = Self::new_internal( server_id, + server_name, stdin, stdout, Some(stderr), @@ -330,7 +390,7 @@ impl LanguageServer { ); if let Some(name) = binary.path.file_name() { - server.name = name.to_string_lossy().into(); + server.process_name = name.to_string_lossy().into(); } Ok(server) @@ -339,6 +399,7 @@ impl LanguageServer { #[allow(clippy::too_many_arguments)] fn new_internal( server_id: LanguageServerId, + server_name: LanguageServerName, stdin: Stdin, stdout: Stdout, stderr: Option, @@ -408,7 +469,8 @@ impl LanguageServer { notification_handlers, response_handlers, io_handlers, - name: Arc::default(), + name: server_name, + process_name: Arc::default(), capabilities: Default::default(), code_action_kinds, next_id: Default::default(), @@ -725,7 +787,7 @@ impl LanguageServer { cx.spawn(|_| async move { let response = self.request::(params).await?; if let Some(info) = response.server_info { - self.name = info.name.into(); + self.process_name = info.name.into(); } self.capabilities = RwLock::new(response.capabilities); @@ -937,8 +999,12 @@ impl LanguageServer { } /// Get the name of the running language server. - pub fn name(&self) -> &str { - &self.name + pub fn name(&self) -> LanguageServerName { + self.name.clone() + } + + pub fn process_name(&self) -> &str { + &self.process_name } /// Get the reported capabilities of the running language server. @@ -1179,8 +1245,11 @@ impl FakeLanguageServer { let root = Self::root_path(); + let server_name = LanguageServerName(name.clone().into()); + let process_name = Arc::from(name.as_str()); let mut server = LanguageServer::new_internal( server_id, + server_name.clone(), stdin_writer, stdout_reader, None::, @@ -1192,12 +1261,13 @@ impl FakeLanguageServer { cx.clone(), |_| {}, ); - server.name = name.as_str().into(); + server.process_name = process_name; let fake = FakeLanguageServer { binary, server: Arc::new({ let mut server = LanguageServer::new_internal( server_id, + server_name, stdout_writer, stdin_reader, None::, @@ -1216,7 +1286,7 @@ impl FakeLanguageServer { .ok(); }, ); - server.name = name.as_str().into(); + server.process_name = name.as_str().into(); server }), notifications_rx, diff --git a/crates/prettier/src/prettier.rs b/crates/prettier/src/prettier.rs index d7b13c99926c45a916cddc350b3eb4e96423b48c..3a3b88cba14d1cc74580afb04ba97a3d5033ebd8 100644 --- a/crates/prettier/src/prettier.rs +++ b/crates/prettier/src/prettier.rs @@ -154,7 +154,7 @@ impl Prettier { node: NodeRuntime, cx: AsyncAppContext, ) -> anyhow::Result { - use lsp::LanguageServerBinary; + use lsp::{LanguageServerBinary, LanguageServerName}; let executor = cx.background_executor().clone(); anyhow::ensure!( @@ -170,14 +170,17 @@ impl Prettier { let node_path = executor .spawn(async move { node.binary_path().await }) .await?; + let server_name = LanguageServerName("prettier".into()); + let server_binary = LanguageServerBinary { + path: node_path, + arguments: vec![prettier_server.into(), prettier_dir.as_path().into()], + env: None, + }; let server = LanguageServer::new( Arc::new(parking_lot::Mutex::new(None)), server_id, - LanguageServerBinary { - path: node_path, - arguments: vec![prettier_server.into(), prettier_dir.as_path().into()], - env: None, - }, + server_name, + server_binary, &prettier_dir, None, cx.clone(), diff --git a/crates/project/src/lsp_store.rs b/crates/project/src/lsp_store.rs index 57c046e282adc694b5435bc5cdf247dd1b6fe4d9..5f1f6a88add186a8558ec8c7e30b43b5fb216e7e 100644 --- a/crates/project/src/lsp_store.rs +++ b/crates/project/src/lsp_store.rs @@ -38,16 +38,17 @@ use language::{ proto::{deserialize_anchor, deserialize_version, serialize_anchor, serialize_version}, range_from_lsp, Bias, Buffer, BufferSnapshot, CachedLspAdapter, CodeLabel, Diagnostic, DiagnosticEntry, DiagnosticSet, Diff, Documentation, File as _, Language, LanguageName, - LanguageRegistry, LanguageServerBinaryStatus, LanguageServerName, LanguageToolchainStore, - LocalFile, LspAdapter, LspAdapterDelegate, Patch, PointUtf16, TextBufferSnapshot, ToOffset, - ToPointUtf16, Transaction, Unclipped, + LanguageRegistry, LanguageServerBinaryStatus, LanguageToolchainStore, LocalFile, LspAdapter, + LspAdapterDelegate, Patch, PointUtf16, TextBufferSnapshot, ToOffset, ToPointUtf16, Transaction, + Unclipped, }; use lsp::{ CodeActionKind, CompletionContext, DiagnosticSeverity, DiagnosticTag, DidChangeWatchedFilesRegistrationOptions, Edit, FileSystemWatcher, InsertTextFormat, LanguageServer, LanguageServerBinary, LanguageServerBinaryOptions, LanguageServerId, - LspRequestFuture, MessageActionItem, MessageType, OneOf, ServerHealthStatus, ServerStatus, - SymbolKind, TextEdit, Url, WorkDoneProgressCancelParams, WorkspaceFolder, + LanguageServerName, LspRequestFuture, MessageActionItem, MessageType, OneOf, + ServerHealthStatus, ServerStatus, SymbolKind, TextEdit, Url, WorkDoneProgressCancelParams, + WorkspaceFolder, }; use node_runtime::read_package_installed_version; use parking_lot::{Mutex, RwLock}; @@ -5598,6 +5599,7 @@ impl LspStore { let pending_server = cx.spawn({ let adapter = adapter.clone(); + let server_name = adapter.name.clone(); let stderr_capture = stderr_capture.clone(); move |_lsp_store, cx| async move { @@ -5608,7 +5610,7 @@ impl LspStore { .update(&mut cx.clone(), |this, cx| { this.languages.create_fake_language_server( server_id, - &adapter.name, + &server_name, binary.clone(), cx.to_async(), ) @@ -5622,6 +5624,7 @@ impl LspStore { lsp::LanguageServer::new( stderr_capture, server_id, + server_name, binary, &root_path, adapter.code_action_kinds(), @@ -6617,7 +6620,7 @@ impl LspStore { cx.emit(LspStoreEvent::LanguageServerAdded( server_id, - language_server.name().into(), + language_server.name(), Some(key.0), )); diff --git a/crates/project/src/prettier_store.rs b/crates/project/src/prettier_store.rs index b6c99e4a1eba4b42538b00ee813931cb809b8a83..c7ac0ffd0bbf6ce9cb980dcabe8f930b61e426df 100644 --- a/crates/project/src/prettier_store.rs +++ b/crates/project/src/prettier_store.rs @@ -15,9 +15,9 @@ use futures::{ use gpui::{AsyncAppContext, EventEmitter, Model, ModelContext, Task, WeakModel}; use language::{ language_settings::{Formatter, LanguageSettings, SelectedFormatter}, - Buffer, LanguageRegistry, LanguageServerName, LocalFile, + Buffer, LanguageRegistry, LocalFile, }; -use lsp::{LanguageServer, LanguageServerId}; +use lsp::{LanguageServer, LanguageServerId, LanguageServerName}; use node_runtime::NodeRuntime; use paths::default_prettier_dir; use prettier::Prettier; diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 48c88d46ace4a3f96516de3097f8d42aa244a419..4d94622020df2696e8376afc4c710058b7ce77fa 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -48,12 +48,12 @@ use itertools::Itertools; use language::{ language_settings::InlayHintKind, proto::split_operations, Buffer, BufferEvent, CachedLspAdapter, Capability, CodeLabel, DiagnosticEntry, Documentation, File as _, Language, - LanguageName, LanguageRegistry, LanguageServerName, PointUtf16, ToOffset, ToPointUtf16, - Toolchain, ToolchainList, Transaction, Unclipped, + LanguageName, LanguageRegistry, PointUtf16, ToOffset, ToPointUtf16, Toolchain, ToolchainList, + Transaction, Unclipped, }; use lsp::{ CompletionContext, CompletionItemKind, DocumentHighlightKind, LanguageServer, LanguageServerId, - MessageActionItem, + LanguageServerName, MessageActionItem, }; use lsp_command::*; use node_runtime::NodeRuntime; diff --git a/crates/project/src/project_settings.rs b/crates/project/src/project_settings.rs index 52594ce5b002beb2589f26d8926c8412e199f036..bd0d7cc884f95edc4e97f323225dde94b65e4461 100644 --- a/crates/project/src/project_settings.rs +++ b/crates/project/src/project_settings.rs @@ -2,7 +2,7 @@ use anyhow::Context; use collections::HashMap; use fs::Fs; use gpui::{AppContext, AsyncAppContext, BorrowAppContext, EventEmitter, Model, ModelContext}; -use language::LanguageServerName; +use lsp::LanguageServerName; use paths::{ local_settings_file_relative_path, local_tasks_file_relative_path, local_vscode_tasks_file_relative_path, EDITORCONFIG_NAME, diff --git a/crates/project/src/project_tests.rs b/crates/project/src/project_tests.rs index 49406b971585efaaf154d7859a3f85fca1dc64b0..2be927458ccfeabdbeb1448fcfb43d4e5d7e0d5c 100644 --- a/crates/project/src/project_tests.rs +++ b/crates/project/src/project_tests.rs @@ -1243,7 +1243,7 @@ async fn test_disk_based_diagnostics_progress(cx: &mut gpui::TestAppContext) { events.next().await.unwrap(), Event::LanguageServerAdded( LanguageServerId(0), - fake_server.server.name().into(), + fake_server.server.name(), Some(worktree_id) ), ); @@ -1378,7 +1378,7 @@ async fn test_restarting_server_with_diagnostics_running(cx: &mut gpui::TestAppC events.next().await.unwrap(), Event::LanguageServerAdded( LanguageServerId(1), - fake_server.server.name().into(), + fake_server.server.name(), Some(worktree_id) ) ); @@ -4865,11 +4865,10 @@ async fn test_multiple_language_server_hovers(cx: &mut gpui::TestAppContext) { }); let new_server_name = new_server.server.name(); assert!( - !servers_with_hover_requests.contains_key(new_server_name), + !servers_with_hover_requests.contains_key(&new_server_name), "Unexpected: initialized server with the same name twice. Name: `{new_server_name}`" ); - let new_server_name = new_server_name.to_string(); - match new_server_name.as_str() { + match new_server_name.as_ref() { "TailwindServer" | "TypeScriptServer" => { servers_with_hover_requests.insert( new_server_name.clone(), @@ -5089,11 +5088,10 @@ async fn test_multiple_language_server_actions(cx: &mut gpui::TestAppContext) { let new_server_name = new_server.server.name(); assert!( - !servers_with_actions_requests.contains_key(new_server_name), + !servers_with_actions_requests.contains_key(&new_server_name), "Unexpected: initialized server with the same name twice. Name: `{new_server_name}`" ); - let new_server_name = new_server_name.to_string(); - match new_server_name.as_str() { + match new_server_name.0.as_ref() { "TailwindServer" | "TypeScriptServer" => { servers_with_actions_requests.insert( new_server_name.clone(), diff --git a/crates/remote_server/src/remote_editing_tests.rs b/crates/remote_server/src/remote_editing_tests.rs index 0ced691939b8ebf54b1ed8cadcb848b39613a51e..e3914c7ae19ebd67967edb2087feeeec361a4164 100644 --- a/crates/remote_server/src/remote_editing_tests.rs +++ b/crates/remote_server/src/remote_editing_tests.rs @@ -6,10 +6,9 @@ use gpui::{Context, Model, SemanticVersion, TestAppContext}; use http_client::{BlockedHttpClient, FakeHttpClient}; use language::{ language_settings::{language_settings, AllLanguageSettings}, - Buffer, FakeLspAdapter, LanguageConfig, LanguageMatcher, LanguageRegistry, LanguageServerName, - LineEnding, + Buffer, FakeLspAdapter, LanguageConfig, LanguageMatcher, LanguageRegistry, LineEnding, }; -use lsp::{CompletionContext, CompletionResponse, CompletionTriggerKind}; +use lsp::{CompletionContext, CompletionResponse, CompletionTriggerKind, LanguageServerName}; use node_runtime::NodeRuntime; use project::{ search::{SearchQuery, SearchResult},