From 5ca5d90234e89f502e96ec48f13ea1ed964460dc Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 4 Aug 2025 10:12:02 +0300 Subject: [PATCH] Use a better type for language IDs field (#35566) Part of the preparation for proto capabilities. Release Notes: - N/A --- crates/extension/src/extension_manifest.rs | 2 +- crates/language/src/language.rs | 9 +++--- .../src/extension_lsp_adapter.rs | 4 +-- crates/languages/src/json.rs | 10 +++---- crates/languages/src/tailwind.rs | 28 +++++++++---------- crates/languages/src/typescript.rs | 11 ++++---- crates/languages/src/vtsls.rs | 10 +++---- crates/project/src/lsp_command.rs | 23 ++++++++------- crates/project/src/lsp_store.rs | 5 +--- 9 files changed, 52 insertions(+), 50 deletions(-) diff --git a/crates/extension/src/extension_manifest.rs b/crates/extension/src/extension_manifest.rs index e3235cf561..5852b3e3fc 100644 --- a/crates/extension/src/extension_manifest.rs +++ b/crates/extension/src/extension_manifest.rs @@ -163,7 +163,7 @@ pub struct LanguageServerManifestEntry { #[serde(default)] languages: Vec, #[serde(default)] - pub language_ids: HashMap, + pub language_ids: HashMap, #[serde(default)] pub code_action_kinds: Option>, } diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index 549afc931c..894625b982 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -161,7 +161,7 @@ pub struct CachedLspAdapter { pub name: LanguageServerName, pub disk_based_diagnostic_sources: Vec, pub disk_based_diagnostics_progress_token: Option, - language_ids: HashMap, + language_ids: HashMap, pub adapter: Arc, pub reinstall_attempt_count: AtomicU64, cached_binary: futures::lock::Mutex>, @@ -277,10 +277,11 @@ impl CachedLspAdapter { pub fn language_id(&self, language_name: &LanguageName) -> String { self.language_ids - .get(language_name.as_ref()) + .get(language_name) .cloned() .unwrap_or_else(|| language_name.lsp_id()) } + pub fn manifest_name(&self) -> Option { self.manifest_name .get_or_init(|| self.adapter.manifest_name()) @@ -573,8 +574,8 @@ pub trait LspAdapter: 'static + Send + Sync { None } - fn language_ids(&self) -> HashMap { - Default::default() + fn language_ids(&self) -> HashMap { + HashMap::default() } /// Support custom initialize params. diff --git a/crates/language_extension/src/extension_lsp_adapter.rs b/crates/language_extension/src/extension_lsp_adapter.rs index 58fbe6cda2..98b6fd4b5a 100644 --- a/crates/language_extension/src/extension_lsp_adapter.rs +++ b/crates/language_extension/src/extension_lsp_adapter.rs @@ -242,7 +242,7 @@ impl LspAdapter for ExtensionLspAdapter { ])) } - fn language_ids(&self) -> HashMap { + fn language_ids(&self) -> HashMap { // TODO: The language IDs can be provided via the language server options // in `extension.toml now but we're leaving these existing usages in place temporarily // to avoid any compatibility issues between Zed and the extension versions. @@ -250,7 +250,7 @@ impl LspAdapter for ExtensionLspAdapter { // We can remove once the following extension versions no longer see any use: // - php@0.0.1 if self.extension.manifest().id.as_ref() == "php" { - return HashMap::from_iter([("PHP".into(), "php".into())]); + return HashMap::from_iter([(LanguageName::new("PHP"), "php".into())]); } self.extension diff --git a/crates/languages/src/json.rs b/crates/languages/src/json.rs index 15818730b8..601b4620c5 100644 --- a/crates/languages/src/json.rs +++ b/crates/languages/src/json.rs @@ -8,8 +8,8 @@ use futures::StreamExt; use gpui::{App, AsyncApp, Task}; use http_client::github::{GitHubLspBinaryVersion, latest_github_release}; use language::{ - ContextProvider, LanguageRegistry, LanguageToolchainStore, LocalFile as _, LspAdapter, - LspAdapterDelegate, + ContextProvider, LanguageName, LanguageRegistry, LanguageToolchainStore, LocalFile as _, + LspAdapter, LspAdapterDelegate, }; use lsp::{LanguageServerBinary, LanguageServerName}; use node_runtime::NodeRuntime; @@ -408,10 +408,10 @@ impl LspAdapter for JsonLspAdapter { Ok(config) } - fn language_ids(&self) -> HashMap { + fn language_ids(&self) -> HashMap { [ - ("JSON".into(), "json".into()), - ("JSONC".into(), "jsonc".into()), + (LanguageName::new("JSON"), "json".into()), + (LanguageName::new("JSONC"), "jsonc".into()), ] .into_iter() .collect() diff --git a/crates/languages/src/tailwind.rs b/crates/languages/src/tailwind.rs index cb4e939083..a7edbb148c 100644 --- a/crates/languages/src/tailwind.rs +++ b/crates/languages/src/tailwind.rs @@ -3,7 +3,7 @@ use async_trait::async_trait; use collections::HashMap; use futures::StreamExt; use gpui::AsyncApp; -use language::{LanguageToolchainStore, LspAdapter, LspAdapterDelegate}; +use language::{LanguageName, LanguageToolchainStore, LspAdapter, LspAdapterDelegate}; use lsp::{LanguageServerBinary, LanguageServerName}; use node_runtime::NodeRuntime; use project::{Fs, lsp_store::language_server_settings}; @@ -168,20 +168,20 @@ impl LspAdapter for TailwindLspAdapter { })) } - fn language_ids(&self) -> HashMap { + fn language_ids(&self) -> HashMap { HashMap::from_iter([ - ("Astro".to_string(), "astro".to_string()), - ("HTML".to_string(), "html".to_string()), - ("CSS".to_string(), "css".to_string()), - ("JavaScript".to_string(), "javascript".to_string()), - ("TSX".to_string(), "typescriptreact".to_string()), - ("Svelte".to_string(), "svelte".to_string()), - ("Elixir".to_string(), "phoenix-heex".to_string()), - ("HEEX".to_string(), "phoenix-heex".to_string()), - ("ERB".to_string(), "erb".to_string()), - ("HTML/ERB".to_string(), "erb".to_string()), - ("PHP".to_string(), "php".to_string()), - ("Vue.js".to_string(), "vue".to_string()), + (LanguageName::new("Astro"), "astro".to_string()), + (LanguageName::new("HTML"), "html".to_string()), + (LanguageName::new("CSS"), "css".to_string()), + (LanguageName::new("JavaScript"), "javascript".to_string()), + (LanguageName::new("TSX"), "typescriptreact".to_string()), + (LanguageName::new("Svelte"), "svelte".to_string()), + (LanguageName::new("Elixir"), "phoenix-heex".to_string()), + (LanguageName::new("HEEX"), "phoenix-heex".to_string()), + (LanguageName::new("ERB"), "erb".to_string()), + (LanguageName::new("HTML/ERB"), "erb".to_string()), + (LanguageName::new("PHP"), "php".to_string()), + (LanguageName::new("Vue.js"), "vue".to_string()), ]) } } diff --git a/crates/languages/src/typescript.rs b/crates/languages/src/typescript.rs index fb51544841..9dc3ee303d 100644 --- a/crates/languages/src/typescript.rs +++ b/crates/languages/src/typescript.rs @@ -8,7 +8,8 @@ use futures::future::join_all; use gpui::{App, AppContext, AsyncApp, Task}; use http_client::github::{AssetKind, GitHubLspBinaryVersion, build_asset_url}; use language::{ - ContextLocation, ContextProvider, File, LanguageToolchainStore, LspAdapter, LspAdapterDelegate, + ContextLocation, ContextProvider, File, LanguageName, LanguageToolchainStore, LspAdapter, + LspAdapterDelegate, }; use lsp::{CodeActionKind, LanguageServerBinary, LanguageServerName}; use node_runtime::NodeRuntime; @@ -741,11 +742,11 @@ impl LspAdapter for TypeScriptLspAdapter { })) } - fn language_ids(&self) -> HashMap { + fn language_ids(&self) -> HashMap { HashMap::from_iter([ - ("TypeScript".into(), "typescript".into()), - ("JavaScript".into(), "javascript".into()), - ("TSX".into(), "typescriptreact".into()), + (LanguageName::new("TypeScript"), "typescript".into()), + (LanguageName::new("JavaScript"), "javascript".into()), + (LanguageName::new("TSX"), "typescriptreact".into()), ]) } } diff --git a/crates/languages/src/vtsls.rs b/crates/languages/src/vtsls.rs index ca07673d5f..33751f733e 100644 --- a/crates/languages/src/vtsls.rs +++ b/crates/languages/src/vtsls.rs @@ -2,7 +2,7 @@ use anyhow::Result; use async_trait::async_trait; use collections::HashMap; use gpui::AsyncApp; -use language::{LanguageToolchainStore, LspAdapter, LspAdapterDelegate}; +use language::{LanguageName, LanguageToolchainStore, LspAdapter, LspAdapterDelegate}; use lsp::{CodeActionKind, LanguageServerBinary, LanguageServerName}; use node_runtime::NodeRuntime; use project::{Fs, lsp_store::language_server_settings}; @@ -273,11 +273,11 @@ impl LspAdapter for VtslsLspAdapter { Ok(default_workspace_configuration) } - fn language_ids(&self) -> HashMap { + fn language_ids(&self) -> HashMap { HashMap::from_iter([ - ("TypeScript".into(), "typescript".into()), - ("JavaScript".into(), "javascript".into()), - ("TSX".into(), "typescriptreact".into()), + (LanguageName::new("TypeScript"), "typescript".into()), + (LanguageName::new("JavaScript"), "javascript".into()), + (LanguageName::new("TSX"), "typescriptreact".into()), ]) } } diff --git a/crates/project/src/lsp_command.rs b/crates/project/src/lsp_command.rs index 958921a0e6..2fd61ea0b2 100644 --- a/crates/project/src/lsp_command.rs +++ b/crates/project/src/lsp_command.rs @@ -3580,6 +3580,18 @@ impl LspCommand for GetCodeLens { } } +impl LinkedEditingRange { + pub fn check_server_capabilities(capabilities: ServerCapabilities) -> bool { + let Some(linked_editing_options) = capabilities.linked_editing_range_provider else { + return false; + }; + if let LinkedEditingRangeServerCapabilities::Simple(false) = linked_editing_options { + return false; + } + true + } +} + #[async_trait(?Send)] impl LspCommand for LinkedEditingRange { type Response = Vec>; @@ -3591,16 +3603,7 @@ impl LspCommand for LinkedEditingRange { } fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool { - let Some(linked_editing_options) = &capabilities - .server_capabilities - .linked_editing_range_provider - else { - return false; - }; - if let LinkedEditingRangeServerCapabilities::Simple(false) = linked_editing_options { - return false; - } - true + Self::check_server_capabilities(capabilities.server_capabilities) } fn to_lsp( diff --git a/crates/project/src/lsp_store.rs b/crates/project/src/lsp_store.rs index 696892abb7..98cecc2e9b 100644 --- a/crates/project/src/lsp_store.rs +++ b/crates/project/src/lsp_store.rs @@ -5069,10 +5069,7 @@ impl LspStore { local .language_servers_for_buffer(buffer, cx) .filter(|(_, server)| { - server - .capabilities() - .linked_editing_range_provider - .is_some() + LinkedEditingRange::check_server_capabilities(server.capabilities()) }) .filter(|(adapter, _)| { scope