Skip to content

Commit a03e8e3

Browse files
committed
fix: Fix reference searching only accounting substrings instead of whole identifiers
1 parent cd26032 commit a03e8e3

File tree

2 files changed

+78
-27
lines changed

2 files changed

+78
-27
lines changed

crates/ide-db/src/search.rs

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -446,33 +446,47 @@ impl<'a> FindUsages<'a> {
446446
})
447447
}
448448

449-
// FIXME: There should be optimization potential here
450-
// Currently we try to descend everything we find which
451-
// means we call `Semantics::descend_into_macros` on
452-
// every textual hit. That function is notoriously
453-
// expensive even for things that do not get down mapped
454-
// into macros.
449+
let find_nodes = move |name: &str, node: &syntax::SyntaxNode, offset: TextSize| {
450+
node.token_at_offset(offset).find(|it| it.text() == name).map(|token| {
451+
// FIXME: There should be optimization potential here
452+
// Currently we try to descend everything we find which
453+
// means we call `Semantics::descend_into_macros` on
454+
// every textual hit. That function is notoriously
455+
// expensive even for things that do not get down mapped
456+
// into macros.
457+
sema.descend_into_macros(token).into_iter().filter_map(|it| it.parent())
458+
})
459+
};
460+
455461
for (text, file_id, search_range) in scope_files(sema, &search_scope) {
456462
let tree = Lazy::new(move || sema.parse(file_id).syntax().clone());
457463

458464
// Search for occurrences of the items name
459465
for offset in match_indices(&text, finder, search_range) {
460-
for name in sema.find_nodes_at_offset_with_descend(&tree, offset) {
461-
if match name {
462-
ast::NameLike::NameRef(name_ref) => self.found_name_ref(&name_ref, sink),
463-
ast::NameLike::Name(name) => self.found_name(&name, sink),
464-
ast::NameLike::Lifetime(lifetime) => self.found_lifetime(&lifetime, sink),
465-
} {
466-
return;
466+
if let Some(iter) = find_nodes(name, &tree, offset) {
467+
for name in iter.filter_map(ast::NameLike::cast) {
468+
if match name {
469+
ast::NameLike::NameRef(name_ref) => {
470+
self.found_name_ref(&name_ref, sink)
471+
}
472+
ast::NameLike::Name(name) => self.found_name(&name, sink),
473+
ast::NameLike::Lifetime(lifetime) => {
474+
self.found_lifetime(&lifetime, sink)
475+
}
476+
} {
477+
return;
478+
}
467479
}
468480
}
469481
}
470482
// Search for occurrences of the `Self` referring to our type
471483
if let Some((self_ty, finder)) = &include_self_kw_refs {
472484
for offset in match_indices(&text, finder, search_range) {
473-
for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) {
474-
if self.found_self_ty_name_ref(self_ty, &name_ref, sink) {
475-
return;
485+
if let Some(iter) = find_nodes("self", &tree, offset) {
486+
for name_ref in iter.filter_map(ast::NameRef::cast) {
487+
if self.found_self_ty_name_ref(self_ty, &name_ref, sink) {
488+
return;
489+
}
476490
}
477491
}
478492
}
@@ -493,17 +507,21 @@ impl<'a> FindUsages<'a> {
493507
let tree = Lazy::new(move || sema.parse(file_id).syntax().clone());
494508

495509
for offset in match_indices(&text, finder, search_range) {
496-
for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) {
497-
if self.found_name_ref(&name_ref, sink) {
498-
return;
510+
if let Some(iter) = find_nodes("super", &tree, offset) {
511+
for name_ref in iter.filter_map(ast::NameRef::cast) {
512+
if self.found_name_ref(&name_ref, sink) {
513+
return;
514+
}
499515
}
500516
}
501517
}
502518
if let Some(finder) = &is_crate_root {
503519
for offset in match_indices(&text, finder, search_range) {
504-
for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) {
505-
if self.found_name_ref(&name_ref, sink) {
506-
return;
520+
if let Some(iter) = find_nodes("crate", &tree, offset) {
521+
for name_ref in iter.filter_map(ast::NameRef::cast) {
522+
if self.found_name_ref(&name_ref, sink) {
523+
return;
524+
}
507525
}
508526
}
509527
}
@@ -544,9 +562,11 @@ impl<'a> FindUsages<'a> {
544562
let finder = &Finder::new("self");
545563

546564
for offset in match_indices(&text, finder, search_range) {
547-
for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) {
548-
if self.found_self_module_name_ref(&name_ref, sink) {
549-
return;
565+
if let Some(iter) = find_nodes("self", &tree, offset) {
566+
for name_ref in iter.filter_map(ast::NameRef::cast) {
567+
if self.found_self_module_name_ref(&name_ref, sink) {
568+
return;
569+
}
550570
}
551571
}
552572
}

crates/ide/src/rename.rs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ pub(crate) fn prepare_rename(
4040
if def.range_for_rename(&sema).is_none() {
4141
bail!("No references found at position")
4242
}
43-
let frange = sema.original_range(name_like.syntax());
43+
let Some(frange) = sema.original_range_opt(name_like.syntax()) else {
44+
bail!("No references found at position");
45+
};
4446

4547
always!(
4648
frange.range.contains_inclusive(position.offset)
@@ -51,7 +53,7 @@ pub(crate) fn prepare_rename(
5153
.reduce(|acc, cur| match (acc, cur) {
5254
// ensure all ranges are the same
5355
(Ok(acc_inner), Ok(cur_inner)) if acc_inner == cur_inner => Ok(acc_inner),
54-
(Err(e), _) => Err(e),
56+
(e @ Err(_), _) | (_, e @ Err(_)) => e,
5557
_ => bail!("inconsistent text range"),
5658
});
5759

@@ -2249,4 +2251,33 @@ fn foo((bar | bar | bar): ()) {
22492251
"#,
22502252
);
22512253
}
2254+
2255+
#[test]
2256+
fn regression_13498() {
2257+
check(
2258+
"Testing",
2259+
r"
2260+
mod foo {
2261+
pub struct Test$0;
2262+
}
2263+
2264+
use foo::Test as Tester;
2265+
2266+
fn main() {
2267+
let t = Tester;
2268+
}
2269+
",
2270+
r"
2271+
mod foo {
2272+
pub struct Testing;
2273+
}
2274+
2275+
use foo::Testing as Tester;
2276+
2277+
fn main() {
2278+
let t = Tester;
2279+
}
2280+
",
2281+
)
2282+
}
22522283
}

0 commit comments

Comments
 (0)