From 13f901f636846e330699a4414059591ec2e67cd1 Mon Sep 17 00:00:00 2001 From: David Lattimore Date: Wed, 22 Jul 2020 16:31:32 +1000 Subject: SSR: Move search code into a submodule Also renamed find_matches to slow_scan_node to reflect that it's a slow way to do things. Actually the name came from a later commit and probably makes more sense once there's an alternative. --- crates/ra_ssr/src/search.rs | 54 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 crates/ra_ssr/src/search.rs (limited to 'crates/ra_ssr/src/search.rs') diff --git a/crates/ra_ssr/src/search.rs b/crates/ra_ssr/src/search.rs new file mode 100644 index 000000000..6f21452ac --- /dev/null +++ b/crates/ra_ssr/src/search.rs @@ -0,0 +1,54 @@ +//! Searching for matches. + +use crate::{matching, Match, MatchFinder}; +use ra_db::FileRange; +use ra_syntax::{ast, AstNode, SyntaxNode}; + +impl<'db> MatchFinder<'db> { + pub(crate) fn slow_scan_node( + &self, + code: &SyntaxNode, + restrict_range: &Option, + matches_out: &mut Vec, + ) { + for rule in &self.rules { + if let Ok(mut m) = matching::get_match(false, rule, &code, restrict_range, &self.sema) { + // Continue searching in each of our placeholders. + for placeholder_value in m.placeholder_values.values_mut() { + if let Some(placeholder_node) = &placeholder_value.node { + // Don't search our placeholder if it's the entire matched node, otherwise we'd + // find the same match over and over until we got a stack overflow. + if placeholder_node != code { + self.slow_scan_node( + placeholder_node, + restrict_range, + &mut placeholder_value.inner_matches.matches, + ); + } + } + } + matches_out.push(m); + return; + } + } + // If we've got a macro call, we already tried matching it pre-expansion, which is the only + // way to match the whole macro, now try expanding it and matching the expansion. + if let Some(macro_call) = ast::MacroCall::cast(code.clone()) { + if let Some(expanded) = self.sema.expand(¯o_call) { + if let Some(tt) = macro_call.token_tree() { + // When matching within a macro expansion, we only want to allow matches of + // nodes that originated entirely from within the token tree of the macro call. + // i.e. we don't want to match something that came from the macro itself. + self.slow_scan_node( + &expanded, + &Some(self.sema.original_range(tt.syntax())), + matches_out, + ); + } + } + } + for child in code.children() { + self.slow_scan_node(&child, restrict_range, matches_out); + } + } +} -- cgit v1.2.3