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.
This commit is contained in:
Michael Davis 2024-08-08 11:17:20 -04:00
parent 48e9357788
commit da2b0a7484
No known key found for this signature in database
2 changed files with 17 additions and 26 deletions

View File

@ -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 @@ pub fn as_path(&self) -> Option<&Path> {
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)

View File

@ -243,7 +243,7 @@ fn apply_document_resource_op(
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 @@ fn apply_document_resource_op(
}
}
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 @@ fn apply_document_resource_op(
.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)?;
}