aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_ide/src/ssr.rs24
-rw-r--r--crates/ra_syntax/src/lib.rs3
-rw-r--r--crates/ra_syntax/src/parsing/reparsing.rs14
-rw-r--r--crates/ra_text_edit/src/lib.rs21
4 files changed, 42 insertions, 20 deletions
diff --git a/crates/ra_ide/src/ssr.rs b/crates/ra_ide/src/ssr.rs
index 7b93ff2d2..e213da606 100644
--- a/crates/ra_ide/src/ssr.rs
+++ b/crates/ra_ide/src/ssr.rs
@@ -401,16 +401,22 @@ fn render_replace(
401 ignored_comments: &Vec<Comment>, 401 ignored_comments: &Vec<Comment>,
402 template: &SsrTemplate, 402 template: &SsrTemplate,
403) -> String { 403) -> String {
404 let mut builder = TextEditBuilder::default(); 404 let edit = {
405 for element in template.template.descendants() { 405 let mut builder = TextEditBuilder::default();
406 if let Some(var) = template.placeholders.get(&element) { 406 for element in template.template.descendants() {
407 builder.replace(element.text_range(), binding[var].to_string()) 407 if let Some(var) = template.placeholders.get(&element) {
408 builder.replace(element.text_range(), binding[var].to_string())
409 }
408 } 410 }
409 } 411 for comment in ignored_comments {
410 for comment in ignored_comments { 412 builder.insert(template.template.text_range().end(), comment.syntax().to_string())
411 builder.insert(template.template.text_range().end(), comment.syntax().to_string()) 413 }
412 } 414 builder.finish()
413 builder.finish().apply(&template.template.text().to_string()) 415 };
416
417 let mut text = template.template.text().to_string();
418 edit.apply(&mut text);
419 text
414} 420}
415 421
416#[cfg(test)] 422#[cfg(test)]
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs
index 1a7348dac..61e686da5 100644
--- a/crates/ra_syntax/src/lib.rs
+++ b/crates/ra_syntax/src/lib.rs
@@ -142,7 +142,8 @@ impl Parse<SourceFile> {
142 } 142 }
143 143
144 fn full_reparse(&self, indel: &Indel) -> Parse<SourceFile> { 144 fn full_reparse(&self, indel: &Indel) -> Parse<SourceFile> {
145 let text = indel.apply(self.tree().syntax().text().to_string()); 145 let mut text = self.tree().syntax().text().to_string();
146 indel.apply(&mut text);
146 SourceFile::parse(&text) 147 SourceFile::parse(&text)
147 } 148 }
148} 149}
diff --git a/crates/ra_syntax/src/parsing/reparsing.rs b/crates/ra_syntax/src/parsing/reparsing.rs
index 6257e3f33..edbc190f8 100644
--- a/crates/ra_syntax/src/parsing/reparsing.rs
+++ b/crates/ra_syntax/src/parsing/reparsing.rs
@@ -109,14 +109,14 @@ fn reparse_block<'node>(
109} 109}
110 110
111fn get_text_after_edit(element: SyntaxElement, edit: &Indel) -> String { 111fn get_text_after_edit(element: SyntaxElement, edit: &Indel) -> String {
112 let edit = 112 let edit = Indel::replace(edit.delete - element.text_range().start(), edit.insert.clone());
113 Indel::replace(edit.delete - element.text_range().start(), edit.insert.clone());
114 113
115 let text = match element { 114 let mut text = match element {
116 NodeOrToken::Token(token) => token.text().to_string(), 115 NodeOrToken::Token(token) => token.text().to_string(),
117 NodeOrToken::Node(node) => node.text().to_string(), 116 NodeOrToken::Node(node) => node.text().to_string(),
118 }; 117 };
119 edit.apply(text) 118 edit.apply(&mut text);
119 text
120} 120}
121 121
122fn is_contextual_kw(text: &str) -> bool { 122fn is_contextual_kw(text: &str) -> bool {
@@ -199,7 +199,11 @@ mod tests {
199 fn do_check(before: &str, replace_with: &str, reparsed_len: u32) { 199 fn do_check(before: &str, replace_with: &str, reparsed_len: u32) {
200 let (range, before) = extract_range(before); 200 let (range, before) = extract_range(before);
201 let edit = Indel::replace(range, replace_with.to_owned()); 201 let edit = Indel::replace(range, replace_with.to_owned());
202 let after = edit.apply(before.clone()); 202 let after = {
203 let mut after = before.clone();
204 edit.apply(&mut after);
205 after
206 };
203 207
204 let fully_reparsed = SourceFile::parse(&after); 208 let fully_reparsed = SourceFile::parse(&after);
205 let incrementally_reparsed: Parse<SourceFile> = { 209 let incrementally_reparsed: Parse<SourceFile> = {
diff --git a/crates/ra_text_edit/src/lib.rs b/crates/ra_text_edit/src/lib.rs
index c41bf324b..7138bbc65 100644
--- a/crates/ra_text_edit/src/lib.rs
+++ b/crates/ra_text_edit/src/lib.rs
@@ -37,11 +37,10 @@ impl Indel {
37 Indel { delete: range, insert: replace_with } 37 Indel { delete: range, insert: replace_with }
38 } 38 }
39 39
40 pub fn apply(&self, mut text: String) -> String { 40 pub fn apply(&self, text: &mut String) {
41 let start: usize = self.delete.start().into(); 41 let start: usize = self.delete.start().into();
42 let end: usize = self.delete.end().into(); 42 let end: usize = self.delete.end().into();
43 text.replace_range(start..end, &self.insert); 43 text.replace_range(start..end, &self.insert);
44 text
45 } 44 }
46} 45}
47 46
@@ -76,8 +75,17 @@ impl TextEdit {
76 &self.indels 75 &self.indels
77 } 76 }
78 77
79 pub fn apply(&self, text: &str) -> String { 78 pub fn apply(&self, text: &mut String) {
80 let mut total_len = TextSize::of(text); 79 match self.indels.len() {
80 0 => return,
81 1 => {
82 self.indels[0].apply(text);
83 return;
84 }
85 _ => (),
86 }
87
88 let mut total_len = TextSize::of(&*text);
81 for indel in self.indels.iter() { 89 for indel in self.indels.iter() {
82 total_len += TextSize::of(&indel.insert); 90 total_len += TextSize::of(&indel.insert);
83 total_len -= indel.delete.end() - indel.delete.start(); 91 total_len -= indel.delete.end() - indel.delete.start();
@@ -95,7 +103,10 @@ impl TextEdit {
95 } 103 }
96 buf.push_str(&text[prev..text.len()]); 104 buf.push_str(&text[prev..text.len()]);
97 assert_eq!(TextSize::of(&buf), total_len); 105 assert_eq!(TextSize::of(&buf), total_len);
98 buf 106
107 // FIXME: figure out a way to mutate the text in-place or reuse the
108 // memory in some other way
109 *text = buf
99 } 110 }
100 111
101 pub fn apply_to_offset(&self, offset: TextSize) -> Option<TextSize> { 112 pub fn apply_to_offset(&self, offset: TextSize) -> Option<TextSize> {