Unnamed repository; edit this file 'description' to name the repository.
Make helix_core::Uri cheap to clone
We clone this type very often in LSP pickers, for example diagnostics and symbols. We can use a single Arc in many cases to avoid the unnecessary clones.
Michael Davis 2024-09-03
parent 48e9357 · commit da2b0a7
-rw-r--r--helix-core/src/uri.rs25
-rw-r--r--helix-view/src/handlers/lsp.rs18
2 files changed, 17 insertions, 26 deletions
diff --git a/helix-core/src/uri.rs b/helix-core/src/uri.rs
index ddb9fb7a..cbe0fadd 100644
--- a/helix-core/src/uri.rs
+++ b/helix-core/src/uri.rs
@@ -1,15 +1,18 @@
use std::{
fmt,
path::{Path, PathBuf},
+ sync::Arc,
};
/// A generic pointer to a file location.
///
/// Currently this type only supports paths to local files.
+///
+/// Cloning this type is cheap: the internal representation uses an Arc.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[non_exhaustive]
pub enum Uri {
- File(PathBuf),
+ File(Arc<Path>),
}
impl Uri {
@@ -26,27 +29,11 @@ impl Uri {
Self::File(path) => Some(path),
}
}
-
- pub fn as_path_buf(self) -> Option<PathBuf> {
- match self {
- Self::File(path) => Some(path),
- }
- }
}
impl From<PathBuf> for Uri {
fn from(path: PathBuf) -> Self {
- Self::File(path)
- }
-}
-
-impl TryFrom<Uri> for PathBuf {
- type Error = ();
-
- fn try_from(uri: Uri) -> Result<Self, Self::Error> {
- match uri {
- Uri::File(path) => Ok(path),
- }
+ Self::File(path.into())
}
}
@@ -93,7 +80,7 @@ impl std::error::Error for UrlConversionError {}
fn convert_url_to_uri(url: &url::Url) -> Result<Uri, UrlConversionErrorKind> {
if url.scheme() == "file" {
url.to_file_path()
- .map(|path| Uri::File(helix_stdx::path::normalize(path)))
+ .map(|path| Uri::File(helix_stdx::path::normalize(path).into()))
.map_err(|_| UrlConversionErrorKind::UnableToConvert)
} else {
Err(UrlConversionErrorKind::UnsupportedScheme)
diff --git a/helix-view/src/handlers/lsp.rs b/helix-view/src/handlers/lsp.rs
index 6aff2e50..1fd2289d 100644
--- a/helix-view/src/handlers/lsp.rs
+++ b/helix-view/src/handlers/lsp.rs
@@ -243,7 +243,7 @@ impl Editor {
match op {
ResourceOp::Create(op) => {
let uri = Uri::try_from(&op.uri)?;
- let path = uri.as_path_buf().expect("URIs are valid paths");
+ let path = uri.as_path().expect("URIs are valid paths");
let ignore_if_exists = op.options.as_ref().map_or(false, |options| {
!options.overwrite.unwrap_or(false) && options.ignore_if_exists.unwrap_or(false)
});
@@ -255,13 +255,15 @@ impl Editor {
}
}
- fs::write(&path, [])?;
- self.language_servers.file_event_handler.file_changed(path);
+ fs::write(path, [])?;
+ self.language_servers
+ .file_event_handler
+ .file_changed(path.to_path_buf());
}
}
ResourceOp::Delete(op) => {
let uri = Uri::try_from(&op.uri)?;
- let path = uri.as_path_buf().expect("URIs are valid paths");
+ let path = uri.as_path().expect("URIs are valid paths");
if path.is_dir() {
let recursive = op
.options
@@ -270,11 +272,13 @@ impl Editor {
.unwrap_or(false);
if recursive {
- fs::remove_dir_all(&path)?
+ fs::remove_dir_all(path)?
} else {
- fs::remove_dir(&path)?
+ fs::remove_dir(path)?
}
- self.language_servers.file_event_handler.file_changed(path);
+ self.language_servers
+ .file_event_handler
+ .file_changed(path.to_path_buf());
} else if path.is_file() {
fs::remove_file(path)?;
}