Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #13549 - Veykril:search-fix, r=Veykril
fix: Fix reference searching only accounting substrings instead of whole identifiers Fixes https://github.com/rust-lang/rust-analyzer/issues/13498
bors 2022-11-05
parent df38770 · parent 17619de · commit 2c37e7d
-rw-r--r--crates/ide-db/src/search.rs70
-rw-r--r--crates/ide/src/rename.rs35
2 files changed, 78 insertions, 27 deletions
diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs
index 82b85f2fa5..aa5d7e9beb 100644
--- a/crates/ide-db/src/search.rs
+++ b/crates/ide-db/src/search.rs
@@ -446,33 +446,47 @@ impl<'a> FindUsages<'a> {
})
}
- // FIXME: There should be optimization potential here
- // Currently we try to descend everything we find which
- // means we call `Semantics::descend_into_macros` on
- // every textual hit. That function is notoriously
- // expensive even for things that do not get down mapped
- // into macros.
+ let find_nodes = move |name: &str, node: &syntax::SyntaxNode, offset: TextSize| {
+ node.token_at_offset(offset).find(|it| it.text() == name).map(|token| {
+ // FIXME: There should be optimization potential here
+ // Currently we try to descend everything we find which
+ // means we call `Semantics::descend_into_macros` on
+ // every textual hit. That function is notoriously
+ // expensive even for things that do not get down mapped
+ // into macros.
+ sema.descend_into_macros(token).into_iter().filter_map(|it| it.parent())
+ })
+ };
+
for (text, file_id, search_range) in scope_files(sema, &search_scope) {
let tree = Lazy::new(move || sema.parse(file_id).syntax().clone());
// Search for occurrences of the items name
for offset in match_indices(&text, finder, search_range) {
- for name in sema.find_nodes_at_offset_with_descend(&tree, offset) {
- if match name {
- ast::NameLike::NameRef(name_ref) => self.found_name_ref(&name_ref, sink),
- ast::NameLike::Name(name) => self.found_name(&name, sink),
- ast::NameLike::Lifetime(lifetime) => self.found_lifetime(&lifetime, sink),
- } {
- return;
+ if let Some(iter) = find_nodes(name, &tree, offset) {
+ for name in iter.filter_map(ast::NameLike::cast) {
+ if match name {
+ ast::NameLike::NameRef(name_ref) => {
+ self.found_name_ref(&name_ref, sink)
+ }
+ ast::NameLike::Name(name) => self.found_name(&name, sink),
+ ast::NameLike::Lifetime(lifetime) => {
+ self.found_lifetime(&lifetime, sink)
+ }
+ } {
+ return;
+ }
}
}
}
// Search for occurrences of the `Self` referring to our type
if let Some((self_ty, finder)) = &include_self_kw_refs {
for offset in match_indices(&text, finder, search_range) {
- for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) {
- if self.found_self_ty_name_ref(self_ty, &name_ref, sink) {
- return;
+ if let Some(iter) = find_nodes("Self", &tree, offset) {
+ for name_ref in iter.filter_map(ast::NameRef::cast) {
+ if self.found_self_ty_name_ref(self_ty, &name_ref, sink) {
+ return;
+ }
}
}
}
@@ -493,17 +507,21 @@ impl<'a> FindUsages<'a> {
let tree = Lazy::new(move || sema.parse(file_id).syntax().clone());
for offset in match_indices(&text, finder, search_range) {
- for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) {
- if self.found_name_ref(&name_ref, sink) {
- return;
+ if let Some(iter) = find_nodes("super", &tree, offset) {
+ for name_ref in iter.filter_map(ast::NameRef::cast) {
+ if self.found_name_ref(&name_ref, sink) {
+ return;
+ }
}
}
}
if let Some(finder) = &is_crate_root {
for offset in match_indices(&text, finder, search_range) {
- for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) {
- if self.found_name_ref(&name_ref, sink) {
- return;
+ if let Some(iter) = find_nodes("crate", &tree, offset) {
+ for name_ref in iter.filter_map(ast::NameRef::cast) {
+ if self.found_name_ref(&name_ref, sink) {
+ return;
+ }
}
}
}
@@ -544,9 +562,11 @@ impl<'a> FindUsages<'a> {
let finder = &Finder::new("self");
for offset in match_indices(&text, finder, search_range) {
- for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) {
- if self.found_self_module_name_ref(&name_ref, sink) {
- return;
+ if let Some(iter) = find_nodes("self", &tree, offset) {
+ for name_ref in iter.filter_map(ast::NameRef::cast) {
+ if self.found_self_module_name_ref(&name_ref, sink) {
+ return;
+ }
}
}
}
diff --git a/crates/ide/src/rename.rs b/crates/ide/src/rename.rs
index fe44856dca..b4df043705 100644
--- a/crates/ide/src/rename.rs
+++ b/crates/ide/src/rename.rs
@@ -40,7 +40,9 @@ pub(crate) fn prepare_rename(
if def.range_for_rename(&sema).is_none() {
bail!("No references found at position")
}
- let frange = sema.original_range(name_like.syntax());
+ let Some(frange) = sema.original_range_opt(name_like.syntax()) else {
+ bail!("No references found at position");
+ };
always!(
frange.range.contains_inclusive(position.offset)
@@ -51,7 +53,7 @@ pub(crate) fn prepare_rename(
.reduce(|acc, cur| match (acc, cur) {
// ensure all ranges are the same
(Ok(acc_inner), Ok(cur_inner)) if acc_inner == cur_inner => Ok(acc_inner),
- (Err(e), _) => Err(e),
+ (e @ Err(_), _) | (_, e @ Err(_)) => e,
_ => bail!("inconsistent text range"),
});
@@ -2249,4 +2251,33 @@ fn foo((bar | bar | bar): ()) {
"#,
);
}
+
+ #[test]
+ fn regression_13498() {
+ check(
+ "Testing",
+ r"
+mod foo {
+ pub struct Test$0;
+}
+
+use foo::Test as Tester;
+
+fn main() {
+ let t = Tester;
+}
+",
+ r"
+mod foo {
+ pub struct Testing;
+}
+
+use foo::Testing as Tester;
+
+fn main() {
+ let t = Tester;
+}
+",
+ )
+ }
}