aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_ssr/src/search.rs29
-rw-r--r--crates/ra_ssr/src/tests.rs23
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};
13use ra_syntax::{ast, AstNode, SyntaxNode}; 13use ra_syntax::{ast, AstNode, SyntaxKind, SyntaxNode};
14use 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.
161fn 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.
171fn 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
152impl UsageCache { 179impl 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]
809fn 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}