Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-view/src/handlers/lsp.rs')
-rw-r--r--helix-view/src/handlers/lsp.rs67
1 files changed, 46 insertions, 21 deletions
diff --git a/helix-view/src/handlers/lsp.rs b/helix-view/src/handlers/lsp.rs
index beb106b2..d817a423 100644
--- a/helix-view/src/handlers/lsp.rs
+++ b/helix-view/src/handlers/lsp.rs
@@ -1,6 +1,7 @@
use crate::editor::Action;
use crate::Editor;
use crate::{DocumentId, ViewId};
+use helix_core::Uri;
use helix_lsp::util::generate_transaction_from_edits;
use helix_lsp::{lsp, OffsetEncoding};
@@ -54,18 +55,30 @@ pub struct ApplyEditError {
pub enum ApplyEditErrorKind {
DocumentChanged,
FileNotFound,
- UnknownURISchema,
+ InvalidUrl(helix_core::uri::UrlConversionError),
IoError(std::io::Error),
// TODO: check edits before applying and propagate failure
// InvalidEdit,
}
+impl From<std::io::Error> for ApplyEditErrorKind {
+ fn from(err: std::io::Error) -> Self {
+ ApplyEditErrorKind::IoError(err)
+ }
+}
+
+impl From<helix_core::uri::UrlConversionError> for ApplyEditErrorKind {
+ fn from(err: helix_core::uri::UrlConversionError) -> Self {
+ ApplyEditErrorKind::InvalidUrl(err)
+ }
+}
+
impl ToString for ApplyEditErrorKind {
fn to_string(&self) -> String {
match self {
ApplyEditErrorKind::DocumentChanged => "document has changed".to_string(),
ApplyEditErrorKind::FileNotFound => "file not found".to_string(),
- ApplyEditErrorKind::UnknownURISchema => "URI schema not supported".to_string(),
+ ApplyEditErrorKind::InvalidUrl(err) => err.to_string(),
ApplyEditErrorKind::IoError(err) => err.to_string(),
}
}
@@ -74,25 +87,28 @@ impl ToString for ApplyEditErrorKind {
impl Editor {
fn apply_text_edits(
&mut self,
- uri: &helix_lsp::Url,
+ url: &helix_lsp::Url,
version: Option<i32>,
text_edits: Vec<lsp::TextEdit>,
offset_encoding: OffsetEncoding,
) -> Result<(), ApplyEditErrorKind> {
- let path = match uri.to_file_path() {
- Ok(path) => path,
- Err(_) => {
- let err = format!("unable to convert URI to filepath: {}", uri);
- log::error!("{}", err);
- self.set_error(err);
- return Err(ApplyEditErrorKind::UnknownURISchema);
+ let uri = match Uri::try_from(url) {
+ Ok(uri) => uri,
+ Err(err) => {
+ log::error!("{err}");
+ return Err(err.into());
}
};
+ let path = uri.as_path().expect("URIs are valid paths");
- let doc_id = match self.open(&path, Action::Load) {
+ let doc_id = match self.open(path, Action::Load) {
Ok(doc_id) => doc_id,
Err(err) => {
- let err = format!("failed to open document: {}: {}", uri, err);
+ let err = format!(
+ "failed to open document: {}: {}",
+ path.to_string_lossy(),
+ err
+ );
log::error!("{}", err);
self.set_error(err);
return Err(ApplyEditErrorKind::FileNotFound);
@@ -158,9 +174,9 @@ impl Editor {
for (i, operation) in operations.iter().enumerate() {
match operation {
lsp::DocumentChangeOperation::Op(op) => {
- self.apply_document_resource_op(op).map_err(|io| {
+ self.apply_document_resource_op(op).map_err(|err| {
ApplyEditError {
- kind: ApplyEditErrorKind::IoError(io),
+ kind: err,
failed_change_idx: i,
}
})?;
@@ -214,12 +230,18 @@ impl Editor {
Ok(())
}
- fn apply_document_resource_op(&mut self, op: &lsp::ResourceOp) -> std::io::Result<()> {
+ fn apply_document_resource_op(
+ &mut self,
+ op: &lsp::ResourceOp,
+ ) -> Result<(), ApplyEditErrorKind> {
use lsp::ResourceOp;
use std::fs;
+ // NOTE: If `Uri` gets another variant than `Path`, the below `expect`s
+ // may no longer be valid.
match op {
ResourceOp::Create(op) => {
- let path = op.uri.to_file_path().unwrap();
+ let uri = Uri::try_from(&op.uri)?;
+ let path = uri.as_path_buf().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)
});
@@ -236,7 +258,8 @@ impl Editor {
}
}
ResourceOp::Delete(op) => {
- let path = op.uri.to_file_path().unwrap();
+ let uri = Uri::try_from(&op.uri)?;
+ let path = uri.as_path_buf().expect("URIs are valid paths");
if path.is_dir() {
let recursive = op
.options
@@ -251,17 +274,19 @@ impl Editor {
}
self.language_servers.file_event_handler.file_changed(path);
} else if path.is_file() {
- fs::remove_file(&path)?;
+ fs::remove_file(path)?;
}
}
ResourceOp::Rename(op) => {
- let from = op.old_uri.to_file_path().unwrap();
- let to = op.new_uri.to_file_path().unwrap();
+ let from_uri = Uri::try_from(&op.old_uri)?;
+ let from = from_uri.as_path().expect("URIs are valid paths");
+ let to_uri = Uri::try_from(&op.new_uri)?;
+ let to = to_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)
});
if !ignore_if_exists || !to.exists() {
- self.move_path(&from, &to)?;
+ self.move_path(from, to)?;
}
}
}