aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_editor/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_editor/src')
-rw-r--r--crates/ra_editor/src/code_actions.rs12
-rw-r--r--crates/ra_editor/src/edit.rs83
-rw-r--r--crates/ra_editor/src/lib.rs4
-rw-r--r--crates/ra_editor/src/typing.rs26
4 files changed, 23 insertions, 102 deletions
diff --git a/crates/ra_editor/src/code_actions.rs b/crates/ra_editor/src/code_actions.rs
index 6979251d1..688a89c3d 100644
--- a/crates/ra_editor/src/code_actions.rs
+++ b/crates/ra_editor/src/code_actions.rs
@@ -8,11 +8,11 @@ use ra_syntax::{
8 SyntaxNodeRef, TextRange, TextUnit, 8 SyntaxNodeRef, TextRange, TextUnit,
9}; 9};
10 10
11use crate::{find_node_at_offset, Edit, EditBuilder}; 11use crate::{find_node_at_offset, TextEdit, TextEditBuilder};
12 12
13#[derive(Debug)] 13#[derive(Debug)]
14pub struct LocalEdit { 14pub struct LocalEdit {
15 pub edit: Edit, 15 pub edit: TextEdit,
16 pub cursor_position: Option<TextUnit>, 16 pub cursor_position: Option<TextUnit>,
17} 17}
18 18
@@ -26,7 +26,7 @@ pub fn flip_comma<'a>(
26 let prev = non_trivia_sibling(comma, Direction::Prev)?; 26 let prev = non_trivia_sibling(comma, Direction::Prev)?;
27 let next = non_trivia_sibling(comma, Direction::Next)?; 27 let next = non_trivia_sibling(comma, Direction::Next)?;
28 Some(move || { 28 Some(move || {
29 let mut edit = EditBuilder::new(); 29 let mut edit = TextEditBuilder::new();
30 edit.replace(prev.range(), next.text().to_string()); 30 edit.replace(prev.range(), next.text().to_string());
31 edit.replace(next.range(), prev.text().to_string()); 31 edit.replace(next.range(), prev.text().to_string());
32 LocalEdit { 32 LocalEdit {
@@ -49,7 +49,7 @@ pub fn add_derive<'a>(
49 .filter(|(name, _arg)| name == "derive") 49 .filter(|(name, _arg)| name == "derive")
50 .map(|(_name, arg)| arg) 50 .map(|(_name, arg)| arg)
51 .next(); 51 .next();
52 let mut edit = EditBuilder::new(); 52 let mut edit = TextEditBuilder::new();
53 let offset = match derive_attr { 53 let offset = match derive_attr {
54 None => { 54 None => {
55 edit.insert(node_start, "#[derive()]\n".to_string()); 55 edit.insert(node_start, "#[derive()]\n".to_string());
@@ -82,7 +82,7 @@ pub fn add_impl<'a>(
82 82
83 Some(move || { 83 Some(move || {
84 let type_params = nominal.type_param_list(); 84 let type_params = nominal.type_param_list();
85 let mut edit = EditBuilder::new(); 85 let mut edit = TextEditBuilder::new();
86 let start_offset = nominal.syntax().range().end(); 86 let start_offset = nominal.syntax().range().end();
87 let mut buf = String::new(); 87 let mut buf = String::new();
88 buf.push_str("\n\nimpl"); 88 buf.push_str("\n\nimpl");
@@ -129,7 +129,7 @@ pub fn introduce_variable<'a>(
129 } 129 }
130 return Some(move || { 130 return Some(move || {
131 let mut buf = String::new(); 131 let mut buf = String::new();
132 let mut edit = EditBuilder::new(); 132 let mut edit = TextEditBuilder::new();
133 133
134 buf.push_str("let var_name = "); 134 buf.push_str("let var_name = ");
135 expr.syntax().text().push_to(&mut buf); 135 expr.syntax().text().push_to(&mut buf);
diff --git a/crates/ra_editor/src/edit.rs b/crates/ra_editor/src/edit.rs
deleted file mode 100644
index 372b8d14c..000000000
--- a/crates/ra_editor/src/edit.rs
+++ /dev/null
@@ -1,83 +0,0 @@
1use crate::{TextRange, TextUnit};
2use ra_syntax::{text_utils::contains_offset_nonstrict, AtomEdit};
3
4#[derive(Debug, Clone)]
5pub struct Edit {
6 atoms: Vec<AtomEdit>,
7}
8
9#[derive(Debug)]
10pub struct EditBuilder {
11 atoms: Vec<AtomEdit>,
12}
13
14impl EditBuilder {
15 pub fn new() -> EditBuilder {
16 EditBuilder { atoms: Vec::new() }
17 }
18 pub fn replace(&mut self, range: TextRange, replace_with: String) {
19 self.atoms.push(AtomEdit::replace(range, replace_with))
20 }
21 pub fn delete(&mut self, range: TextRange) {
22 self.atoms.push(AtomEdit::delete(range))
23 }
24 pub fn insert(&mut self, offset: TextUnit, text: String) {
25 self.atoms.push(AtomEdit::insert(offset, text))
26 }
27 pub fn finish(self) -> Edit {
28 let mut atoms = self.atoms;
29 atoms.sort_by_key(|a| (a.delete.start(), a.delete.end()));
30 for (a1, a2) in atoms.iter().zip(atoms.iter().skip(1)) {
31 assert!(a1.delete.end() <= a2.delete.start())
32 }
33 Edit { atoms }
34 }
35 pub fn invalidates_offset(&self, offset: TextUnit) -> bool {
36 self.atoms
37 .iter()
38 .any(|atom| contains_offset_nonstrict(atom.delete, offset))
39 }
40}
41
42impl Edit {
43 pub fn into_atoms(self) -> Vec<AtomEdit> {
44 self.atoms
45 }
46
47 pub fn apply(&self, text: &str) -> String {
48 let mut total_len = text.len();
49 for atom in self.atoms.iter() {
50 total_len += atom.insert.len();
51 total_len -= u32::from(atom.delete.end() - atom.delete.start()) as usize;
52 }
53 let mut buf = String::with_capacity(total_len);
54 let mut prev = 0;
55 for atom in self.atoms.iter() {
56 let start = u32::from(atom.delete.start()) as usize;
57 let end = u32::from(atom.delete.end()) as usize;
58 if start > prev {
59 buf.push_str(&text[prev..start]);
60 }
61 buf.push_str(&atom.insert);
62 prev = end;
63 }
64 buf.push_str(&text[prev..text.len()]);
65 assert_eq!(buf.len(), total_len);
66 buf
67 }
68
69 pub fn apply_to_offset(&self, offset: TextUnit) -> Option<TextUnit> {
70 let mut res = offset;
71 for atom in self.atoms.iter() {
72 if atom.delete.start() >= offset {
73 break;
74 }
75 if offset < atom.delete.end() {
76 return None;
77 }
78 res += TextUnit::of_str(&atom.insert);
79 res -= atom.delete.len();
80 }
81 Some(res)
82 }
83}
diff --git a/crates/ra_editor/src/lib.rs b/crates/ra_editor/src/lib.rs
index ce080ee97..36cabed25 100644
--- a/crates/ra_editor/src/lib.rs
+++ b/crates/ra_editor/src/lib.rs
@@ -1,5 +1,4 @@
1mod code_actions; 1mod code_actions;
2mod edit;
3mod extend_selection; 2mod extend_selection;
4mod folding_ranges; 3mod folding_ranges;
5mod line_index; 4mod line_index;
@@ -10,14 +9,13 @@ mod typing;
10 9
11pub use self::{ 10pub use self::{
12 code_actions::{add_derive, add_impl, flip_comma, introduce_variable, LocalEdit}, 11 code_actions::{add_derive, add_impl, flip_comma, introduce_variable, LocalEdit},
13 edit::{Edit, EditBuilder},
14 extend_selection::extend_selection, 12 extend_selection::extend_selection,
15 folding_ranges::{folding_ranges, Fold, FoldKind}, 13 folding_ranges::{folding_ranges, Fold, FoldKind},
16 line_index::{LineCol, LineIndex}, 14 line_index::{LineCol, LineIndex},
17 symbols::{file_structure, file_symbols, FileSymbol, StructureNode}, 15 symbols::{file_structure, file_symbols, FileSymbol, StructureNode},
18 typing::{join_lines, on_enter, on_eq_typed}, 16 typing::{join_lines, on_enter, on_eq_typed},
19}; 17};
20pub use ra_syntax::AtomEdit; 18use ra_text_edit::{TextEdit, TextEditBuilder};
21use ra_syntax::{ 19use ra_syntax::{
22 algo::find_leaf_at_offset, 20 algo::find_leaf_at_offset,
23 ast::{self, AstNode, NameOwner}, 21 ast::{self, AstNode, NameOwner},
diff --git a/crates/ra_editor/src/typing.rs b/crates/ra_editor/src/typing.rs
index 01acdda7c..46a6e2d62 100644
--- a/crates/ra_editor/src/typing.rs
+++ b/crates/ra_editor/src/typing.rs
@@ -3,13 +3,14 @@ use std::mem;
3use ra_syntax::{ 3use ra_syntax::{
4 algo::{find_covering_node, find_leaf_at_offset, LeafAtOffset}, 4 algo::{find_covering_node, find_leaf_at_offset, LeafAtOffset},
5 ast, 5 ast,
6 text_utils::{contains_offset_nonstrict, intersect}, 6 text_utils::intersect,
7 AstNode, SourceFileNode, SyntaxKind, 7 AstNode, SourceFileNode, SyntaxKind,
8 SyntaxKind::*, 8 SyntaxKind::*,
9 SyntaxNodeRef, TextRange, TextUnit, 9 SyntaxNodeRef, TextRange, TextUnit,
10}; 10};
11use ra_text_edit::text_utils::contains_offset_nonstrict;
11 12
12use crate::{find_node_at_offset, EditBuilder, LocalEdit}; 13use crate::{find_node_at_offset, TextEditBuilder, LocalEdit};
13 14
14pub fn join_lines(file: &SourceFileNode, range: TextRange) -> LocalEdit { 15pub fn join_lines(file: &SourceFileNode, range: TextRange) -> LocalEdit {
15 let range = if range.is_empty() { 16 let range = if range.is_empty() {
@@ -18,7 +19,7 @@ pub fn join_lines(file: &SourceFileNode, range: TextRange) -> LocalEdit {
18 let pos = match text.find('\n') { 19 let pos = match text.find('\n') {
19 None => { 20 None => {
20 return LocalEdit { 21 return LocalEdit {
21 edit: EditBuilder::new().finish(), 22 edit: TextEditBuilder::new().finish(),
22 cursor_position: None, 23 cursor_position: None,
23 }; 24 };
24 } 25 }
@@ -30,7 +31,7 @@ pub fn join_lines(file: &SourceFileNode, range: TextRange) -> LocalEdit {
30 }; 31 };
31 32
32 let node = find_covering_node(file.syntax(), range); 33 let node = find_covering_node(file.syntax(), range);
33 let mut edit = EditBuilder::new(); 34 let mut edit = TextEditBuilder::new();
34 for node in node.descendants() { 35 for node in node.descendants() {
35 let text = match node.leaf_text() { 36 let text = match node.leaf_text() {
36 Some(text) => text, 37 Some(text) => text,
@@ -72,7 +73,7 @@ pub fn on_enter(file: &SourceFileNode, offset: TextUnit) -> Option<LocalEdit> {
72 let indent = node_indent(file, comment.syntax())?; 73 let indent = node_indent(file, comment.syntax())?;
73 let inserted = format!("\n{}{} ", indent, prefix); 74 let inserted = format!("\n{}{} ", indent, prefix);
74 let cursor_position = offset + TextUnit::of_str(&inserted); 75 let cursor_position = offset + TextUnit::of_str(&inserted);
75 let mut edit = EditBuilder::new(); 76 let mut edit = TextEditBuilder::new();
76 edit.insert(offset, inserted); 77 edit.insert(offset, inserted);
77 Some(LocalEdit { 78 Some(LocalEdit {
78 edit: edit.finish(), 79 edit: edit.finish(),
@@ -122,7 +123,7 @@ pub fn on_eq_typed(file: &SourceFileNode, offset: TextUnit) -> Option<LocalEdit>
122 return None; 123 return None;
123 } 124 }
124 let offset = let_stmt.syntax().range().end(); 125 let offset = let_stmt.syntax().range().end();
125 let mut edit = EditBuilder::new(); 126 let mut edit = TextEditBuilder::new();
126 edit.insert(offset, ";".to_string()); 127 edit.insert(offset, ";".to_string());
127 Some(LocalEdit { 128 Some(LocalEdit {
128 edit: edit.finish(), 129 edit: edit.finish(),
@@ -130,7 +131,12 @@ pub fn on_eq_typed(file: &SourceFileNode, offset: TextUnit) -> Option<LocalEdit>
130 }) 131 })
131} 132}
132 133
133fn remove_newline(edit: &mut EditBuilder, node: SyntaxNodeRef, node_text: &str, offset: TextUnit) { 134fn remove_newline(
135 edit: &mut TextEditBuilder,
136 node: SyntaxNodeRef,
137 node_text: &str,
138 offset: TextUnit,
139) {
134 if node.kind() != WHITESPACE || node_text.bytes().filter(|&b| b == b'\n').count() != 1 { 140 if node.kind() != WHITESPACE || node_text.bytes().filter(|&b| b == b'\n').count() != 1 {
135 // The node is either the first or the last in the file 141 // The node is either the first or the last in the file
136 let suff = &node_text[TextRange::from_to( 142 let suff = &node_text[TextRange::from_to(
@@ -191,7 +197,7 @@ fn is_trailing_comma(left: SyntaxKind, right: SyntaxKind) -> bool {
191 } 197 }
192} 198}
193 199
194fn join_single_expr_block(edit: &mut EditBuilder, node: SyntaxNodeRef) -> Option<()> { 200fn join_single_expr_block(edit: &mut TextEditBuilder, node: SyntaxNodeRef) -> Option<()> {
195 let block = ast::Block::cast(node.parent()?)?; 201 let block = ast::Block::cast(node.parent()?)?;
196 let block_expr = ast::BlockExpr::cast(block.syntax().parent()?)?; 202 let block_expr = ast::BlockExpr::cast(block.syntax().parent()?)?;
197 let expr = single_expr(block)?; 203 let expr = single_expr(block)?;
@@ -269,14 +275,14 @@ fn foo() {
269 fn test_join_lines_lambda_block() { 275 fn test_join_lines_lambda_block() {
270 check_join_lines( 276 check_join_lines(
271 r" 277 r"
272pub fn reparse(&self, edit: &AtomEdit) -> File { 278pub fn reparse(&self, edit: &AtomTextEdit) -> File {
273 <|>self.incremental_reparse(edit).unwrap_or_else(|| { 279 <|>self.incremental_reparse(edit).unwrap_or_else(|| {
274 self.full_reparse(edit) 280 self.full_reparse(edit)
275 }) 281 })
276} 282}
277", 283",
278 r" 284 r"
279pub fn reparse(&self, edit: &AtomEdit) -> File { 285pub fn reparse(&self, edit: &AtomTextEdit) -> File {
280 <|>self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit)) 286 <|>self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit))
281} 287}
282", 288",