mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 12:54:58 +00:00
Auto merge of #14144 - lowr:fix/find-occurrence-of-raw-ident, r=Veykril
fix: Search raw identifiers without prefix When we find references/usages of a raw identifier, we should disregard `r#` prefix because there are keywords one can use without the prefix in earlier editions (see #13034; this bug is actually fallout from the PR). `name`, the text we're searching for, has already been stripped of the prefix, but the text of nodes we compare it to hasn't been. The second commit is strictly refactoring, I can remove it if it's not much of value.
This commit is contained in:
commit
88b3d9f6f4
3 changed files with 59 additions and 43 deletions
|
@ -455,15 +455,21 @@ impl<'a> FindUsages<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let find_nodes = move |name: &str, node: &syntax::SyntaxNode, offset: TextSize| {
|
let find_nodes = move |name: &str, node: &syntax::SyntaxNode, offset: TextSize| {
|
||||||
node.token_at_offset(offset).find(|it| it.text() == name).map(|token| {
|
node.token_at_offset(offset)
|
||||||
// FIXME: There should be optimization potential here
|
.find(|it| {
|
||||||
// Currently we try to descend everything we find which
|
// `name` is stripped of raw ident prefix. See the comment on name retrieval above.
|
||||||
// means we call `Semantics::descend_into_macros` on
|
it.text().trim_start_matches("r#") == name
|
||||||
// every textual hit. That function is notoriously
|
})
|
||||||
// expensive even for things that do not get down mapped
|
.into_iter()
|
||||||
// into macros.
|
.flat_map(|token| {
|
||||||
sema.descend_into_macros(token).into_iter().filter_map(|it| it.parent())
|
// 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) {
|
for (text, file_id, search_range) in scope_files(sema, &search_scope) {
|
||||||
|
@ -471,30 +477,23 @@ impl<'a> FindUsages<'a> {
|
||||||
|
|
||||||
// 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) {
|
||||||
if let Some(iter) = find_nodes(name, &tree, offset) {
|
for name in find_nodes(name, &tree, offset).filter_map(ast::NameLike::cast) {
|
||||||
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) => {
|
ast::NameLike::Name(name) => self.found_name(&name, sink),
|
||||||
self.found_name_ref(&name_ref, sink)
|
ast::NameLike::Lifetime(lifetime) => self.found_lifetime(&lifetime, sink),
|
||||||
}
|
} {
|
||||||
ast::NameLike::Name(name) => self.found_name(&name, sink),
|
return;
|
||||||
ast::NameLike::Lifetime(lifetime) => {
|
|
||||||
self.found_lifetime(&lifetime, sink)
|
|
||||||
}
|
|
||||||
} {
|
|
||||||
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) {
|
||||||
if let Some(iter) = find_nodes("Self", &tree, offset) {
|
for name_ref in find_nodes("Self", &tree, offset).filter_map(ast::NameRef::cast)
|
||||||
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;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -513,21 +512,21 @@ 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) {
|
||||||
if let Some(iter) = find_nodes("super", &tree, offset) {
|
for name_ref in
|
||||||
for name_ref in iter.filter_map(ast::NameRef::cast) {
|
find_nodes("super", &tree, offset).filter_map(ast::NameRef::cast)
|
||||||
if self.found_name_ref(&name_ref, sink) {
|
{
|
||||||
return;
|
if self.found_name_ref(&name_ref, sink) {
|
||||||
}
|
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) {
|
||||||
if let Some(iter) = find_nodes("crate", &tree, offset) {
|
for name_ref in
|
||||||
for name_ref in iter.filter_map(ast::NameRef::cast) {
|
find_nodes("crate", &tree, offset).filter_map(ast::NameRef::cast)
|
||||||
if self.found_name_ref(&name_ref, sink) {
|
{
|
||||||
return;
|
if self.found_name_ref(&name_ref, sink) {
|
||||||
}
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -566,11 +565,10 @@ 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) {
|
||||||
if let Some(iter) = find_nodes("self", &tree, offset) {
|
for name_ref in find_nodes("self", &tree, offset).filter_map(ast::NameRef::cast)
|
||||||
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;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2016,4 +2016,19 @@ fn method$0() {}
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn raw_identifier() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
fn r#fn$0() {}
|
||||||
|
fn main() { r#fn(); }
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
r#fn Function FileId(0) 0..12 3..7
|
||||||
|
|
||||||
|
FileId(0) 25..29
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1371,7 +1371,6 @@ pub fn baz() {}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rename_mod_from_raw_ident() {
|
fn test_rename_mod_from_raw_ident() {
|
||||||
// FIXME: `r#fn` in path expression is not renamed.
|
|
||||||
check_expect(
|
check_expect(
|
||||||
"foo",
|
"foo",
|
||||||
r#"
|
r#"
|
||||||
|
@ -1397,6 +1396,10 @@ pub fn baz() {}
|
||||||
insert: "foo",
|
insert: "foo",
|
||||||
delete: 4..8,
|
delete: 4..8,
|
||||||
},
|
},
|
||||||
|
Indel {
|
||||||
|
insert: "foo",
|
||||||
|
delete: 23..27,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue