@@ -64,7 +64,7 @@ pub struct FileReference {
6464 pub range : TextRange ,
6565 /// The node of the reference in the (macro-)file
6666 pub name : FileReferenceNode ,
67- pub category : Option < ReferenceCategory > ,
67+ pub category : ReferenceCategory ,
6868}
6969
7070#[ derive( Debug , Clone ) ]
@@ -124,17 +124,16 @@ impl FileReferenceNode {
124124 }
125125}
126126
127- #[ derive( Debug , Copy , Clone , PartialEq , Eq , Hash ) ]
128- pub enum ReferenceCategory {
129- // FIXME: Add this variant and delete the `retain_adt_literal_usages` function.
130- // Create
131- Write ,
132- Read ,
133- Import ,
134- // FIXME: Some day should be able to search in doc comments. Would probably
135- // need to switch from enum to bitflags then?
136- // DocComment
137- Test ,
127+ bitflags:: bitflags! {
128+ #[ derive( Copy , Clone , Default , PartialEq , Eq , Hash , Debug ) ]
129+ pub struct ReferenceCategory : u8 {
130+ // FIXME: Add this variant and delete the `retain_adt_literal_usages` function.
131+ // const CREATE = 1 << 0;
132+ const WRITE = 1 << 0 ;
133+ const READ = 1 << 1 ;
134+ const IMPORT = 1 << 2 ;
135+ const TEST = 1 << 3 ;
136+ }
138137}
139138
140139/// Generally, `search_scope` returns files that might contain references for the element.
@@ -660,7 +659,7 @@ impl<'a> FindUsages<'a> {
660659 let reference = FileReference {
661660 range,
662661 name : FileReferenceNode :: NameRef ( name_ref. clone ( ) ) ,
663- category : None ,
662+ category : ReferenceCategory :: empty ( ) ,
664663 } ;
665664 sink ( file_id, reference)
666665 }
@@ -676,10 +675,15 @@ impl<'a> FindUsages<'a> {
676675 match NameRefClass :: classify ( self . sema , name_ref) {
677676 Some ( NameRefClass :: Definition ( def @ Definition :: Module ( _) ) ) if def == self . def => {
678677 let FileRange { file_id, range } = self . sema . original_range ( name_ref. syntax ( ) ) ;
678+ let category = if is_name_ref_in_import ( name_ref) {
679+ ReferenceCategory :: IMPORT
680+ } else {
681+ ReferenceCategory :: empty ( )
682+ } ;
679683 let reference = FileReference {
680684 range,
681685 name : FileReferenceNode :: NameRef ( name_ref. clone ( ) ) ,
682- category : is_name_ref_in_import ( name_ref ) . then_some ( ReferenceCategory :: Import ) ,
686+ category,
683687 } ;
684688 sink ( file_id, reference)
685689 }
@@ -700,7 +704,7 @@ impl<'a> FindUsages<'a> {
700704 let reference = FileReference {
701705 range,
702706 name : FileReferenceNode :: FormatStringEntry ( token, range) ,
703- category : Some ( ReferenceCategory :: Read ) ,
707+ category : ReferenceCategory :: READ ,
704708 } ;
705709 sink ( file_id, reference)
706710 }
@@ -719,7 +723,7 @@ impl<'a> FindUsages<'a> {
719723 let reference = FileReference {
720724 range,
721725 name : FileReferenceNode :: Lifetime ( lifetime. clone ( ) ) ,
722- category : None ,
726+ category : ReferenceCategory :: empty ( ) ,
723727 } ;
724728 sink ( file_id, reference)
725729 }
@@ -817,7 +821,7 @@ impl<'a> FindUsages<'a> {
817821 range,
818822 name : FileReferenceNode :: Name ( name. clone ( ) ) ,
819823 // FIXME: mutable patterns should have `Write` access
820- category : Some ( ReferenceCategory :: Read ) ,
824+ category : ReferenceCategory :: READ ,
821825 } ;
822826 sink ( file_id, reference)
823827 }
@@ -826,7 +830,7 @@ impl<'a> FindUsages<'a> {
826830 let reference = FileReference {
827831 range,
828832 name : FileReferenceNode :: Name ( name. clone ( ) ) ,
829- category : None ,
833+ category : ReferenceCategory :: empty ( ) ,
830834 } ;
831835 sink ( file_id, reference)
832836 }
@@ -851,7 +855,7 @@ impl<'a> FindUsages<'a> {
851855 let reference = FileReference {
852856 range,
853857 name : FileReferenceNode :: Name ( name. clone ( ) ) ,
854- category : None ,
858+ category : ReferenceCategory :: empty ( ) ,
855859 } ;
856860 sink ( file_id, reference)
857861 }
@@ -875,38 +879,41 @@ impl ReferenceCategory {
875879 sema : & Semantics < ' _ , RootDatabase > ,
876880 def : & Definition ,
877881 r : & ast:: NameRef ,
878- ) -> Option < ReferenceCategory > {
882+ ) -> ReferenceCategory {
883+ let mut result = ReferenceCategory :: empty ( ) ;
879884 if is_name_ref_in_test ( sema, r) {
880- return Some ( ReferenceCategory :: Test ) ;
885+ result |= ReferenceCategory :: TEST ;
881886 }
882887
883888 // Only Locals and Fields have accesses for now.
884889 if !matches ! ( def, Definition :: Local ( _) | Definition :: Field ( _) ) {
885- return is_name_ref_in_import ( r) . then_some ( ReferenceCategory :: Import ) ;
890+ if is_name_ref_in_import ( r) {
891+ result |= ReferenceCategory :: IMPORT ;
892+ }
893+ return result;
886894 }
887895
888896 let mode = r. syntax ( ) . ancestors ( ) . find_map ( |node| {
889- match_ast ! {
890- match node {
891- ast:: BinExpr ( expr) => {
892- if matches!( expr. op_kind( ) ?, ast:: BinaryOp :: Assignment { .. } ) {
893- // If the variable or field ends on the LHS's end then it's a Write (covers fields and locals).
894- // FIXME: This is not terribly accurate.
895- if let Some ( lhs) = expr. lhs( ) {
896- if lhs. syntax( ) . text_range( ) . end( ) == r. syntax( ) . text_range( ) . end( ) {
897- return Some ( ReferenceCategory :: Write ) ;
897+ match_ast ! {
898+ match node {
899+ ast:: BinExpr ( expr) => {
900+ if matches!( expr. op_kind( ) ?, ast:: BinaryOp :: Assignment { .. } ) {
901+ // If the variable or field ends on the LHS's end then it's a Write
902+ // (covers fields and locals). FIXME: This is not terribly accurate.
903+ if let Some ( lhs) = expr. lhs( ) {
904+ if lhs. syntax( ) . text_range( ) . end( ) == r. syntax( ) . text_range( ) . end( ) {
905+ return Some ( ReferenceCategory :: WRITE )
906+ }
898907 }
899908 }
900- }
901- Some ( ReferenceCategory :: Read )
902- } ,
903- _ => None
909+ Some ( ReferenceCategory :: READ )
910+ } ,
911+ _ => None ,
912+ }
904913 }
905- }
906- } ) ;
914+ } ) . unwrap_or ( ReferenceCategory :: READ ) ;
907915
908- // Default Locals and Fields to read
909- mode. or ( Some ( ReferenceCategory :: Read ) )
916+ result | mode
910917 }
911918}
912919
0 commit comments