aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ssr/src/replacing.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ssr/src/replacing.rs')
-rw-r--r--crates/ra_ssr/src/replacing.rs40
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
3use crate::matching::Var; 3use crate::matching::Var;
4use crate::{parsing::ParsedRule, Match, SsrMatches}; 4use crate::{resolving::ResolvedRule, Match, SsrMatches};
5use ra_syntax::ast::AstToken; 5use ra_syntax::ast::{self, AstToken};
6use ra_syntax::{SyntaxElement, SyntaxNode, SyntaxToken, TextSize}; 6use ra_syntax::{SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextSize};
7use ra_text_edit::TextEdit; 7use 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;
12pub(crate) fn matches_to_edit( 12pub(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(
36struct ReplacementRenderer<'a> { 36struct 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
43fn render_replace(match_info: &Match, file_src: &str, rules: &[ParsedRule]) -> String { 43fn 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) =