aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ssr/src/search.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ssr/src/search.rs')
-rw-r--r--crates/ra_ssr/src/search.rs54
1 files changed, 54 insertions, 0 deletions
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 @@
1//! Searching for matches.
2
3use crate::{matching, Match, MatchFinder};
4use ra_db::FileRange;
5use ra_syntax::{ast, AstNode, SyntaxNode};
6
7impl<'db> MatchFinder<'db> {
8 pub(crate) fn slow_scan_node(
9 &self,
10 code: &SyntaxNode,
11 restrict_range: &Option<FileRange>,
12 matches_out: &mut Vec<Match>,
13 ) {
14 for rule in &self.rules {
15 if let Ok(mut m) = matching::get_match(false, rule, &code, restrict_range, &self.sema) {
16 // Continue searching in each of our placeholders.
17 for placeholder_value in m.placeholder_values.values_mut() {
18 if let Some(placeholder_node) = &placeholder_value.node {
19 // Don't search our placeholder if it's the entire matched node, otherwise we'd
20 // find the same match over and over until we got a stack overflow.
21 if placeholder_node != code {
22 self.slow_scan_node(
23 placeholder_node,
24 restrict_range,
25 &mut placeholder_value.inner_matches.matches,
26 );
27 }
28 }
29 }
30 matches_out.push(m);
31 return;
32 }
33 }
34 // If we've got a macro call, we already tried matching it pre-expansion, which is the only
35 // way to match the whole macro, now try expanding it and matching the expansion.
36 if let Some(macro_call) = ast::MacroCall::cast(code.clone()) {
37 if let Some(expanded) = self.sema.expand(&macro_call) {
38 if let Some(tt) = macro_call.token_tree() {
39 // When matching within a macro expansion, we only want to allow matches of
40 // nodes that originated entirely from within the token tree of the macro call.
41 // i.e. we don't want to match something that came from the macro itself.
42 self.slow_scan_node(
43 &expanded,
44 &Some(self.sema.original_range(tt.syntax())),
45 matches_out,
46 );
47 }
48 }
49 }
50 for child in code.children() {
51 self.slow_scan_node(&child, restrict_range, matches_out);
52 }
53 }
54}