Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'src/edi/wsedit.rs')
| -rw-r--r-- | src/edi/wsedit.rs | 312 |
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)| { |