From be742a587704f27f4e503c50f549aa9ec1527fcc Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 13 Aug 2018 02:38:34 +0300 Subject: Apply code actions --- crates/libeditor/src/edit.rs | 75 ++++++++++++++++++-------------------------- crates/libeditor/src/lib.rs | 2 +- 2 files changed, 32 insertions(+), 45 deletions(-) (limited to 'crates/libeditor') diff --git a/crates/libeditor/src/edit.rs b/crates/libeditor/src/edit.rs index 163ecf6de..15a2a904f 100644 --- a/crates/libeditor/src/edit.rs +++ b/crates/libeditor/src/edit.rs @@ -1,11 +1,11 @@ use {TextRange, TextUnit}; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Edit { - pub atoms: Vec, + atoms: Vec, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct AtomEdit { pub delete: TextRange, pub insert: String, @@ -22,7 +22,6 @@ impl EditBuilder { } pub fn replace(&mut self, range: TextRange, replacement: String) { - let range = self.translate(range); self.atoms.push(AtomEdit { delete: range, insert: replacement }) } @@ -35,59 +34,47 @@ impl EditBuilder { } pub fn finish(self) -> Edit { - Edit { atoms: self.atoms } - } - - fn translate(&self, range: TextRange) -> TextRange { - let mut range = range; - for atom in self.atoms.iter() { - range = atom.apply_to_range(range) - .expect("conflicting edits"); + let mut atoms = self.atoms; + atoms.sort_by_key(|a| a.delete.start()); + for (a1, a2) in atoms.iter().zip(atoms.iter().skip(1)) { + assert!(a1.end() <= a2.start()) } - range + Edit { atoms } } } impl Edit { + pub fn into_atoms(self) -> Vec { + self.atoms + } + pub fn apply(&self, text: &str) -> String { - let mut text = text.to_owned(); + let mut total_len = text.len(); for atom in self.atoms.iter() { - text = atom.apply(&text); + total_len += atom.insert.len(); + total_len -= atom.end() - atom.start(); } - text + let mut buf = String::with_capacity(total_len); + let mut prev = 0; + for atom in self.atoms.iter() { + if atom.start() > prev { + buf.push_str(&text[prev..atom.start()]); + } + buf.push_str(&atom.insert); + prev = atom.end(); + } + buf.push_str(&text[prev..text.len()]); + assert_eq!(buf.len(), total_len); + buf } } impl AtomEdit { - fn apply(&self, text: &str) -> String { - let prefix = &text[ - TextRange::from_to(0.into(), self.delete.start()) - ]; - let suffix = &text[ - TextRange::from_to(self.delete.end(), TextUnit::of_str(text)) - ]; - let mut res = String::with_capacity(prefix.len() + self.insert.len() + suffix.len()); - res.push_str(prefix); - res.push_str(&self.insert); - res.push_str(suffix); - res + fn start(&self) -> usize { + u32::from(self.delete.start()) as usize } - fn apply_to_position(&self, pos: TextUnit) -> Option { - if pos <= self.delete.start() { - return Some(pos); - } - if pos < self.delete.end() { - return None; - } - Some(pos - self.delete.len() + TextUnit::of_str(&self.insert)) - } - - fn apply_to_range(&self, range: TextRange) -> Option { - Some(TextRange::from_to( - self.apply_to_position(range.start())?, - self.apply_to_position(range.end())?, - )) + fn end(&self) -> usize { + u32::from(self.delete.end()) as usize } } - diff --git a/crates/libeditor/src/lib.rs b/crates/libeditor/src/lib.rs index 103f32190..1e88f1471 100644 --- a/crates/libeditor/src/lib.rs +++ b/crates/libeditor/src/lib.rs @@ -19,7 +19,7 @@ pub use self::{ line_index::{LineIndex, LineCol}, extend_selection::extend_selection, symbols::{FileSymbol, file_symbols}, - edit::{EditBuilder, Edit}, + edit::{EditBuilder, Edit, AtomEdit}, code_actions::{flip_comma}, }; -- cgit v1.2.3