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 <nathan@zed.dev>
This commit is contained in:
Richard Feldman 2025-01-28 19:04:21 -05:00 committed by GitHub
parent 92a1cb893f
commit 33d1145c3f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 45 additions and 25 deletions

View file

@ -7042,7 +7042,7 @@ impl Editor {
let mut should_rewrap = is_vim_mode == IsVimMode::Yes; let mut should_rewrap = is_vim_mode == IsVimMode::Yes;
if let Some(language_scope) = buffer.language_scope_at(selection.head()) { 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" => { "Markdown" | "Plain Text" => {
should_rewrap = true; should_rewrap = true;
} }

View file

@ -15,6 +15,11 @@ impl SharedString {
pub const fn new_static(str: &'static str) -> Self { pub const fn new_static(str: &'static str) -> Self {
Self(ArcCow::Borrowed(str)) Self(ArcCow::Borrowed(str))
} }
/// Creates a [`SharedString`] from anything that can become an Arc<str>
pub fn new(str: impl Into<Arc<str>>) -> Self {
SharedString(ArcCow::Owned(str.into()))
}
} }
impl JsonSchema for SharedString { impl JsonSchema for SharedString {

View file

@ -2424,7 +2424,7 @@ fn test_language_at_with_hidden_languages(cx: &mut App) {
assert_eq!(config.language_name(), "Markdown".into()); assert_eq!(config.language_name(), "Markdown".into());
let language = snapshot.language_at(point).unwrap(); let language = snapshot.language_at(point).unwrap();
assert_eq!(language.name().0.as_ref(), "Markdown"); assert_eq!(language.name().as_ref(), "Markdown");
} }
buffer buffer

View file

@ -256,7 +256,7 @@ impl CachedLspAdapter {
pub fn language_id(&self, language_name: &LanguageName) -> String { pub fn language_id(&self, language_name: &LanguageName) -> String {
self.language_ids self.language_ids
.get(language_name.0.as_ref()) .get(language_name.as_ref())
.cloned() .cloned()
.unwrap_or_else(|| language_name.lsp_id()) .unwrap_or_else(|| language_name.lsp_id())
} }
@ -1462,7 +1462,7 @@ impl Language {
self.config self.config
.code_fence_block_name .code_fence_block_name
.clone() .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<Arc<dyn ContextProvider>> { pub fn context_provider(&self) -> Option<Arc<dyn ContextProvider>> {

View file

@ -14,7 +14,7 @@ use futures::{
Future, Future,
}; };
use globset::GlobSet; use globset::GlobSet;
use gpui::{App, BackgroundExecutor}; use gpui::{App, BackgroundExecutor, SharedString};
use lsp::LanguageServerId; use lsp::LanguageServerId;
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, RwLock};
use postage::watch; use postage::watch;
@ -36,15 +36,15 @@ use util::{maybe, paths::PathExt, post_inc, ResultExt};
#[derive( #[derive(
Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, JsonSchema, Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, JsonSchema,
)] )]
pub struct LanguageName(pub Arc<str>); pub struct LanguageName(SharedString);
impl LanguageName { impl LanguageName {
pub fn new(s: &str) -> Self { pub fn new(s: &str) -> Self {
Self(Arc::from(s)) Self(SharedString::new(s))
} }
pub fn from_proto(s: String) -> Self { pub fn from_proto(s: String) -> Self {
Self(Arc::from(s)) Self(SharedString::from(s))
} }
pub fn to_proto(self) -> String { pub fn to_proto(self) -> String {
self.0.to_string() self.0.to_string()
@ -57,6 +57,18 @@ impl LanguageName {
} }
} }
impl From<LanguageName> for SharedString {
fn from(value: LanguageName) -> Self {
value.0
}
}
impl AsRef<str> for LanguageName {
fn as_ref(&self) -> &str {
self.0.as_ref()
}
}
impl Borrow<str> for LanguageName { impl Borrow<str> for LanguageName {
fn borrow(&self) -> &str { fn borrow(&self) -> &str {
self.0.as_ref() self.0.as_ref()
@ -71,7 +83,7 @@ impl std::fmt::Display for LanguageName {
impl<'a> From<&'a str> for LanguageName { impl<'a> From<&'a str> for LanguageName {
fn from(str: &'a str) -> LanguageName { fn from(str: &'a str) -> LanguageName {
LanguageName(str.into()) LanguageName(SharedString::new(str))
} }
} }
@ -657,7 +669,7 @@ impl LanguageRegistry {
.iter() .iter()
.any(|suffix| path_suffixes.contains(&Some(suffix.as_str()))); .any(|suffix| path_suffixes.contains(&Some(suffix.as_str())));
let custom_suffixes = user_file_types 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); .unwrap_or(&empty);
let path_matches_custom_suffix = path_suffixes let path_matches_custom_suffix = path_suffixes
.iter() .iter()

View file

@ -141,7 +141,7 @@ impl LanguageSelectorDelegate {
let need_icon = FileFinderSettings::get_global(cx).file_icons; let need_icon = FileFinderSettings::get_global(cx).file_icons;
if let Some(buffer_language) = buffer_language { if let Some(buffer_language) = buffer_language {
let buffer_language_name = buffer_language.name(); 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)"); label.push_str(" (current)");
let icon = need_icon let icon = need_icon
.then(|| self.language_icon(&buffer_language.config().matcher, cx)) .then(|| self.language_icon(&buffer_language.config().matcher, cx))
@ -154,7 +154,7 @@ impl LanguageSelectorDelegate {
let language_name = LanguageName::new(mat.string.as_str()); let language_name = LanguageName::new(mat.string.as_str());
match self match self
.language_registry .language_registry
.available_language_for_name(&language_name.0) .available_language_for_name(language_name.as_ref())
{ {
Some(available_language) => { Some(available_language) => {
let icon = self.language_icon(available_language.matcher(), cx); let icon = self.language_icon(available_language.matcher(), cx);

View file

@ -499,7 +499,7 @@ impl SyntaxTreeToolbarItemView {
fn render_header(active_layer: &OwnedSyntaxLayer) -> ButtonLike { fn render_header(active_layer: &OwnedSyntaxLayer) -> ButtonLike {
ButtonLike::new("syntax tree header") 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()))) .child(Label::new(format_node_range(active_layer.node())))
} }
} }

View file

@ -86,7 +86,7 @@ impl SignatureHelp {
} else { } else {
let markdown = markdown.join(str_for_join); let markdown = markdown.join(str_for_join);
let language_name = language let language_name = language
.map(|n| n.name().0.to_lowercase()) .map(|n| n.name().as_ref().to_lowercase())
.unwrap_or_default(); .unwrap_or_default();
let markdown = if function_options_count >= 2 { let markdown = if function_options_count >= 2 {

View file

@ -2579,7 +2579,7 @@ impl Project {
language_name: LanguageName, language_name: LanguageName,
) -> Option<SharedString> { ) -> Option<SharedString> {
languages languages
.language_for_name(&language_name.0) .language_for_name(language_name.as_ref())
.await .await
.ok()? .ok()?
.toolchain_lister() .toolchain_lister()

View file

@ -10,7 +10,7 @@ use std::{
use anyhow::{Context as _, Result}; use anyhow::{Context as _, Result};
use collections::{HashMap, HashSet, VecDeque}; use collections::{HashMap, HashSet, VecDeque};
use gpui::{App, AppContext as _, Entity, Task}; use gpui::{App, AppContext as _, Entity, SharedString, Task};
use itertools::Itertools; use itertools::Itertools;
use language::{ContextProvider, File, Language, LanguageToolchainStore, Location}; use language::{ContextProvider, File, Language, LanguageToolchainStore, Location};
use settings::{parse_json_with_comments, SettingsLocation}; use settings::{parse_json_with_comments, SettingsLocation};
@ -53,7 +53,7 @@ pub enum TaskSourceKind {
abs_path: PathBuf, abs_path: PathBuf,
}, },
/// Languages-specific tasks coming from extensions. /// Languages-specific tasks coming from extensions.
Language { name: Arc<str> }, Language { name: SharedString },
} }
impl TaskSourceKind { impl TaskSourceKind {
@ -91,7 +91,7 @@ impl Inventory {
cx: &App, cx: &App,
) -> Vec<(TaskSourceKind, TaskTemplate)> { ) -> Vec<(TaskSourceKind, TaskTemplate)> {
let task_source_kind = language.as_ref().map(|language| TaskSourceKind::Language { 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 global_tasks = self.global_templates_from_settings();
let language_tasks = language let language_tasks = language
@ -124,7 +124,7 @@ impl Inventory {
.as_ref() .as_ref()
.and_then(|location| location.buffer.read(cx).language_at(location.range.start)); .and_then(|location| location.buffer.read(cx).language_at(location.range.start));
let task_source_kind = language.as_ref().map(|language| TaskSourceKind::Language { let task_source_kind = language.as_ref().map(|language| TaskSourceKind::Language {
name: language.name().0, name: language.name().into(),
}); });
let file = location let file = location
.as_ref() .as_ref()

View file

@ -316,7 +316,10 @@ impl LocalToolchainStore {
cx.background_executor() cx.background_executor()
.spawn(async move { .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()?; let toolchains = language.toolchain_lister()?;
Some(toolchains.list(root.to_path_buf(), project_env).await) Some(toolchains.list(root.to_path_buf(), project_env).await)
}) })

View file

@ -224,7 +224,7 @@ impl PromptBuilder {
buffer: BufferSnapshot, buffer: BufferSnapshot,
range: Range<usize>, range: Range<usize>,
) -> Result<String, RenderError> { ) -> Result<String, RenderError> {
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", None | Some("Markdown" | "Plain Text") => "text",
Some(_) => "code", Some(_) => "code",
}; };

View file

@ -454,7 +454,7 @@ fn markdown_code_blocks(buffer: &BufferSnapshot, range: Range<Point>) -> Vec<Ran
} }
fn language_supported(language: &Arc<Language>) -> bool { fn language_supported(language: &Arc<Language>) -> bool {
match language.name().0.as_ref() { match language.name().as_ref() {
"TypeScript" | "Python" => true, "TypeScript" | "Python" => true,
_ => false, _ => false,
} }

View file

@ -1088,7 +1088,7 @@ impl WorkspaceDb {
.context("Preparing insertion")?; .context("Preparing insertion")?;
let toolchain: Vec<(String, String, String)> = 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 { Ok(toolchain.into_iter().next().and_then(|(name, path, raw_json)| Some(Toolchain {
name: name.into(), name: name.into(),
@ -1144,7 +1144,7 @@ impl WorkspaceDb {
insert(( insert((
workspace_id, workspace_id,
worktree_id.to_usize(), worktree_id.to_usize(),
toolchain.language_name.0.as_ref(), toolchain.language_name.as_ref(),
toolchain.name.as_ref(), toolchain.name.as_ref(),
toolchain.path.as_ref(), toolchain.path.as_ref(),
))?; ))?;

View file

@ -69,7 +69,7 @@ impl QuickActionBar {
return self.render_repl_launch_menu(spec, cx); return self.render_repl_launch_menu(spec, cx);
} }
SessionSupport::RequiresSetup(language) => { SessionSupport::RequiresSetup(language) => {
return self.render_repl_setup(&language.0, cx); return self.render_repl_setup(language.as_ref(), cx);
} }
SessionSupport::Unsupported => return None, SessionSupport::Unsupported => return None,
}; };