diff options
-rw-r--r-- | crates/ra_ssr/src/search.rs | 29 | ||||
-rw-r--r-- | crates/ra_ssr/src/tests.rs | 23 |
2 files changed, 51 insertions, 1 deletions
diff --git a/crates/ra_ssr/src/search.rs b/crates/ra_ssr/src/search.rs index 9a4e35e96..141e7d026 100644 --- a/crates/ra_ssr/src/search.rs +++ b/crates/ra_ssr/src/search.rs | |||
@@ -10,7 +10,8 @@ use ra_ide_db::{ | |||
10 | defs::Definition, | 10 | defs::Definition, |
11 | search::{Reference, SearchScope}, | 11 | search::{Reference, SearchScope}, |
12 | }; | 12 | }; |
13 | use ra_syntax::{ast, AstNode, SyntaxNode}; | 13 | use ra_syntax::{ast, AstNode, SyntaxKind, SyntaxNode}; |
14 | use test_utils::mark; | ||
14 | 15 | ||
15 | /// A cache for the results of find_usages. This is for when we have multiple patterns that have the | 16 | /// A cache for the results of find_usages. This is for when we have multiple patterns that have the |
16 | /// same path. e.g. if the pattern was `foo::Bar` that can parse as a path, an expression, a type | 17 | /// same path. e.g. if the pattern was `foo::Bar` that can parse as a path, an expression, a type |
@@ -59,6 +60,10 @@ impl<'db> MatchFinder<'db> { | |||
59 | .skip(first_path.depth as usize) | 60 | .skip(first_path.depth as usize) |
60 | .next() | 61 | .next() |
61 | { | 62 | { |
63 | if !is_search_permitted_ancestors(&node_to_match) { | ||
64 | mark::hit!(use_declaration_with_braces); | ||
65 | continue; | ||
66 | } | ||
62 | if let Ok(m) = | 67 | if let Ok(m) = |
63 | matching::get_match(false, rule, &node_to_match, &None, &self.sema) | 68 | matching::get_match(false, rule, &node_to_match, &None, &self.sema) |
64 | { | 69 | { |
@@ -123,6 +128,9 @@ impl<'db> MatchFinder<'db> { | |||
123 | restrict_range: &Option<FileRange>, | 128 | restrict_range: &Option<FileRange>, |
124 | matches_out: &mut Vec<Match>, | 129 | matches_out: &mut Vec<Match>, |
125 | ) { | 130 | ) { |
131 | if !is_search_permitted(code) { | ||
132 | return; | ||
133 | } | ||
126 | if let Ok(m) = matching::get_match(false, rule, &code, restrict_range, &self.sema) { | 134 | if let Ok(m) = matching::get_match(false, rule, &code, restrict_range, &self.sema) { |
127 | matches_out.push(m); | 135 | matches_out.push(m); |
128 | } | 136 | } |
@@ -149,6 +157,25 @@ impl<'db> MatchFinder<'db> { | |||
149 | } | 157 | } |
150 | } | 158 | } |
151 | 159 | ||
160 | /// Returns whether we support matching within `node` and all of its ancestors. | ||
161 | fn is_search_permitted_ancestors(node: &SyntaxNode) -> bool { | ||
162 | if let Some(parent) = node.parent() { | ||
163 | if !is_search_permitted_ancestors(&parent) { | ||
164 | return false; | ||
165 | } | ||
166 | } | ||
167 | is_search_permitted(node) | ||
168 | } | ||
169 | |||
170 | /// Returns whether we support matching within this kind of node. | ||
171 | fn is_search_permitted(node: &SyntaxNode) -> bool { | ||
172 | // FIXME: Properly handle use declarations. At the moment, if our search pattern is `foo::bar` | ||
173 | // and the code is `use foo::{baz, bar}`, we'll match `bar`, since it resolves to `foo::bar`. | ||
174 | // However we'll then replace just the part we matched `bar`. We probably need to instead remove | ||
175 | // `bar` and insert a new use declaration. | ||
176 | node.kind() != SyntaxKind::USE_ITEM | ||
177 | } | ||
178 | |||
152 | impl UsageCache { | 179 | impl UsageCache { |
153 | fn find(&mut self, definition: &Definition) -> Option<&[Reference]> { | 180 | fn find(&mut self, definition: &Definition) -> Option<&[Reference]> { |
154 | // We expect a very small number of cache entries (generally 1), so a linear scan should be | 181 | // We expect a very small number of cache entries (generally 1), so a linear scan should be |
diff --git a/crates/ra_ssr/src/tests.rs b/crates/ra_ssr/src/tests.rs index 33742dc8e..f564c6129 100644 --- a/crates/ra_ssr/src/tests.rs +++ b/crates/ra_ssr/src/tests.rs | |||
@@ -804,3 +804,26 @@ fn overlapping_possible_matches() { | |||
804 | &["foo(foo(42))", "foo(foo(foo(foo(42))))"], | 804 | &["foo(foo(42))", "foo(foo(foo(foo(42))))"], |
805 | ); | 805 | ); |
806 | } | 806 | } |
807 | |||
808 | #[test] | ||
809 | fn use_declaration_with_braces() { | ||
810 | // It would be OK for a path rule to match and alter a use declaration. We shouldn't mess it up | ||
811 | // though. In particular, we must not change `use foo::{baz, bar}` to `use foo::{baz, | ||
812 | // foo2::bar2}`. | ||
813 | mark::check!(use_declaration_with_braces); | ||
814 | assert_ssr_transform( | ||
815 | "foo::bar ==>> foo2::bar2", | ||
816 | r#" | ||
817 | mod foo { pub fn bar() {} pub fn baz() {} } | ||
818 | mod foo2 { pub fn bar2() {} } | ||
819 | use foo::{baz, bar}; | ||
820 | fn main() { bar() } | ||
821 | "#, | ||
822 | expect![[" | ||
823 | mod foo { pub fn bar() {} pub fn baz() {} } | ||
824 | mod foo2 { pub fn bar2() {} } | ||
825 | use foo::{baz, bar}; | ||
826 | fn main() { foo2::bar2() } | ||
827 | "]], | ||
828 | ) | ||
829 | } | ||