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.rs38
1 files changed, 13 insertions, 25 deletions
diff --git a/crates/ra_ssr/src/search.rs b/crates/ra_ssr/src/search.rs
index ec3addcf8..a28e9f341 100644
--- a/crates/ra_ssr/src/search.rs
+++ b/crates/ra_ssr/src/search.rs
@@ -1,17 +1,20 @@
1//! Searching for matches. 1//! Searching for matches.
2 2
3use crate::{matching, Match, MatchFinder}; 3use crate::{matching, parsing::ParsedRule, Match, MatchFinder};
4use ra_db::FileRange; 4use ra_db::FileRange;
5use ra_syntax::{ast, AstNode, SyntaxNode}; 5use ra_syntax::{ast, AstNode, SyntaxNode};
6 6
7impl<'db> MatchFinder<'db> { 7impl<'db> MatchFinder<'db> {
8 pub(crate) fn find_all_matches(&self, matches_out: &mut Vec<Match>) { 8 /// Adds all matches for `rule` to `matches_out`. Matches may overlap in ways that make
9 /// replacement impossible, so further processing is required in order to properly nest matches
10 /// and remove overlapping matches. This is done in the `nesting` module.
11 pub(crate) fn find_matches_for_rule(&self, rule: &ParsedRule, matches_out: &mut Vec<Match>) {
9 // FIXME: Use resolved paths in the pattern to find places to search instead of always 12 // FIXME: Use resolved paths in the pattern to find places to search instead of always
10 // scanning every node. 13 // scanning every node.
11 self.slow_scan(matches_out); 14 self.slow_scan(rule, matches_out);
12 } 15 }
13 16
14 fn slow_scan(&self, matches_out: &mut Vec<Match>) { 17 fn slow_scan(&self, rule: &ParsedRule, matches_out: &mut Vec<Match>) {
15 use ra_db::SourceDatabaseExt; 18 use ra_db::SourceDatabaseExt;
16 use ra_ide_db::symbol_index::SymbolsDatabase; 19 use ra_ide_db::symbol_index::SymbolsDatabase;
17 for &root in self.sema.db.local_roots().iter() { 20 for &root in self.sema.db.local_roots().iter() {
@@ -19,7 +22,7 @@ impl<'db> MatchFinder<'db> {
19 for file_id in sr.iter() { 22 for file_id in sr.iter() {
20 let file = self.sema.parse(file_id); 23 let file = self.sema.parse(file_id);
21 let code = file.syntax(); 24 let code = file.syntax();
22 self.slow_scan_node(code, &None, matches_out); 25 self.slow_scan_node(code, rule, &None, matches_out);
23 } 26 }
24 } 27 }
25 } 28 }
@@ -27,28 +30,12 @@ impl<'db> MatchFinder<'db> {
27 fn slow_scan_node( 30 fn slow_scan_node(
28 &self, 31 &self,
29 code: &SyntaxNode, 32 code: &SyntaxNode,
33 rule: &ParsedRule,
30 restrict_range: &Option<FileRange>, 34 restrict_range: &Option<FileRange>,
31 matches_out: &mut Vec<Match>, 35 matches_out: &mut Vec<Match>,
32 ) { 36 ) {
33 for rule in &self.rules { 37 if let Ok(m) = matching::get_match(false, rule, &code, restrict_range, &self.sema) {
34 if let Ok(mut m) = matching::get_match(false, rule, &code, restrict_range, &self.sema) { 38 matches_out.push(m);
35 // Continue searching in each of our placeholders.
36 for placeholder_value in m.placeholder_values.values_mut() {
37 if let Some(placeholder_node) = &placeholder_value.node {
38 // Don't search our placeholder if it's the entire matched node, otherwise we'd
39 // find the same match over and over until we got a stack overflow.
40 if placeholder_node != code {
41 self.slow_scan_node(
42 placeholder_node,
43 restrict_range,
44 &mut placeholder_value.inner_matches.matches,
45 );
46 }
47 }
48 }
49 matches_out.push(m);
50 return;
51 }
52 } 39 }
53 // If we've got a macro call, we already tried matching it pre-expansion, which is the only 40 // If we've got a macro call, we already tried matching it pre-expansion, which is the only
54 // way to match the whole macro, now try expanding it and matching the expansion. 41 // way to match the whole macro, now try expanding it and matching the expansion.
@@ -60,6 +47,7 @@ impl<'db> MatchFinder<'db> {
60 // i.e. we don't want to match something that came from the macro itself. 47 // i.e. we don't want to match something that came from the macro itself.
61 self.slow_scan_node( 48 self.slow_scan_node(
62 &expanded, 49 &expanded,
50 rule,
63 &Some(self.sema.original_range(tt.syntax())), 51 &Some(self.sema.original_range(tt.syntax())),
64 matches_out, 52 matches_out,
65 ); 53 );
@@ -67,7 +55,7 @@ impl<'db> MatchFinder<'db> {
67 } 55 }
68 } 56 }
69 for child in code.children() { 57 for child in code.children() {
70 self.slow_scan_node(&child, restrict_range, matches_out); 58 self.slow_scan_node(&child, rule, restrict_range, matches_out);
71 } 59 }
72 } 60 }
73} 61}