mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-31 23:38:45 +00:00
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
This commit is contained in:
commit
2c37e7d4af
2 changed files with 78 additions and 27 deletions
|
@ -446,31 +446,44 @@ impl<'a> FindUsages<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// FIXME: There should be optimization potential here
|
||||||
// Currently we try to descend everything we find which
|
// Currently we try to descend everything we find which
|
||||||
// means we call `Semantics::descend_into_macros` on
|
// means we call `Semantics::descend_into_macros` on
|
||||||
// every textual hit. That function is notoriously
|
// every textual hit. That function is notoriously
|
||||||
// expensive even for things that do not get down mapped
|
// expensive even for things that do not get down mapped
|
||||||
// into macros.
|
// 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) {
|
for (text, file_id, search_range) in scope_files(sema, &search_scope) {
|
||||||
let tree = Lazy::new(move || sema.parse(file_id).syntax().clone());
|
let tree = Lazy::new(move || sema.parse(file_id).syntax().clone());
|
||||||
|
|
||||||
// Search for occurrences of the items name
|
// Search for occurrences of the items name
|
||||||
for offset in match_indices(&text, finder, search_range) {
|
for offset in match_indices(&text, finder, search_range) {
|
||||||
for name in sema.find_nodes_at_offset_with_descend(&tree, offset) {
|
if let Some(iter) = find_nodes(name, &tree, offset) {
|
||||||
|
for name in iter.filter_map(ast::NameLike::cast) {
|
||||||
if match name {
|
if match name {
|
||||||
ast::NameLike::NameRef(name_ref) => self.found_name_ref(&name_ref, sink),
|
ast::NameLike::NameRef(name_ref) => {
|
||||||
|
self.found_name_ref(&name_ref, sink)
|
||||||
|
}
|
||||||
ast::NameLike::Name(name) => self.found_name(&name, sink),
|
ast::NameLike::Name(name) => self.found_name(&name, sink),
|
||||||
ast::NameLike::Lifetime(lifetime) => self.found_lifetime(&lifetime, sink),
|
ast::NameLike::Lifetime(lifetime) => {
|
||||||
|
self.found_lifetime(&lifetime, sink)
|
||||||
|
}
|
||||||
} {
|
} {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Search for occurrences of the `Self` referring to our type
|
// Search for occurrences of the `Self` referring to our type
|
||||||
if let Some((self_ty, finder)) = &include_self_kw_refs {
|
if let Some((self_ty, finder)) = &include_self_kw_refs {
|
||||||
for offset in match_indices(&text, finder, search_range) {
|
for offset in match_indices(&text, finder, search_range) {
|
||||||
for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) {
|
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) {
|
if self.found_self_ty_name_ref(self_ty, &name_ref, sink) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -478,6 +491,7 @@ impl<'a> FindUsages<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Search for `super` and `crate` resolving to our module
|
// Search for `super` and `crate` resolving to our module
|
||||||
match self.def {
|
match self.def {
|
||||||
|
@ -493,15 +507,18 @@ impl<'a> FindUsages<'a> {
|
||||||
let tree = Lazy::new(move || sema.parse(file_id).syntax().clone());
|
let tree = Lazy::new(move || sema.parse(file_id).syntax().clone());
|
||||||
|
|
||||||
for offset in match_indices(&text, finder, search_range) {
|
for offset in match_indices(&text, finder, search_range) {
|
||||||
for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) {
|
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) {
|
if self.found_name_ref(&name_ref, sink) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if let Some(finder) = &is_crate_root {
|
if let Some(finder) = &is_crate_root {
|
||||||
for offset in match_indices(&text, finder, search_range) {
|
for offset in match_indices(&text, finder, search_range) {
|
||||||
for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) {
|
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) {
|
if self.found_name_ref(&name_ref, sink) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -510,6 +527,7 @@ impl<'a> FindUsages<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,13 +562,15 @@ impl<'a> FindUsages<'a> {
|
||||||
let finder = &Finder::new("self");
|
let finder = &Finder::new("self");
|
||||||
|
|
||||||
for offset in match_indices(&text, finder, search_range) {
|
for offset in match_indices(&text, finder, search_range) {
|
||||||
for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) {
|
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) {
|
if self.found_self_module_name_ref(&name_ref, sink) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,9 @@ pub(crate) fn prepare_rename(
|
||||||
if def.range_for_rename(&sema).is_none() {
|
if def.range_for_rename(&sema).is_none() {
|
||||||
bail!("No references found at position")
|
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!(
|
always!(
|
||||||
frange.range.contains_inclusive(position.offset)
|
frange.range.contains_inclusive(position.offset)
|
||||||
|
@ -51,7 +53,7 @@ pub(crate) fn prepare_rename(
|
||||||
.reduce(|acc, cur| match (acc, cur) {
|
.reduce(|acc, cur| match (acc, cur) {
|
||||||
// ensure all ranges are the same
|
// ensure all ranges are the same
|
||||||
(Ok(acc_inner), Ok(cur_inner)) if acc_inner == cur_inner => Ok(acc_inner),
|
(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"),
|
_ => 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;
|
||||||
|
}
|
||||||
|
",
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue