Skip to content

Commit 8d09ab8

Browse files
SSR: Disable matching within use declarations
It currently does the wrong thing when the use declaration contains braces.
1 parent 63f500b commit 8d09ab8

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

crates/ra_ssr/src/search.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ use ra_ide_db::{
1010
defs::Definition,
1111
search::{Reference, SearchScope},
1212
};
13-
use ra_syntax::{ast, AstNode, SyntaxNode};
13+
use ra_syntax::{ast, AstNode, SyntaxKind, SyntaxNode};
14+
use test_utils::mark;
1415

1516
/// A cache for the results of find_usages. This is for when we have multiple patterns that have the
1617
/// 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> {
5960
.skip(first_path.depth as usize)
6061
.next()
6162
{
63+
if !is_search_permitted_ancestors(&node_to_match) {
64+
mark::hit!(use_declaration_with_braces);
65+
continue;
66+
}
6267
if let Ok(m) =
6368
matching::get_match(false, rule, &node_to_match, &None, &self.sema)
6469
{
@@ -123,6 +128,9 @@ impl<'db> MatchFinder<'db> {
123128
restrict_range: &Option<FileRange>,
124129
matches_out: &mut Vec<Match>,
125130
) {
131+
if !is_search_permitted(code) {
132+
return;
133+
}
126134
if let Ok(m) = matching::get_match(false, rule, &code, restrict_range, &self.sema) {
127135
matches_out.push(m);
128136
}
@@ -149,6 +157,25 @@ impl<'db> MatchFinder<'db> {
149157
}
150158
}
151159

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+
152179
impl UsageCache {
153180
fn find(&mut self, definition: &Definition) -> Option<&[Reference]> {
154181
// We expect a very small number of cache entries (generally 1), so a linear scan should be

crates/ra_ssr/src/tests.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,3 +804,26 @@ fn overlapping_possible_matches() {
804804
&["foo(foo(42))", "foo(foo(foo(foo(42))))"],
805805
);
806806
}
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+
}

0 commit comments

Comments
 (0)