From 33d1145c3f7327a14f39a40c77a2cb6741f5d78d Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Tue, 28 Jan 2025 19:04:21 -0500 Subject: [PATCH] Refactor to use `SharedString` in more places (#23813) Splitting this off from https://github.com/zed-industries/zed/pull/23808, per @maxdeviant's suggestion! Release Notes: - N/A --------- Co-authored-by: Nathan --- crates/editor/src/editor.rs | 2 +- crates/gpui/src/shared_string.rs | 5 ++++ crates/language/src/buffer_tests.rs | 2 +- crates/language/src/language.rs | 4 ++-- crates/language/src/language_registry.rs | 24 ++++++++++++++----- .../src/language_selector.rs | 4 ++-- crates/language_tools/src/syntax_tree_view.rs | 2 +- .../project/src/lsp_command/signature_help.rs | 2 +- crates/project/src/project.rs | 2 +- crates/project/src/task_inventory.rs | 8 +++---- crates/project/src/toolchain_store.rs | 5 +++- crates/prompt_library/src/prompts.rs | 2 +- crates/repl/src/repl_editor.rs | 2 +- crates/workspace/src/persistence.rs | 4 ++-- .../zed/src/zed/quick_action_bar/repl_menu.rs | 2 +- 15 files changed, 45 insertions(+), 25 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index ba3f1dc54c..01b8a8e6db 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -7042,7 +7042,7 @@ impl Editor { let mut should_rewrap = is_vim_mode == IsVimMode::Yes; if let Some(language_scope) = buffer.language_scope_at(selection.head()) { - match language_scope.language_name().0.as_ref() { + match language_scope.language_name().as_ref() { "Markdown" | "Plain Text" => { should_rewrap = true; } diff --git a/crates/gpui/src/shared_string.rs b/crates/gpui/src/shared_string.rs index b5210efa50..1d55d13ad0 100644 --- a/crates/gpui/src/shared_string.rs +++ b/crates/gpui/src/shared_string.rs @@ -15,6 +15,11 @@ impl SharedString { pub const fn new_static(str: &'static str) -> Self { Self(ArcCow::Borrowed(str)) } + + /// Creates a [`SharedString`] from anything that can become an Arc + pub fn new(str: impl Into>) -> Self { + SharedString(ArcCow::Owned(str.into())) + } } impl JsonSchema for SharedString { diff --git a/crates/language/src/buffer_tests.rs b/crates/language/src/buffer_tests.rs index 59e5e44f2c..f586ba78bb 100644 --- a/crates/language/src/buffer_tests.rs +++ b/crates/language/src/buffer_tests.rs @@ -2424,7 +2424,7 @@ fn test_language_at_with_hidden_languages(cx: &mut App) { assert_eq!(config.language_name(), "Markdown".into()); let language = snapshot.language_at(point).unwrap(); - assert_eq!(language.name().0.as_ref(), "Markdown"); + assert_eq!(language.name().as_ref(), "Markdown"); } buffer diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index ea2243031f..58aef2e8bc 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -256,7 +256,7 @@ impl CachedLspAdapter { pub fn language_id(&self, language_name: &LanguageName) -> String { self.language_ids - .get(language_name.0.as_ref()) + .get(language_name.as_ref()) .cloned() .unwrap_or_else(|| language_name.lsp_id()) } @@ -1462,7 +1462,7 @@ impl Language { self.config .code_fence_block_name .clone() - .unwrap_or_else(|| self.config.name.0.to_lowercase().into()) + .unwrap_or_else(|| self.config.name.as_ref().to_lowercase().into()) } pub fn context_provider(&self) -> Option> { diff --git a/crates/language/src/language_registry.rs b/crates/language/src/language_registry.rs index 055798279b..f0d314f87d 100644 --- a/crates/language/src/language_registry.rs +++ b/crates/language/src/language_registry.rs @@ -14,7 +14,7 @@ use futures::{ Future, }; use globset::GlobSet; -use gpui::{App, BackgroundExecutor}; +use gpui::{App, BackgroundExecutor, SharedString}; use lsp::LanguageServerId; use parking_lot::{Mutex, RwLock}; use postage::watch; @@ -36,15 +36,15 @@ use util::{maybe, paths::PathExt, post_inc, ResultExt}; #[derive( Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, JsonSchema, )] -pub struct LanguageName(pub Arc); +pub struct LanguageName(SharedString); impl LanguageName { pub fn new(s: &str) -> Self { - Self(Arc::from(s)) + Self(SharedString::new(s)) } pub fn from_proto(s: String) -> Self { - Self(Arc::from(s)) + Self(SharedString::from(s)) } pub fn to_proto(self) -> String { self.0.to_string() @@ -57,6 +57,18 @@ impl LanguageName { } } +impl From for SharedString { + fn from(value: LanguageName) -> Self { + value.0 + } +} + +impl AsRef for LanguageName { + fn as_ref(&self) -> &str { + self.0.as_ref() + } +} + impl Borrow for LanguageName { fn borrow(&self) -> &str { self.0.as_ref() @@ -71,7 +83,7 @@ impl std::fmt::Display for LanguageName { impl<'a> From<&'a str> for LanguageName { fn from(str: &'a str) -> LanguageName { - LanguageName(str.into()) + LanguageName(SharedString::new(str)) } } @@ -657,7 +669,7 @@ impl LanguageRegistry { .iter() .any(|suffix| path_suffixes.contains(&Some(suffix.as_str()))); let custom_suffixes = user_file_types - .and_then(|types| types.get(&language_name.0)) + .and_then(|types| types.get(language_name.as_ref())) .unwrap_or(&empty); let path_matches_custom_suffix = path_suffixes .iter() diff --git a/crates/language_selector/src/language_selector.rs b/crates/language_selector/src/language_selector.rs index 6b28ce185b..10af10b4d2 100644 --- a/crates/language_selector/src/language_selector.rs +++ b/crates/language_selector/src/language_selector.rs @@ -141,7 +141,7 @@ impl LanguageSelectorDelegate { let need_icon = FileFinderSettings::get_global(cx).file_icons; if let Some(buffer_language) = buffer_language { let buffer_language_name = buffer_language.name(); - if buffer_language_name.0.as_ref() == mat.string.as_str() { + if buffer_language_name.as_ref() == mat.string.as_str() { label.push_str(" (current)"); let icon = need_icon .then(|| self.language_icon(&buffer_language.config().matcher, cx)) @@ -154,7 +154,7 @@ impl LanguageSelectorDelegate { let language_name = LanguageName::new(mat.string.as_str()); match self .language_registry - .available_language_for_name(&language_name.0) + .available_language_for_name(language_name.as_ref()) { Some(available_language) => { let icon = self.language_icon(available_language.matcher(), cx); diff --git a/crates/language_tools/src/syntax_tree_view.rs b/crates/language_tools/src/syntax_tree_view.rs index 4f4579b0a0..9db4a97fa9 100644 --- a/crates/language_tools/src/syntax_tree_view.rs +++ b/crates/language_tools/src/syntax_tree_view.rs @@ -499,7 +499,7 @@ impl SyntaxTreeToolbarItemView { fn render_header(active_layer: &OwnedSyntaxLayer) -> ButtonLike { ButtonLike::new("syntax tree header") - .child(Label::new(active_layer.language.name().0)) + .child(Label::new(active_layer.language.name())) .child(Label::new(format_node_range(active_layer.node()))) } } diff --git a/crates/project/src/lsp_command/signature_help.rs b/crates/project/src/lsp_command/signature_help.rs index bf197a11ba..c641a931b4 100644 --- a/crates/project/src/lsp_command/signature_help.rs +++ b/crates/project/src/lsp_command/signature_help.rs @@ -86,7 +86,7 @@ impl SignatureHelp { } else { let markdown = markdown.join(str_for_join); let language_name = language - .map(|n| n.name().0.to_lowercase()) + .map(|n| n.name().as_ref().to_lowercase()) .unwrap_or_default(); let markdown = if function_options_count >= 2 { diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index d7e715795a..eaef0b0a53 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -2579,7 +2579,7 @@ impl Project { language_name: LanguageName, ) -> Option { languages - .language_for_name(&language_name.0) + .language_for_name(language_name.as_ref()) .await .ok()? .toolchain_lister() diff --git a/crates/project/src/task_inventory.rs b/crates/project/src/task_inventory.rs index d67ad7f1ea..3e7c9dd644 100644 --- a/crates/project/src/task_inventory.rs +++ b/crates/project/src/task_inventory.rs @@ -10,7 +10,7 @@ use std::{ use anyhow::{Context as _, Result}; use collections::{HashMap, HashSet, VecDeque}; -use gpui::{App, AppContext as _, Entity, Task}; +use gpui::{App, AppContext as _, Entity, SharedString, Task}; use itertools::Itertools; use language::{ContextProvider, File, Language, LanguageToolchainStore, Location}; use settings::{parse_json_with_comments, SettingsLocation}; @@ -53,7 +53,7 @@ pub enum TaskSourceKind { abs_path: PathBuf, }, /// Languages-specific tasks coming from extensions. - Language { name: Arc }, + Language { name: SharedString }, } impl TaskSourceKind { @@ -91,7 +91,7 @@ impl Inventory { cx: &App, ) -> Vec<(TaskSourceKind, TaskTemplate)> { let task_source_kind = language.as_ref().map(|language| TaskSourceKind::Language { - name: language.name().0, + name: language.name().into(), }); let global_tasks = self.global_templates_from_settings(); let language_tasks = language @@ -124,7 +124,7 @@ impl Inventory { .as_ref() .and_then(|location| location.buffer.read(cx).language_at(location.range.start)); let task_source_kind = language.as_ref().map(|language| TaskSourceKind::Language { - name: language.name().0, + name: language.name().into(), }); let file = location .as_ref() diff --git a/crates/project/src/toolchain_store.rs b/crates/project/src/toolchain_store.rs index a8de446418..131cdfa726 100644 --- a/crates/project/src/toolchain_store.rs +++ b/crates/project/src/toolchain_store.rs @@ -316,7 +316,10 @@ impl LocalToolchainStore { cx.background_executor() .spawn(async move { - let language = registry.language_for_name(&language_name.0).await.ok()?; + let language = registry + .language_for_name(language_name.as_ref()) + .await + .ok()?; let toolchains = language.toolchain_lister()?; Some(toolchains.list(root.to_path_buf(), project_env).await) }) diff --git a/crates/prompt_library/src/prompts.rs b/crates/prompt_library/src/prompts.rs index 768d208b20..f8a453d113 100644 --- a/crates/prompt_library/src/prompts.rs +++ b/crates/prompt_library/src/prompts.rs @@ -224,7 +224,7 @@ impl PromptBuilder { buffer: BufferSnapshot, range: Range, ) -> Result { - let content_type = match language_name.as_ref().map(|l| l.0.as_ref()) { + let content_type = match language_name.as_ref().map(|l| l.as_ref()) { None | Some("Markdown" | "Plain Text") => "text", Some(_) => "code", }; diff --git a/crates/repl/src/repl_editor.rs b/crates/repl/src/repl_editor.rs index bdd39c4ee8..2e919caa72 100644 --- a/crates/repl/src/repl_editor.rs +++ b/crates/repl/src/repl_editor.rs @@ -454,7 +454,7 @@ fn markdown_code_blocks(buffer: &BufferSnapshot, range: Range) -> Vec) -> bool { - match language.name().0.as_ref() { + match language.name().as_ref() { "TypeScript" | "Python" => true, _ => false, } diff --git a/crates/workspace/src/persistence.rs b/crates/workspace/src/persistence.rs index 8bd5c87286..a89c1a7766 100644 --- a/crates/workspace/src/persistence.rs +++ b/crates/workspace/src/persistence.rs @@ -1088,7 +1088,7 @@ impl WorkspaceDb { .context("Preparing insertion")?; let toolchain: Vec<(String, String, String)> = - select((workspace_id, language_name.0.to_owned(), worktree_id.to_usize()))?; + select((workspace_id, language_name.as_ref().to_string(), worktree_id.to_usize()))?; Ok(toolchain.into_iter().next().and_then(|(name, path, raw_json)| Some(Toolchain { name: name.into(), @@ -1144,7 +1144,7 @@ impl WorkspaceDb { insert(( workspace_id, worktree_id.to_usize(), - toolchain.language_name.0.as_ref(), + toolchain.language_name.as_ref(), toolchain.name.as_ref(), toolchain.path.as_ref(), ))?; diff --git a/crates/zed/src/zed/quick_action_bar/repl_menu.rs b/crates/zed/src/zed/quick_action_bar/repl_menu.rs index 80d2107842..6e7f57ad94 100644 --- a/crates/zed/src/zed/quick_action_bar/repl_menu.rs +++ b/crates/zed/src/zed/quick_action_bar/repl_menu.rs @@ -69,7 +69,7 @@ impl QuickActionBar { return self.render_repl_launch_menu(spec, cx); } SessionSupport::RequiresSetup(language) => { - return self.render_repl_setup(&language.0, cx); + return self.render_repl_setup(language.as_ref(), cx); } SessionSupport::Unsupported => return None, };