about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--crates/ide-db/Cargo.toml1
-rw-r--r--crates/ide-db/src/search.rs30
3 files changed, 21 insertions, 11 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 9f10d92c4e3..eaadcc8b8c6 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -660,6 +660,7 @@ dependencies = [
  "indexmap",
  "itertools",
  "limit",
+ "memchr",
  "once_cell",
  "parser",
  "profile",
diff --git a/crates/ide-db/Cargo.toml b/crates/ide-db/Cargo.toml
index a1b0bd6cb30..30272bc16f6 100644
--- a/crates/ide-db/Cargo.toml
+++ b/crates/ide-db/Cargo.toml
@@ -20,6 +20,7 @@ either = "1.7.0"
 itertools = "0.10.3"
 arrayvec = "0.7.2"
 indexmap = "1.9.1"
+memchr = "2.5.0"
 
 stdx = { path = "../stdx", version = "0.0.0" }
 parser = { path = "../parser", version = "0.0.0" }
diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs
index 6f885fba783..7cabdb55e8d 100644
--- a/crates/ide-db/src/search.rs
+++ b/crates/ide-db/src/search.rs
@@ -8,6 +8,7 @@ use std::{mem, sync::Arc};
 
 use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt};
 use hir::{DefWithBody, HasAttrs, HasSource, InFile, ModuleSource, Semantics, Visibility};
+use memchr::memmem::Finder;
 use once_cell::unsync::Lazy;
 use parser::SyntaxKind;
 use stdx::hash::NoHashHashMap;
@@ -411,14 +412,17 @@ impl<'a> FindUsages<'a> {
             Some(s) => s.as_str(),
             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>(
             text: &'a str,
-            name: &'a str,
+            finder: &'a Finder<'a>,
             search_range: TextRange,
         ) -> 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();
                 if !search_range.contains_inclusive(offset) {
                     return None;
@@ -427,6 +431,7 @@ impl<'a> FindUsages<'a> {
             })
         }
 
+        // for<'a> |scope: &'a SearchScope| -> impl Iterator<Item = (Arc<String>, FileId, TextRange)> + 'a { ... }
         fn scope_files<'a>(
             sema: &'a Semantics<'_, RootDatabase>,
             scope: &'a SearchScope,
@@ -450,7 +455,7 @@ impl<'a> FindUsages<'a> {
             let tree = Lazy::new(move || sema.parse(file_id).syntax().clone());
 
             // 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) {
                     if match name {
                         ast::NameLike::NameRef(name_ref) => self.found_name_ref(&name_ref, sink),
@@ -462,8 +467,8 @@ impl<'a> FindUsages<'a> {
                 }
             }
             // Search for occurrences of the `Self` referring to our type
-            if let Some(self_ty) = &self.include_self_kw_refs {
-                for offset in match_indices(&text, "Self", search_range) {
+            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;
@@ -479,20 +484,22 @@ impl<'a> FindUsages<'a> {
                 let scope = search_scope
                     .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) {
                     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) {
                             if self.found_name_ref(&name_ref, sink) {
                                 return;
                             }
                         }
                     }
-                    if is_crate_root {
-                        for offset in match_indices(&text, "crate", search_range) {
+                    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;
@@ -533,8 +540,9 @@ impl<'a> FindUsages<'a> {
                     search_range.unwrap_or_else(|| TextRange::up_to(TextSize::of(text.as_str())));
 
                 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) {
                         if self.found_self_module_name_ref(&name_ref, sink) {
                             return;