diff options
Diffstat (limited to 'crates/ra_ssr/src/search.rs')
-rw-r--r-- | crates/ra_ssr/src/search.rs | 38 |
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 | ||
3 | use crate::{matching, Match, MatchFinder}; | 3 | use crate::{matching, parsing::ParsedRule, Match, MatchFinder}; |
4 | use ra_db::FileRange; | 4 | use ra_db::FileRange; |
5 | use ra_syntax::{ast, AstNode, SyntaxNode}; | 5 | use ra_syntax::{ast, AstNode, SyntaxNode}; |
6 | 6 | ||
7 | impl<'db> MatchFinder<'db> { | 7 | impl<'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 | } |