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.rs55
1 files changed, 55 insertions, 0 deletions
diff --git a/crates/ra_ssr/src/replacing.rs b/crates/ra_ssr/src/replacing.rs
new file mode 100644
index 000000000..81a5e06a9
--- /dev/null
+++ b/crates/ra_ssr/src/replacing.rs
@@ -0,0 +1,55 @@
1//! Code for applying replacement templates for matches that have previously been found.
2
3use crate::matching::Var;
4use crate::parsing::PatternElement;
5use crate::{Match, SsrMatches};
6use ra_syntax::ast::AstToken;
7use ra_syntax::TextSize;
8use ra_text_edit::TextEdit;
9
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
12/// in the original code.
13pub(crate) fn matches_to_edit(matches: &SsrMatches) -> TextEdit {
14 matches_to_edit_at_offset(matches, 0.into())
15}
16
17fn matches_to_edit_at_offset(matches: &SsrMatches, relative_start: TextSize) -> TextEdit {
18 let mut edit_builder = ra_text_edit::TextEditBuilder::default();
19 for m in &matches.matches {
20 edit_builder.replace(m.range.checked_sub(relative_start).unwrap(), render_replace(m));
21 }
22 edit_builder.finish()
23}
24
25fn render_replace(match_info: &Match) -> String {
26 let mut out = String::new();
27 for r in &match_info.template.tokens {
28 match r {
29 PatternElement::Token(t) => out.push_str(t.text.as_str()),
30 PatternElement::Placeholder(p) => {
31 if let Some(placeholder_value) =
32 match_info.placeholder_values.get(&Var(p.ident.to_string()))
33 {
34 let range = &placeholder_value.range.range;
35 let mut matched_text = placeholder_value.node.text().to_string();
36 let edit =
37 matches_to_edit_at_offset(&placeholder_value.inner_matches, range.start());
38 edit.apply(&mut matched_text);
39 out.push_str(&matched_text);
40 } else {
41 // We validated that all placeholder references were valid before we
42 // started, so this shouldn't happen.
43 panic!(
44 "Internal error: replacement referenced unknown placeholder {}",
45 p.ident
46 );
47 }
48 }
49 }
50 }
51 for comment in &match_info.ignored_comments {
52 out.push_str(&comment.syntax().to_string());
53 }
54 out
55}