Skip to content

Commit

Permalink
Auto merge of rust-lang#13549 - Veykril:search-fix, r=Veykril
Browse files Browse the repository at this point in the history
fix: Fix reference searching only accounting substrings instead of whole identifiers

Fixes rust-lang/rust-analyzer#13498
  • Loading branch information
bors committed Nov 5, 2022
2 parents df38770 + 17619de commit 2c37e7d
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 27 deletions.
70 changes: 45 additions & 25 deletions crates/ide-db/src/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}
}
Expand All @@ -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;
}
}
}
}
Expand Down Expand Up @@ -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;
}
}
}
}
Expand Down
35 changes: 33 additions & 2 deletions crates/ide/src/rename.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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"),
});

Expand Down Expand Up @@ -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;
}
",
)
}
}

0 comments on commit 2c37e7d

Please sign in to comment.