diff options
Diffstat (limited to 'crates/ra_ssr/src/replacing.rs')
-rw-r--r-- | crates/ra_ssr/src/replacing.rs | 55 |
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 | |||
3 | use crate::matching::Var; | ||
4 | use crate::parsing::PatternElement; | ||
5 | use crate::{Match, SsrMatches}; | ||
6 | use ra_syntax::ast::AstToken; | ||
7 | use ra_syntax::TextSize; | ||
8 | use 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. | ||
13 | pub(crate) fn matches_to_edit(matches: &SsrMatches) -> TextEdit { | ||
14 | matches_to_edit_at_offset(matches, 0.into()) | ||
15 | } | ||
16 | |||
17 | fn 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 | |||
25 | fn 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 | } | ||