@@ -21,7 +21,7 @@ use ide_db::{
21
21
use syntax:: {
22
22
algo:: find_node_at_offset,
23
23
ast:: { self , NameOwner } ,
24
- AstNode , SyntaxKind , SyntaxNode , TextRange , TokenAtOffset ,
24
+ match_ast , AstNode , SyntaxKind , SyntaxNode , TextRange , TokenAtOffset ,
25
25
} ;
26
26
27
27
use crate :: { display:: TryToNav , FilePosition , FileRange , NavigationTarget , RangeInfo } ;
@@ -89,6 +89,10 @@ pub(crate) fn find_all_refs(
89
89
let _p = profile:: span ( "find_all_refs" ) ;
90
90
let syntax = sema. parse ( position. file_id ) . syntax ( ) . clone ( ) ;
91
91
92
+ if let Some ( res) = try_find_self_references ( & syntax, position) {
93
+ return Some ( res) ;
94
+ }
95
+
92
96
let ( opt_name, search_kind) = if let Some ( name) =
93
97
get_struct_def_name_for_struct_literal_search ( & sema, & syntax, position)
94
98
{
@@ -194,6 +198,77 @@ fn get_struct_def_name_for_struct_literal_search(
194
198
None
195
199
}
196
200
201
+ fn try_find_self_references (
202
+ syntax : & SyntaxNode ,
203
+ position : FilePosition ,
204
+ ) -> Option < RangeInfo < ReferenceSearchResult > > {
205
+ let self_token =
206
+ syntax. token_at_offset ( position. offset ) . find ( |t| t. kind ( ) == SyntaxKind :: SELF_KW ) ?;
207
+ let parent = self_token. parent ( ) ;
208
+ match_ast ! {
209
+ match parent {
210
+ ast:: SelfParam ( it) => ( ) ,
211
+ ast:: PathSegment ( segment) => {
212
+ segment. self_token( ) ?;
213
+ let path = segment. parent_path( ) ;
214
+ if path. qualifier( ) . is_some( ) && !ast:: PathExpr :: can_cast( path. syntax( ) . parent( ) ?. kind( ) ) {
215
+ return None ;
216
+ }
217
+ } ,
218
+ _ => return None ,
219
+ }
220
+ } ;
221
+ let function = parent. ancestors ( ) . find_map ( ast:: Fn :: cast) ?;
222
+ let self_param = function. param_list ( ) ?. self_param ( ) ?;
223
+ let param_self_token = self_param. self_token ( ) ?;
224
+
225
+ let declaration = Declaration {
226
+ nav : NavigationTarget {
227
+ file_id : position. file_id ,
228
+ full_range : self_param. syntax ( ) . text_range ( ) ,
229
+ focus_range : Some ( param_self_token. text_range ( ) ) ,
230
+ name : param_self_token. text ( ) . clone ( ) ,
231
+ kind : param_self_token. kind ( ) ,
232
+ container_name : None ,
233
+ description : None ,
234
+ docs : None ,
235
+ } ,
236
+ kind : ReferenceKind :: SelfKw ,
237
+ access : Some ( if self_param. mut_token ( ) . is_some ( ) {
238
+ ReferenceAccess :: Write
239
+ } else {
240
+ ReferenceAccess :: Read
241
+ } ) ,
242
+ } ;
243
+ let references = function
244
+ . body ( )
245
+ . map ( |body| {
246
+ body. syntax ( )
247
+ . descendants ( )
248
+ . filter_map ( ast:: PathExpr :: cast)
249
+ . filter_map ( |expr| {
250
+ let path = expr. path ( ) ?;
251
+ if path. qualifier ( ) . is_none ( ) {
252
+ path. segment ( ) ?. self_token ( )
253
+ } else {
254
+ None
255
+ }
256
+ } )
257
+ . map ( |token| Reference {
258
+ file_range : FileRange { file_id : position. file_id , range : token. text_range ( ) } ,
259
+ kind : ReferenceKind :: SelfKw ,
260
+ access : declaration. access , // FIXME: properly check access kind here instead of copying it from the declaration
261
+ } )
262
+ . collect ( )
263
+ } )
264
+ . unwrap_or_default ( ) ;
265
+
266
+ Some ( RangeInfo :: new (
267
+ param_self_token. text_range ( ) ,
268
+ ReferenceSearchResult { declaration, references } ,
269
+ ) )
270
+ }
271
+
197
272
#[ cfg( test) ]
198
273
mod tests {
199
274
use expect_test:: { expect, Expect } ;
@@ -762,6 +837,32 @@ fn f() -> m::En {
762
837
) ;
763
838
}
764
839
840
+ #[ test]
841
+ fn test_find_self_refs ( ) {
842
+ check (
843
+ r#"
844
+ struct Foo { bar: i32 }
845
+
846
+ impl Foo {
847
+ fn foo(self) {
848
+ let x = self<|>.bar;
849
+ if true {
850
+ let _ = match () {
851
+ () => self,
852
+ };
853
+ }
854
+ }
855
+ }
856
+ "# ,
857
+ expect ! [ [ r#"
858
+ self SELF_KW FileId(0) 47..51 47..51 SelfKw Read
859
+
860
+ FileId(0) 71..75 SelfKw Read
861
+ FileId(0) 152..156 SelfKw Read
862
+ "# ] ] ,
863
+ ) ;
864
+ }
865
+
765
866
fn check ( ra_fixture : & str , expect : Expect ) {
766
867
check_with_scope ( ra_fixture, None , expect)
767
868
}
0 commit comments