diff options
Diffstat (limited to 'crates/ra_ssr/src/replacing.rs')
-rw-r--r-- | crates/ra_ssr/src/replacing.rs | 40 |
1 files changed, 30 insertions, 10 deletions
diff --git a/crates/ra_ssr/src/replacing.rs b/crates/ra_ssr/src/replacing.rs index f1c5bdf14..4b3f5509c 100644 --- a/crates/ra_ssr/src/replacing.rs +++ b/crates/ra_ssr/src/replacing.rs | |||
@@ -1,9 +1,9 @@ | |||
1 | //! Code for applying replacement templates for matches that have previously been found. | 1 | //! Code for applying replacement templates for matches that have previously been found. |
2 | 2 | ||
3 | use crate::matching::Var; | 3 | use crate::matching::Var; |
4 | use crate::{parsing::ParsedRule, Match, SsrMatches}; | 4 | use crate::{resolving::ResolvedRule, Match, SsrMatches}; |
5 | use ra_syntax::ast::AstToken; | 5 | use ra_syntax::ast::{self, AstToken}; |
6 | use ra_syntax::{SyntaxElement, SyntaxNode, SyntaxToken, TextSize}; | 6 | use ra_syntax::{SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextSize}; |
7 | use ra_text_edit::TextEdit; | 7 | use ra_text_edit::TextEdit; |
8 | 8 | ||
9 | /// Returns a text edit that will replace each match in `matches` with its corresponding replacement | 9 | /// Returns a text edit that will replace each match in `matches` with its corresponding replacement |
@@ -12,7 +12,7 @@ use ra_text_edit::TextEdit; | |||
12 | pub(crate) fn matches_to_edit( | 12 | pub(crate) fn matches_to_edit( |
13 | matches: &SsrMatches, | 13 | matches: &SsrMatches, |
14 | file_src: &str, | 14 | file_src: &str, |
15 | rules: &[ParsedRule], | 15 | rules: &[ResolvedRule], |
16 | ) -> TextEdit { | 16 | ) -> TextEdit { |
17 | matches_to_edit_at_offset(matches, file_src, 0.into(), rules) | 17 | matches_to_edit_at_offset(matches, file_src, 0.into(), rules) |
18 | } | 18 | } |
@@ -21,7 +21,7 @@ fn matches_to_edit_at_offset( | |||
21 | matches: &SsrMatches, | 21 | matches: &SsrMatches, |
22 | file_src: &str, | 22 | file_src: &str, |
23 | relative_start: TextSize, | 23 | relative_start: TextSize, |
24 | rules: &[ParsedRule], | 24 | rules: &[ResolvedRule], |
25 | ) -> TextEdit { | 25 | ) -> TextEdit { |
26 | let mut edit_builder = ra_text_edit::TextEditBuilder::default(); | 26 | let mut edit_builder = ra_text_edit::TextEditBuilder::default(); |
27 | for m in &matches.matches { | 27 | for m in &matches.matches { |
@@ -36,11 +36,11 @@ fn matches_to_edit_at_offset( | |||
36 | struct ReplacementRenderer<'a> { | 36 | struct ReplacementRenderer<'a> { |
37 | match_info: &'a Match, | 37 | match_info: &'a Match, |
38 | file_src: &'a str, | 38 | file_src: &'a str, |
39 | rules: &'a [ParsedRule], | 39 | rules: &'a [ResolvedRule], |
40 | rule: &'a ParsedRule, | 40 | rule: &'a ResolvedRule, |
41 | } | 41 | } |
42 | 42 | ||
43 | fn render_replace(match_info: &Match, file_src: &str, rules: &[ParsedRule]) -> String { | 43 | fn render_replace(match_info: &Match, file_src: &str, rules: &[ResolvedRule]) -> String { |
44 | let mut out = String::new(); | 44 | let mut out = String::new(); |
45 | let rule = &rules[match_info.rule_index]; | 45 | let rule = &rules[match_info.rule_index]; |
46 | let template = rule | 46 | let template = rule |
@@ -48,7 +48,7 @@ fn render_replace(match_info: &Match, file_src: &str, rules: &[ParsedRule]) -> S | |||
48 | .as_ref() | 48 | .as_ref() |
49 | .expect("You called MatchFinder::edits after calling MatchFinder::add_search_pattern"); | 49 | .expect("You called MatchFinder::edits after calling MatchFinder::add_search_pattern"); |
50 | let renderer = ReplacementRenderer { match_info, file_src, rules, rule }; | 50 | let renderer = ReplacementRenderer { match_info, file_src, rules, rule }; |
51 | renderer.render_node_children(&template, &mut out); | 51 | renderer.render_node(&template.node, &mut out); |
52 | for comment in &match_info.ignored_comments { | 52 | for comment in &match_info.ignored_comments { |
53 | out.push_str(&comment.syntax().to_string()); | 53 | out.push_str(&comment.syntax().to_string()); |
54 | } | 54 | } |
@@ -68,11 +68,31 @@ impl ReplacementRenderer<'_> { | |||
68 | self.render_token(&token, out); | 68 | self.render_token(&token, out); |
69 | } | 69 | } |
70 | SyntaxElement::Node(child_node) => { | 70 | SyntaxElement::Node(child_node) => { |
71 | self.render_node_children(&child_node, out); | 71 | self.render_node(&child_node, out); |
72 | } | 72 | } |
73 | } | 73 | } |
74 | } | 74 | } |
75 | 75 | ||
76 | fn render_node(&self, node: &SyntaxNode, out: &mut String) { | ||
77 | use ra_syntax::ast::AstNode; | ||
78 | if let Some(mod_path) = self.match_info.rendered_template_paths.get(&node) { | ||
79 | out.push_str(&mod_path.to_string()); | ||
80 | // Emit everything except for the segment's name-ref, since we already effectively | ||
81 | // emitted that as part of `mod_path`. | ||
82 | if let Some(path) = ast::Path::cast(node.clone()) { | ||
83 | if let Some(segment) = path.segment() { | ||
84 | for node_or_token in segment.syntax().children_with_tokens() { | ||
85 | if node_or_token.kind() != SyntaxKind::NAME_REF { | ||
86 | self.render_node_or_token(&node_or_token, out); | ||
87 | } | ||
88 | } | ||
89 | } | ||
90 | } | ||
91 | } else { | ||
92 | self.render_node_children(&node, out); | ||
93 | } | ||
94 | } | ||
95 | |||
76 | fn render_token(&self, token: &SyntaxToken, out: &mut String) { | 96 | fn render_token(&self, token: &SyntaxToken, out: &mut String) { |
77 | if let Some(placeholder) = self.rule.get_placeholder(&token) { | 97 | if let Some(placeholder) = self.rule.get_placeholder(&token) { |
78 | if let Some(placeholder_value) = | 98 | if let Some(placeholder_value) = |