Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-db/src/search.rs')
-rw-r--r--crates/ide-db/src/search.rs52
1 files changed, 50 insertions, 2 deletions
diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs
index 69459a4b72..a0655341fa 100644
--- a/crates/ide-db/src/search.rs
+++ b/crates/ide-db/src/search.rs
@@ -449,6 +449,8 @@ impl Definition {
scope: None,
include_self_kw_refs: None,
search_self_mod: false,
+ excluded_categories: ReferenceCategory::empty(),
+ exclude_library_files: false,
}
}
}
@@ -465,6 +467,10 @@ pub struct FindUsages<'a> {
include_self_kw_refs: Option<hir::Type<'a>>,
/// whether to search for the `self` module
search_self_mod: bool,
+ /// categories to exclude while collecting usages
+ excluded_categories: ReferenceCategory,
+ /// whether to skip files from library source roots
+ exclude_library_files: bool,
}
impl<'a> FindUsages<'a> {
@@ -495,6 +501,16 @@ impl<'a> FindUsages<'a> {
self
}
+ pub fn set_excluded_categories(mut self, categories: ReferenceCategory) -> Self {
+ self.excluded_categories = categories;
+ self
+ }
+
+ pub fn set_exclude_library_files(mut self, exclude_library_files: bool) -> Self {
+ self.exclude_library_files = exclude_library_files;
+ self
+ }
+
pub fn at_least_one(&self) -> bool {
let mut found = false;
self.search(&mut |_, _| {
@@ -599,7 +615,7 @@ impl<'a> FindUsages<'a> {
search_scope: &SearchScope,
name: &str,
) -> bool {
- if self.scope.is_some() {
+ if self.scope.is_some() || self.exclude_library_files {
return false;
}
@@ -922,7 +938,7 @@ impl<'a> FindUsages<'a> {
let _p = tracing::info_span!("FindUsages:search").entered();
let sema = self.sema;
- let search_scope = {
+ let mut search_scope = {
// FIXME: Is the trait scope needed for trait impl assoc items?
let base =
as_trait_assoc_def(sema.db, self.def).unwrap_or(self.def).search_scope(sema.db);
@@ -931,6 +947,14 @@ impl<'a> FindUsages<'a> {
Some(scope) => base.intersection(scope),
}
};
+ if self.exclude_library_files {
+ search_scope
+ .entries
+ .retain(|&file_id, _| !is_library_file(sema.db, file_id.file_id(sema.db)));
+ }
+ if search_scope.entries.is_empty() {
+ return;
+ }
let name = match (self.rename, self.def) {
(Some(rename), _) => {
@@ -1118,6 +1142,10 @@ impl<'a> FindUsages<'a> {
name_ref: &ast::NameRef,
sink: &mut dyn FnMut(EditionedFileId, FileReference) -> bool,
) -> bool {
+ if self.is_excluded_name_ref(name_ref) {
+ return false;
+ }
+
// See https://github.com/rust-lang/rust-analyzer/pull/15864/files/e0276dc5ddc38c65240edb408522bb869f15afb4#r1389848845
let ty_eq = |ty: hir::Type<'_>| match (ty.as_adt(), self_ty.as_adt()) {
(Some(ty), Some(self_ty)) => ty == self_ty,
@@ -1146,6 +1174,10 @@ impl<'a> FindUsages<'a> {
name_ref: &ast::NameRef,
sink: &mut dyn FnMut(EditionedFileId, FileReference) -> bool,
) -> bool {
+ if self.is_excluded_name_ref(name_ref) {
+ return false;
+ }
+
match NameRefClass::classify(self.sema, name_ref) {
Some(NameRefClass::Definition(def @ Definition::Module(_), _)) if def == self.def => {
let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax());
@@ -1210,6 +1242,10 @@ impl<'a> FindUsages<'a> {
name_ref: &ast::NameRef,
sink: &mut dyn FnMut(EditionedFileId, FileReference) -> bool,
) -> bool {
+ if self.is_excluded_name_ref(name_ref) {
+ return false;
+ }
+
match NameRefClass::classify(self.sema, name_ref) {
Some(NameRefClass::Definition(def, _))
if self.def == def
@@ -1283,6 +1319,13 @@ impl<'a> FindUsages<'a> {
}
}
+ fn is_excluded_name_ref(&self, name_ref: &ast::NameRef) -> bool {
+ (self.excluded_categories.contains(ReferenceCategory::TEST)
+ && is_name_ref_in_test(self.sema, name_ref))
+ || (self.excluded_categories.contains(ReferenceCategory::IMPORT)
+ && is_name_ref_in_import(name_ref))
+ }
+
fn found_name(
&self,
name: &ast::Name,
@@ -1409,3 +1452,8 @@ fn is_name_ref_in_test(sema: &Semantics<'_, RootDatabase>, name_ref: &ast::NameR
None => false,
})
}
+
+fn is_library_file(db: &RootDatabase, file_id: span::FileId) -> bool {
+ let source_root = db.file_source_root(file_id).source_root_id(db);
+ db.source_root(source_root).source_root(db).is_library
+}