@@ -449,6 +449,8 @@ impl Definition {
449449 scope : None ,
450450 include_self_kw_refs : None ,
451451 search_self_mod : false ,
452+ included_categories : ReferenceCategory :: all ( ) ,
453+ exclude_library_files : false ,
452454 }
453455 }
454456}
@@ -465,6 +467,10 @@ pub struct FindUsages<'a> {
465467 include_self_kw_refs : Option < hir:: Type < ' a > > ,
466468 /// whether to search for the `self` module
467469 search_self_mod : bool ,
470+ /// categories to include while collecting usages
471+ included_categories : ReferenceCategory ,
472+ /// whether to skip files from library source roots
473+ exclude_library_files : bool ,
468474}
469475
470476impl < ' a > FindUsages < ' a > {
@@ -495,6 +501,16 @@ impl<'a> FindUsages<'a> {
495501 self
496502 }
497503
504+ pub fn set_included_categories ( mut self , categories : ReferenceCategory ) -> Self {
505+ self . included_categories = categories;
506+ self
507+ }
508+
509+ pub fn set_exclude_library_files ( mut self , exclude_library_files : bool ) -> Self {
510+ self . exclude_library_files = exclude_library_files;
511+ self
512+ }
513+
498514 pub fn at_least_one ( & self ) -> bool {
499515 let mut found = false ;
500516 self . search ( & mut |_, _| {
@@ -516,14 +532,21 @@ impl<'a> FindUsages<'a> {
516532 fn scope_files < ' b > (
517533 db : & ' b RootDatabase ,
518534 scope : & ' b SearchScope ,
535+ exclude_library_files : bool ,
519536 ) -> impl Iterator < Item = ( Arc < str > , EditionedFileId , TextRange ) > + ' b {
520- scope. entries . iter ( ) . map ( |( & file_id, & search_range) | {
521- let text = db. file_text ( file_id. file_id ( db) ) . text ( db) ;
522- let search_range =
523- search_range. unwrap_or_else ( || TextRange :: up_to ( TextSize :: of ( & * * text) ) ) ;
537+ scope
538+ . entries
539+ . iter ( )
540+ . filter ( move |( file_id, _) | {
541+ !exclude_library_files || !is_library_file ( db, file_id. file_id ( db) )
542+ } )
543+ . map ( |( & file_id, & search_range) | {
544+ let text = db. file_text ( file_id. file_id ( db) ) . text ( db) ;
545+ let search_range =
546+ search_range. unwrap_or_else ( || TextRange :: up_to ( TextSize :: of ( & * * text) ) ) ;
524547
525- ( text. clone ( ) , file_id, search_range)
526- } )
548+ ( text. clone ( ) , file_id, search_range)
549+ } )
527550 }
528551
529552 fn match_indices < ' b > (
@@ -649,6 +672,7 @@ impl<'a> FindUsages<'a> {
649672 fn collect_possible_aliases (
650673 sema : & Semantics < ' _ , RootDatabase > ,
651674 container : Adt ,
675+ exclude_library_files : bool ,
652676 ) -> Option < ( FxHashSet < SmolStr > , Vec < FileRangeWrapper < EditionedFileId > > ) > {
653677 fn insert_type_alias (
654678 db : & RootDatabase ,
@@ -682,9 +706,11 @@ impl<'a> FindUsages<'a> {
682706 } ;
683707
684708 let finder = Finder :: new ( current_to_process. as_bytes ( ) ) ;
685- for ( file_text, file_id, search_range) in
686- FindUsages :: scope_files ( db, & current_to_process_search_scope)
687- {
709+ for ( file_text, file_id, search_range) in FindUsages :: scope_files (
710+ db,
711+ & current_to_process_search_scope,
712+ exclude_library_files,
713+ ) {
688714 let tree = LazyCell :: new ( move || sema. parse ( file_id) . syntax ( ) . clone ( ) ) ;
689715
690716 for offset in FindUsages :: match_indices ( & file_text, & finder, search_range) {
@@ -869,7 +895,7 @@ impl<'a> FindUsages<'a> {
869895 }
870896
871897 let Some ( ( container_possible_aliases, is_possibly_self) ) =
872- collect_possible_aliases ( self . sema , container)
898+ collect_possible_aliases ( self . sema , container, self . exclude_library_files )
873899 else {
874900 return false ;
875901 } ;
@@ -906,7 +932,7 @@ impl<'a> FindUsages<'a> {
906932 self ,
907933 & finder,
908934 name,
909- FindUsages :: scope_files ( self . sema . db , search_scope) ,
935+ FindUsages :: scope_files ( self . sema . db , search_scope, self . exclude_library_files ) ,
910936 |path, name_position| {
911937 has_any_name ( path, |name| container_possible_aliases. contains ( name) )
912938 && !self_positions. contains ( & name_position)
@@ -931,6 +957,9 @@ impl<'a> FindUsages<'a> {
931957 Some ( scope) => base. intersection ( scope) ,
932958 }
933959 } ;
960+ if search_scope. entries . is_empty ( ) {
961+ return ;
962+ }
934963
935964 let name = match ( self . rename , self . def ) {
936965 ( Some ( rename) , _) => {
@@ -982,7 +1011,9 @@ impl<'a> FindUsages<'a> {
9821011 let finder = & Finder :: new ( name) ;
9831012 let include_self_kw_refs =
9841013 self . include_self_kw_refs . as_ref ( ) . map ( |ty| ( ty, Finder :: new ( "Self" ) ) ) ;
985- for ( text, file_id, search_range) in Self :: scope_files ( sema. db , & search_scope) {
1014+ for ( text, file_id, search_range) in
1015+ Self :: scope_files ( sema. db , & search_scope, self . exclude_library_files )
1016+ {
9861017 let tree = LazyCell :: new ( move || sema. parse ( file_id) . syntax ( ) . clone ( ) ) ;
9871018
9881019 // Search for occurrences of the items name
@@ -1039,7 +1070,9 @@ impl<'a> FindUsages<'a> {
10391070 let is_crate_root = module. is_crate_root ( self . sema . db ) . then ( || Finder :: new ( "crate" ) ) ;
10401071 let finder = & Finder :: new ( "super" ) ;
10411072
1042- for ( text, file_id, search_range) in Self :: scope_files ( sema. db , & scope) {
1073+ for ( text, file_id, search_range) in
1074+ Self :: scope_files ( sema. db , & scope, self . exclude_library_files )
1075+ {
10431076 self . sema . db . unwind_if_revision_cancelled ( ) ;
10441077
10451078 let tree = LazyCell :: new ( move || sema. parse ( file_id) . syntax ( ) . clone ( ) ) ;
@@ -1118,6 +1151,10 @@ impl<'a> FindUsages<'a> {
11181151 name_ref : & ast:: NameRef ,
11191152 sink : & mut dyn FnMut ( EditionedFileId , FileReference ) -> bool ,
11201153 ) -> bool {
1154+ if self . is_excluded_name_ref ( name_ref) {
1155+ return false ;
1156+ }
1157+
11211158 // See https://github.com/rust-lang/rust-analyzer/pull/15864/files/e0276dc5ddc38c65240edb408522bb869f15afb4#r1389848845
11221159 let ty_eq = |ty : hir:: Type < ' _ > | match ( ty. as_adt ( ) , self_ty. as_adt ( ) ) {
11231160 ( Some ( ty) , Some ( self_ty) ) => ty == self_ty,
@@ -1146,6 +1183,10 @@ impl<'a> FindUsages<'a> {
11461183 name_ref : & ast:: NameRef ,
11471184 sink : & mut dyn FnMut ( EditionedFileId , FileReference ) -> bool ,
11481185 ) -> bool {
1186+ if self . is_excluded_name_ref ( name_ref) {
1187+ return false ;
1188+ }
1189+
11491190 match NameRefClass :: classify ( self . sema , name_ref) {
11501191 Some ( NameRefClass :: Definition ( def @ Definition :: Module ( _) , _) ) if def == self . def => {
11511192 let FileRange { file_id, range } = self . sema . original_range ( name_ref. syntax ( ) ) ;
@@ -1210,6 +1251,10 @@ impl<'a> FindUsages<'a> {
12101251 name_ref : & ast:: NameRef ,
12111252 sink : & mut dyn FnMut ( EditionedFileId , FileReference ) -> bool ,
12121253 ) -> bool {
1254+ if self . is_excluded_name_ref ( name_ref) {
1255+ return false ;
1256+ }
1257+
12131258 match NameRefClass :: classify ( self . sema , name_ref) {
12141259 Some ( NameRefClass :: Definition ( def, _) )
12151260 if self . def == def
@@ -1282,6 +1327,13 @@ impl<'a> FindUsages<'a> {
12821327 }
12831328 }
12841329
1330+ fn is_excluded_name_ref ( & self , name_ref : & ast:: NameRef ) -> bool {
1331+ ( !self . included_categories . contains ( ReferenceCategory :: TEST )
1332+ && is_name_ref_in_test ( self . sema , name_ref) )
1333+ || ( !self . included_categories . contains ( ReferenceCategory :: IMPORT )
1334+ && is_name_ref_in_import ( name_ref) )
1335+ }
1336+
12851337 fn found_name (
12861338 & self ,
12871339 name : & ast:: Name ,
@@ -1408,3 +1460,8 @@ fn is_name_ref_in_test(sema: &Semantics<'_, RootDatabase>, name_ref: &ast::NameR
14081460 None => false ,
14091461 } )
14101462}
1463+
1464+ fn is_library_file ( db : & RootDatabase , file_id : span:: FileId ) -> bool {
1465+ let source_root = db. file_source_root ( file_id) . source_root_id ( db) ;
1466+ db. source_root ( source_root) . source_root ( db) . is_library
1467+ }
0 commit comments