From 662ab2ecc8e29eb5995b3c162fac869838bea9a2 Mon Sep 17 00:00:00 2001 From: David Lattimore Date: Wed, 17 Jun 2020 16:53:51 +1000 Subject: Allow SSR to match type references, items, paths and patterns Part of #3186 --- crates/ra_ssr/src/replacing.rs | 55 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 crates/ra_ssr/src/replacing.rs (limited to 'crates/ra_ssr/src/replacing.rs') 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 @@ +//! Code for applying replacement templates for matches that have previously been found. + +use crate::matching::Var; +use crate::parsing::PatternElement; +use crate::{Match, SsrMatches}; +use ra_syntax::ast::AstToken; +use ra_syntax::TextSize; +use ra_text_edit::TextEdit; + +/// Returns a text edit that will replace each match in `matches` with its corresponding replacement +/// template. Placeholders in the template will have been substituted with whatever they matched to +/// in the original code. +pub(crate) fn matches_to_edit(matches: &SsrMatches) -> TextEdit { + matches_to_edit_at_offset(matches, 0.into()) +} + +fn matches_to_edit_at_offset(matches: &SsrMatches, relative_start: TextSize) -> TextEdit { + let mut edit_builder = ra_text_edit::TextEditBuilder::default(); + for m in &matches.matches { + edit_builder.replace(m.range.checked_sub(relative_start).unwrap(), render_replace(m)); + } + edit_builder.finish() +} + +fn render_replace(match_info: &Match) -> String { + let mut out = String::new(); + for r in &match_info.template.tokens { + match r { + PatternElement::Token(t) => out.push_str(t.text.as_str()), + PatternElement::Placeholder(p) => { + if let Some(placeholder_value) = + match_info.placeholder_values.get(&Var(p.ident.to_string())) + { + let range = &placeholder_value.range.range; + let mut matched_text = placeholder_value.node.text().to_string(); + let edit = + matches_to_edit_at_offset(&placeholder_value.inner_matches, range.start()); + edit.apply(&mut matched_text); + out.push_str(&matched_text); + } else { + // We validated that all placeholder references were valid before we + // started, so this shouldn't happen. + panic!( + "Internal error: replacement referenced unknown placeholder {}", + p.ident + ); + } + } + } + } + for comment in &match_info.ignored_comments { + out.push_str(&comment.syntax().to_string()); + } + out +} -- cgit v1.2.3