Use memmem when searching for usages in ide-db

This commit is contained in:
Lukas Wirth 2022-09-16 16:26:54 +02:00
parent 2b61be2975
commit b73fa0be9c
3 changed files with 21 additions and 11 deletions

1
Cargo.lock generated
View File

@ -660,6 +660,7 @@ dependencies = [
"indexmap", "indexmap",
"itertools", "itertools",
"limit", "limit",
"memchr",
"once_cell", "once_cell",
"parser", "parser",
"profile", "profile",

View File

@ -20,6 +20,7 @@ either = "1.7.0"
itertools = "0.10.3" itertools = "0.10.3"
arrayvec = "0.7.2" arrayvec = "0.7.2"
indexmap = "1.9.1" indexmap = "1.9.1"
memchr = "2.5.0"
stdx = { path = "../stdx", version = "0.0.0" } stdx = { path = "../stdx", version = "0.0.0" }
parser = { path = "../parser", version = "0.0.0" } parser = { path = "../parser", version = "0.0.0" }

View File

@ -8,6 +8,7 @@
use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt}; use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt};
use hir::{DefWithBody, HasAttrs, HasSource, InFile, ModuleSource, Semantics, Visibility}; use hir::{DefWithBody, HasAttrs, HasSource, InFile, ModuleSource, Semantics, Visibility};
use memchr::memmem::Finder;
use once_cell::unsync::Lazy; use once_cell::unsync::Lazy;
use parser::SyntaxKind; use parser::SyntaxKind;
use stdx::hash::NoHashHashMap; use stdx::hash::NoHashHashMap;
@ -411,14 +412,17 @@ fn search(&self, sink: &mut dyn FnMut(FileId, FileReference) -> bool) {
Some(s) => s.as_str(), Some(s) => s.as_str(),
None => return, None => return,
}; };
let finder = &Finder::new(name);
let include_self_kw_refs =
self.include_self_kw_refs.as_ref().map(|ty| (ty, Finder::new("Self")));
// these can't be closures because rust infers the lifetimes wrong ... // for<'a> |text: &'a str, name: &'a str, search_range: TextRange| -> impl Iterator<Item = TextSize> + 'a { ... }
fn match_indices<'a>( fn match_indices<'a>(
text: &'a str, text: &'a str,
name: &'a str, finder: &'a Finder<'a>,
search_range: TextRange, search_range: TextRange,
) -> impl Iterator<Item = TextSize> + 'a { ) -> impl Iterator<Item = TextSize> + 'a {
text.match_indices(name).filter_map(move |(idx, _)| { finder.find_iter(text.as_bytes()).filter_map(move |idx| {
let offset: TextSize = idx.try_into().unwrap(); let offset: TextSize = idx.try_into().unwrap();
if !search_range.contains_inclusive(offset) { if !search_range.contains_inclusive(offset) {
return None; return None;
@ -427,6 +431,7 @@ fn match_indices<'a>(
}) })
} }
// for<'a> |scope: &'a SearchScope| -> impl Iterator<Item = (Arc<String>, FileId, TextRange)> + 'a { ... }
fn scope_files<'a>( fn scope_files<'a>(
sema: &'a Semantics<'_, RootDatabase>, sema: &'a Semantics<'_, RootDatabase>,
scope: &'a SearchScope, scope: &'a SearchScope,
@ -450,7 +455,7 @@ fn scope_files<'a>(
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, name, search_range) { for offset in match_indices(&text, finder, search_range) {
for name in sema.find_nodes_at_offset_with_descend(&tree, offset) { for name in sema.find_nodes_at_offset_with_descend(&tree, offset) {
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),
@ -462,8 +467,8 @@ fn scope_files<'a>(
} }
} }
// 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) = &self.include_self_kw_refs { if let Some((self_ty, finder)) = &include_self_kw_refs {
for offset in match_indices(&text, "Self", search_range) { for offset in match_indices(&text, finder, search_range) {
for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) { 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) { if self.found_self_ty_name_ref(self_ty, &name_ref, sink) {
return; return;
@ -479,20 +484,22 @@ fn scope_files<'a>(
let scope = search_scope let scope = search_scope
.intersection(&SearchScope::module_and_children(self.sema.db, module)); .intersection(&SearchScope::module_and_children(self.sema.db, module));
let is_crate_root = module.is_crate_root(self.sema.db); let is_crate_root =
module.is_crate_root(self.sema.db).then(|| Finder::new("crate"));
let finder = &Finder::new("super");
for (text, file_id, search_range) in scope_files(sema, &scope) { for (text, file_id, search_range) in scope_files(sema, &scope) {
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, "super", search_range) { for offset in match_indices(&text, finder, search_range) {
for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) { for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) {
if self.found_name_ref(&name_ref, sink) { if self.found_name_ref(&name_ref, sink) {
return; return;
} }
} }
} }
if is_crate_root { if let Some(finder) = &is_crate_root {
for offset in match_indices(&text, "crate", search_range) { for offset in match_indices(&text, finder, search_range) {
for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) { for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) {
if self.found_name_ref(&name_ref, sink) { if self.found_name_ref(&name_ref, sink) {
return; return;
@ -533,8 +540,9 @@ fn scope_files<'a>(
search_range.unwrap_or_else(|| TextRange::up_to(TextSize::of(text.as_str()))); search_range.unwrap_or_else(|| TextRange::up_to(TextSize::of(text.as_str())));
let tree = Lazy::new(|| sema.parse(file_id).syntax().clone()); let tree = Lazy::new(|| sema.parse(file_id).syntax().clone());
let finder = &Finder::new("self");
for offset in match_indices(&text, "self", search_range) { for offset in match_indices(&text, finder, search_range) {
for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) { for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) {
if self.found_self_module_name_ref(&name_ref, sink) { if self.found_self_module_name_ref(&name_ref, sink) {
return; return;