diff options
-rw-r--r-- | crates/ra_ide/src/ssr.rs | 24 | ||||
-rw-r--r-- | crates/ra_syntax/src/lib.rs | 3 | ||||
-rw-r--r-- | crates/ra_syntax/src/parsing/reparsing.rs | 14 | ||||
-rw-r--r-- | crates/ra_text_edit/src/lib.rs | 21 |
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 | ||
111 | fn get_text_after_edit(element: SyntaxElement, edit: &Indel) -> String { | 111 | fn 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 | ||
122 | fn is_contextual_kw(text: &str) -> bool { | 122 | fn 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> { |