diff options
-rw-r--r-- | crates/ra_ssr/src/lib.rs | 3 | ||||
-rw-r--r-- | crates/ra_ssr/src/matching.rs | 2 | ||||
-rw-r--r-- | crates/ra_ssr/src/replacing.rs | 33 | ||||
-rw-r--r-- | crates/ra_ssr/src/tests.rs | 17 | ||||
-rw-r--r-- | editors/code/src/commands.ts | 2 |
5 files changed, 38 insertions, 19 deletions
diff --git a/crates/ra_ssr/src/lib.rs b/crates/ra_ssr/src/lib.rs index 8f149e3db..e148f4564 100644 --- a/crates/ra_ssr/src/lib.rs +++ b/crates/ra_ssr/src/lib.rs | |||
@@ -69,7 +69,8 @@ impl<'db> MatchFinder<'db> { | |||
69 | if matches.matches.is_empty() { | 69 | if matches.matches.is_empty() { |
70 | None | 70 | None |
71 | } else { | 71 | } else { |
72 | Some(replacing::matches_to_edit(&matches)) | 72 | use ra_db::SourceDatabaseExt; |
73 | Some(replacing::matches_to_edit(&matches, &self.sema.db.file_text(file_id))) | ||
73 | } | 74 | } |
74 | } | 75 | } |
75 | 76 | ||
diff --git a/crates/ra_ssr/src/matching.rs b/crates/ra_ssr/src/matching.rs index 85420ed3c..bb87bda43 100644 --- a/crates/ra_ssr/src/matching.rs +++ b/crates/ra_ssr/src/matching.rs | |||
@@ -585,7 +585,7 @@ mod tests { | |||
585 | "1+2" | 585 | "1+2" |
586 | ); | 586 | ); |
587 | 587 | ||
588 | let edit = crate::replacing::matches_to_edit(&matches); | 588 | let edit = crate::replacing::matches_to_edit(&matches, input); |
589 | let mut after = input.to_string(); | 589 | let mut after = input.to_string(); |
590 | edit.apply(&mut after); | 590 | edit.apply(&mut after); |
591 | assert_eq!(after, "fn main() { bar(1+2); }"); | 591 | assert_eq!(after, "fn main() { bar(1+2); }"); |
diff --git a/crates/ra_ssr/src/replacing.rs b/crates/ra_ssr/src/replacing.rs index 5dcde82a2..70ce1c185 100644 --- a/crates/ra_ssr/src/replacing.rs +++ b/crates/ra_ssr/src/replacing.rs | |||
@@ -10,21 +10,25 @@ use ra_text_edit::TextEdit; | |||
10 | /// Returns a text edit that will replace each match in `matches` with its corresponding replacement | 10 | /// Returns a text edit that will replace each match in `matches` with its corresponding replacement |
11 | /// template. Placeholders in the template will have been substituted with whatever they matched to | 11 | /// template. Placeholders in the template will have been substituted with whatever they matched to |
12 | /// in the original code. | 12 | /// in the original code. |
13 | pub(crate) fn matches_to_edit(matches: &SsrMatches) -> TextEdit { | 13 | pub(crate) fn matches_to_edit(matches: &SsrMatches, file_src: &str) -> TextEdit { |
14 | matches_to_edit_at_offset(matches, 0.into()) | 14 | matches_to_edit_at_offset(matches, file_src, 0.into()) |
15 | } | 15 | } |
16 | 16 | ||
17 | fn matches_to_edit_at_offset(matches: &SsrMatches, relative_start: TextSize) -> TextEdit { | 17 | fn matches_to_edit_at_offset( |
18 | matches: &SsrMatches, | ||
19 | file_src: &str, | ||
20 | relative_start: TextSize, | ||
21 | ) -> TextEdit { | ||
18 | let mut edit_builder = ra_text_edit::TextEditBuilder::default(); | 22 | let mut edit_builder = ra_text_edit::TextEditBuilder::default(); |
19 | for m in &matches.matches { | 23 | for m in &matches.matches { |
20 | edit_builder.replace(m.range.checked_sub(relative_start).unwrap(), render_replace(m)); | 24 | edit_builder |
25 | .replace(m.range.checked_sub(relative_start).unwrap(), render_replace(m, file_src)); | ||
21 | } | 26 | } |
22 | edit_builder.finish() | 27 | edit_builder.finish() |
23 | } | 28 | } |
24 | 29 | ||
25 | fn render_replace(match_info: &Match) -> String { | 30 | fn render_replace(match_info: &Match, file_src: &str) -> String { |
26 | let mut out = String::new(); | 31 | let mut out = String::new(); |
27 | let match_start = match_info.matched_node.text_range().start(); | ||
28 | for r in &match_info.template.tokens { | 32 | for r in &match_info.template.tokens { |
29 | match r { | 33 | match r { |
30 | PatternElement::Token(t) => out.push_str(t.text.as_str()), | 34 | PatternElement::Token(t) => out.push_str(t.text.as_str()), |
@@ -33,16 +37,13 @@ fn render_replace(match_info: &Match) -> String { | |||
33 | match_info.placeholder_values.get(&Var(p.ident.to_string())) | 37 | match_info.placeholder_values.get(&Var(p.ident.to_string())) |
34 | { | 38 | { |
35 | let range = &placeholder_value.range.range; | 39 | let range = &placeholder_value.range.range; |
36 | let mut matched_text = if let Some(node) = &placeholder_value.node { | 40 | let mut matched_text = |
37 | node.text().to_string() | 41 | file_src[usize::from(range.start())..usize::from(range.end())].to_owned(); |
38 | } else { | 42 | let edit = matches_to_edit_at_offset( |
39 | let relative_range = range.checked_sub(match_start).unwrap(); | 43 | &placeholder_value.inner_matches, |
40 | match_info.matched_node.text().to_string() | 44 | file_src, |
41 | [usize::from(relative_range.start())..usize::from(relative_range.end())] | 45 | range.start(), |
42 | .to_string() | 46 | ); |
43 | }; | ||
44 | let edit = | ||
45 | matches_to_edit_at_offset(&placeholder_value.inner_matches, range.start()); | ||
46 | edit.apply(&mut matched_text); | 47 | edit.apply(&mut matched_text); |
47 | out.push_str(&matched_text); | 48 | out.push_str(&matched_text); |
48 | } else { | 49 | } else { |
diff --git a/crates/ra_ssr/src/tests.rs b/crates/ra_ssr/src/tests.rs index 7a3141be8..8be60c293 100644 --- a/crates/ra_ssr/src/tests.rs +++ b/crates/ra_ssr/src/tests.rs | |||
@@ -606,3 +606,20 @@ fn replace_within_macro_expansion() { | |||
606 | fn f() {macro1!(bar(5.x()).o2())}"#, | 606 | fn f() {macro1!(bar(5.x()).o2())}"#, |
607 | ) | 607 | ) |
608 | } | 608 | } |
609 | |||
610 | #[test] | ||
611 | fn preserves_whitespace_within_macro_expansion() { | ||
612 | assert_ssr_transform( | ||
613 | "$a + $b ==>> $b - $a", | ||
614 | r#" | ||
615 | macro_rules! macro1 { | ||
616 | ($a:expr) => {$a} | ||
617 | } | ||
618 | fn f() {macro1!(1 * 2 + 3 + 4}"#, | ||
619 | r#" | ||
620 | macro_rules! macro1 { | ||
621 | ($a:expr) => {$a} | ||
622 | } | ||
623 | fn f() {macro1!(4 - 3 - 1 * 2}"#, | ||
624 | ) | ||
625 | } | ||
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts index 8c9d7802f..5a1bc7f57 100644 --- a/editors/code/src/commands.ts +++ b/editors/code/src/commands.ts | |||
@@ -158,7 +158,7 @@ export function ssr(ctx: Ctx): Cmd { | |||
158 | 158 | ||
159 | const options: vscode.InputBoxOptions = { | 159 | const options: vscode.InputBoxOptions = { |
160 | value: "() ==>> ()", | 160 | value: "() ==>> ()", |
161 | prompt: "Enter request, for example 'Foo($a:expr) ==> Foo::new($a)' ", | 161 | prompt: "Enter request, for example 'Foo($a) ==> Foo::new($a)' ", |
162 | validateInput: async (x: string) => { | 162 | validateInput: async (x: string) => { |
163 | try { | 163 | try { |
164 | await client.sendRequest(ra.ssr, { query: x, parseOnly: true }); | 164 | await client.sendRequest(ra.ssr, { query: x, parseOnly: true }); |