Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'src/edi/wsedit.rs')
-rw-r--r--src/edi/wsedit.rs312
1 files changed, 257 insertions, 55 deletions
diff --git a/src/edi/wsedit.rs b/src/edi/wsedit.rs
index eb11a8b..55e0827 100644
--- a/src/edi/wsedit.rs
+++ b/src/edi/wsedit.rs
@@ -5,6 +5,10 @@ use lsp_types::*;
use rootcause::prelude::{IteratorExt, ResultExt};
use rootcause::report;
use ropey::Rope;
+use rust_analyzer::lsp::ext::{
+ SnippetDocumentChangeOperation, SnippetTextDocumentEdit,
+ SnippetWorkspaceEdit,
+};
use super::*;
use crate::error::WDebug;
@@ -52,23 +56,221 @@ impl Editor {
) -> rootcause::Result<()> {
self.apply_tds(
&text_document
+ .text_document_identifier
.uri
.to_file_path()
.map_err(|_| report!("sad"))?,
edits,
- TextArea::apply_snippet_tedit,
- TextArea::apply_snippet_tedit_raw,
+ |t, e| match e {
+ Edit::AnnotatedTextEdit(AnnotatedTextEdit {
+ text_edit,
+ ..
+ })
+ | Edit::TextEdit(text_edit) =>
+ Ok(drop(t.apply(text_edit)?)),
+ Edit::SnippetTextEdit(SnippetTextEdit {
+ range,
+ snippet,
+ annotation_id,
+ }) => {
+ let x2 = rust_analyzer::lsp::ext::SnippetTextEdit {
+ range: *range,
+ new_text: snippet.value.clone(),
+ insert_text_format: None,
+ annotation_id: annotation_id.clone(),
+ };
+ t.apply_snippet_tedit(&x2)
+ }
+ },
+ |e, t| match e {
+ Edit::AnnotatedTextEdit(AnnotatedTextEdit {
+ text_edit,
+ ..
+ })
+ | Edit::TextEdit(text_edit) =>
+ TextArea::apply_raw(text_edit, t),
+ Edit::SnippetTextEdit(SnippetTextEdit {
+ range,
+ snippet,
+ annotation_id,
+ }) => {
+ let x2 = rust_analyzer::lsp::ext::SnippetTextEdit {
+ range: *range,
+ new_text: snippet.value.clone(),
+ insert_text_format: None,
+ annotation_id: annotation_id.clone(),
+ };
+ TextArea::apply_snippet_tedit_raw(&x2, t)
+ }
+ },
+ // TextArea::apply_snippet_tedit,
+ // TextArea::apply_snippet_tedit_raw,
)
}
- fn apply_dco(
+ fn apply_sdc(
&mut self,
- op: DocumentChangeOperation,
+ op: SnippetDocumentChangeOperation,
) -> rootcause::Result<()> {
match op.clone() {
- DocumentChangeOperation::Edit(t) => self.apply_tde(t)?,
- DocumentChangeOperation::Op(ResourceOp::Create(
- CreateFile { uri, options, .. },
- )) => {
+ SnippetDocumentChangeOperation::Edit(
+ SnippetTextDocumentEdit { text_document, edits },
+ ) => self.apply_tds(
+ &text_document
+ .text_document_identifier
+ .uri
+ .to_file_path()
+ .map_err(|_| report!("sad"))?,
+ edits,
+ TextArea::apply_snippet_tedit,
+ TextArea::apply_snippet_tedit_raw,
+ ),
+ SnippetDocumentChangeOperation::Change(dc) =>
+ self.apply_dc(dc),
+ }
+ }
+ // pub fn apply_sdc(
+ // &mut self,
+ // x: SnippetDocumentChangeOperation,
+ // ) -> rootcause::Result<()> {
+ // match x {
+ // // self.apply_tde(x)
+ // DocumentChange::TextDocumentEdit(text_document_edit) =>
+ // self.apply_tde(text_document_edit)?,
+ // DocumentChange::CreateFile(CreateFile {
+ // uri,
+ // options,
+ // ..
+ // }) => {
+ // let f = uri
+ // .to_file_path()
+ // .map_err(|()| report!("not path"))?;
+ // let mut opts = OpenOptions::new();
+ // opts.write(true)
+ // // .create(true)
+ // .create(matches!(
+ // options,
+ // Some(CreateFileOptions {
+ // ignore_if_exists: Some(true) | None,
+ // ..
+ // }) | None
+ // ))
+ // .create_new(matches!(
+ // options,
+ // Some(CreateFileOptions {
+ // ignore_if_exists: Some(false),
+ // ..
+ // })
+ // ))
+ // .truncate(true);
+ // match opts.open(&f) {
+ // Ok(_f) => {}
+ // Err(e)
+ // if let Some(CreateFileOptions {
+ // overwrite: Some(true),
+ // ..
+ // }) = options
+ // && e.kind()
+ // == std::io::ErrorKind::AlreadyExists => {}
+ // Err(e) =>
+ // Err(e)
+ // .context_custom::<WDebug, _>(f)
+ // .context_custom::<WDebug, _>((opts, options))?,
+ // };
+ // }
+ // DocumentChange::RenameFile(RenameFile {
+ // old_uri,
+ // new_uri,
+ // options,
+ // annotation_id,
+ // }) => {
+ // let old_f = old_uri
+ // .to_file_path()
+ // .map_err(|()| report!("not path"))?;
+ // let new_f = new_uri
+ // .to_file_path()
+ // .map_err(|()| report!("not path"))?;
+
+ // // FIXME: overwrite
+ // if let Some(p) = new_f.parent()
+ // && !p.exists()
+ // {
+ // std::fs::create_dir_all(p)?;
+ // }
+ // match std::fs::rename(&old_f, &new_f) {
+ // Err(e)
+ // if e.kind()
+ // == std::io::ErrorKind::IsADirectory =>
+ // {
+ // do yeet report!("unhandled case: dir rename");
+ // }
+ // Err(e)
+ // if let Some(RenameFileOptions {
+ // ignore_if_exists: Some(true),
+ // ..
+ // }) = options
+ // && e.kind()
+ // == std::io::ErrorKind::AlreadyExists => {}
+ // Ok(_) => {}
+ // Err(e) => Err(e).context_with(|| {
+ // format!("renaming {old_f:?} to {new_f:?}")
+ // })?,
+ // }
+ // if let Some(f) = self.files.get_mut(&old_f)
+ // // .or(Some(self).filter(|x| x.origin == Some(old_f)))
+ // {
+ // f.bar.last_action =
+ // annotation_id.unwrap_or("renamed".into());
+ // f.origin = Some(new_f);
+ // f.mtime = Editor::modify(f.origin.as_deref());
+ // } else if self.origin == Some(old_f) {
+ // self.bar.last_action =
+ // annotation_id.unwrap_or("renamed".into());
+ // self.origin = Some(new_f);
+ // self.mtime = Editor::modify(self.origin.as_deref());
+ // }
+ // }
+ // DocumentChange::DeleteFile(DeleteFile {
+ // uri,
+ // options,
+ // ..
+ // }) => {
+ // let f = uri
+ // .to_file_path()
+ // .map_err(|()| report!("not path"))?;
+ // match std::fs::remove_file(&f) {
+ // Ok(()) => (),
+ // Err(e)
+ // if e.kind()
+ // == std::io::ErrorKind::IsADirectory =>
+ // {
+ // std::fs::remove_dir_all(f)?;
+ // }
+ // Err(e)
+ // if let Some(DeleteFileOptions {
+ // ignore_if_not_exists: Some(true),
+ // ..
+ // }) = options
+ // && e.kind()
+ // == std::io::ErrorKind::NotFound => {}
+ // Err(e) => do yeet e,
+ // }
+ // }
+ // };
+ // Ok(())
+ // }
+ pub fn apply_dc(
+ &mut self,
+ x: DocumentChange,
+ ) -> rootcause::Result<()> {
+ match x {
+ // self.apply_tde(x)
+ DocumentChange::TextDocumentEdit(text_document_edit) =>
+ self.apply_tde(text_document_edit)?,
+ DocumentChange::CreateFile(CreateFile {
+ uri,
+ options,
+ ..
+ }) => {
let f = uri
.to_file_path()
.map_err(|()| report!("not path"))?;
@@ -105,9 +307,12 @@ impl Editor {
.context_custom::<WDebug, _>((opts, options))?,
};
}
- DocumentChangeOperation::Op(ResourceOp::Rename(
- RenameFile { old_uri, new_uri, options, annotation_id },
- )) => {
+ DocumentChange::RenameFile(RenameFile {
+ old_uri,
+ new_uri,
+ options,
+ annotation_id,
+ }) => {
let old_f = old_uri
.to_file_path()
.map_err(|()| report!("not path"))?;
@@ -154,31 +359,11 @@ impl Editor {
self.mtime = Editor::modify(self.origin.as_deref());
}
}
- DocumentChangeOperation::Op(ResourceOp::Delete(
- DeleteFile {
- uri,
- options:
- Some(DeleteFileOptions {
- recursive: Some(true), // ??? seems redundant
- ignore_if_not_exists,
- ..
- }),
- },
- )) => {
- let f = uri
- .to_file_path()
- .map_err(|()| report!("not path"))?;
- match std::fs::remove_dir_all(f) {
- Ok(()) => (),
- Err(e)
- if e.kind() == std::io::ErrorKind::NotFound
- && ignore_if_not_exists == Some(true) => {}
- Err(e) => do yeet e,
- }
- }
- DocumentChangeOperation::Op(ResourceOp::Delete(
- DeleteFile { uri, options },
- )) => {
+ DocumentChange::DeleteFile(DeleteFile {
+ uri,
+ options,
+ ..
+ }) => {
let f = uri
.to_file_path()
.map_err(|()| report!("not path"))?;
@@ -200,8 +385,41 @@ impl Editor {
Err(e) => do yeet e,
}
}
+ };
+ Ok(())
+ }
+ pub fn apply_swsedit(
+ &mut self,
+ x: SnippetWorkspaceEdit,
+ ) -> rootcause::Result<()> {
+ match x {
+ SnippetWorkspaceEdit { document_changes: Some(x), .. } => x
+ .into_iter()
+ .map(|x| self.apply_sdc(x))
+ .collect_reports()
+ .context("couldnt apply one or more wsedits")?,
+ SnippetWorkspaceEdit { changes: Some(x), .. } => x
+ .into_iter()
+ .map(|(p, e)| {
+ self.apply_tds(
+ &p.to_file_path().map_err(|_| {
+ report!("evil path")
+ .context_custom::<WDebug, _>(e.clone())
+ })?,
+ e.clone(),
+ |x, y| x.apply(y).map(drop),
+ TextArea::apply_raw,
+ )
+ .context_custom::<WDebug, _>(e)
+ })
+ .collect_reports()
+ .context("couldnt apply one or more fs operations")?,
+ x =>
+ do yeet report!("strange workspace edit")
+ .context_custom::<WDebug, _>(x),
}
-
+ change!(self);
+ self.hist.record(&self.text);
Ok(())
}
#[must_use]
@@ -210,27 +428,11 @@ impl Editor {
x: WorkspaceEdit,
) -> rootcause::Result<()> {
match x {
- WorkspaceEdit {
- document_changes: Some(DocumentChanges::Edits(x)),
- ..
- } => x
+ WorkspaceEdit { document_changes: Some(x), .. } => x
.into_iter()
- .map(|x| self.apply_tde(x))
+ .map(|x| self.apply_dc(x))
.collect_reports()
.context("couldnt apply one or more wsedits")?,
- WorkspaceEdit {
- document_changes: Some(DocumentChanges::Operations(x)),
- ..
- } => x
- .clone()
- .into_iter()
- .map(|op: DocumentChangeOperation| {
- self.apply_dco(op.clone())
- .context_custom::<WDebug, _>(op)
- })
- .collect_reports()
- .context("couldnt apply one or more fs operations")
- .context_custom::<WDebug, _>(x)?,
WorkspaceEdit { changes: Some(x), .. } => x
.into_iter()
.map(|(p, e)| {