@@ -112,25 +112,20 @@ impl IntoIterator for ReferenceSearchResult {
112
112
113
113
pub ( crate ) fn find_all_refs (
114
114
db : & RootDatabase ,
115
- mut position : FilePosition ,
115
+ position : FilePosition ,
116
116
search_scope : Option < SearchScope > ,
117
117
) -> Option < RangeInfo < ReferenceSearchResult > > {
118
118
let parse = db. parse ( position. file_id ) ;
119
119
let syntax = parse. tree ( ) . syntax ( ) . clone ( ) ;
120
120
121
- let token = syntax. token_at_offset ( position. offset ) ;
122
- let mut search_kind = ReferenceKind :: Other ;
121
+ let ( opt_name, search_kind) =
122
+ if let Some ( name) = get_struct_def_name_for_struc_litetal_search ( & syntax, position) {
123
+ ( Some ( name) , ReferenceKind :: StructLiteral )
124
+ } else {
125
+ ( find_node_at_offset :: < ast:: Name > ( & syntax, position. offset ) , ReferenceKind :: Other )
126
+ } ;
123
127
124
- if let TokenAtOffset :: Between ( ref left, ref right) = token {
125
- if ( right. kind ( ) == SyntaxKind :: L_CURLY || right. kind ( ) == SyntaxKind :: L_PAREN )
126
- && left. kind ( ) != SyntaxKind :: IDENT
127
- {
128
- position = FilePosition { offset : left. text_range ( ) . start ( ) , ..position } ;
129
- search_kind = ReferenceKind :: StructLiteral ;
130
- }
131
- }
132
-
133
- let RangeInfo { range, info : ( name, def) } = find_name ( db, & syntax, position) ?;
128
+ let RangeInfo { range, info : ( name, def) } = find_name ( db, & syntax, position, opt_name) ?;
134
129
135
130
let declaration = match def. kind {
136
131
NameKind :: Macro ( mac) => mac. to_nav ( db) ,
@@ -170,9 +165,10 @@ fn find_name(
170
165
db : & RootDatabase ,
171
166
syntax : & SyntaxNode ,
172
167
position : FilePosition ,
168
+ opt_name : Option < ast:: Name > ,
173
169
) -> Option < RangeInfo < ( String , NameDefinition ) > > {
174
170
let mut sb = SourceBinder :: new ( db) ;
175
- if let Some ( name) = find_node_at_offset :: < ast :: Name > ( & syntax , position . offset ) {
171
+ if let Some ( name) = opt_name {
176
172
let def = classify_name ( & mut sb, InFile :: new ( position. file_id . into ( ) , & name) ) ?;
177
173
let range = name. syntax ( ) . text_range ( ) ;
178
174
return Some ( RangeInfo :: new ( range, ( name. text ( ) . to_string ( ) , def) ) ) ;
@@ -218,15 +214,8 @@ fn process_definition(
218
214
if let Some ( d) = classify_name_ref ( & mut sb, InFile :: new ( file_id. into ( ) , & name_ref) )
219
215
{
220
216
if d == def {
221
- let kind = if name_ref
222
- . syntax ( )
223
- . ancestors ( )
224
- . find_map ( ast:: RecordLit :: cast)
225
- . and_then ( |l| l. path ( ) )
226
- . and_then ( |p| p. segment ( ) )
227
- . and_then ( |p| p. name_ref ( ) )
228
- . map ( |n| n == name_ref)
229
- . unwrap_or ( false )
217
+ let kind = if is_record_lit_name_ref ( & name_ref)
218
+ || is_call_expr_name_ref ( & name_ref)
230
219
{
231
220
ReferenceKind :: StructLiteral
232
221
} else {
@@ -301,6 +290,49 @@ fn reference_access(kind: &NameKind, name_ref: &ast::NameRef) -> Option<Referenc
301
290
mode. or ( Some ( ReferenceAccess :: Read ) )
302
291
}
303
292
293
+ fn is_record_lit_name_ref ( name_ref : & ast:: NameRef ) -> bool {
294
+ name_ref
295
+ . syntax ( )
296
+ . ancestors ( )
297
+ . find_map ( ast:: RecordLit :: cast)
298
+ . and_then ( |l| l. path ( ) )
299
+ . and_then ( |p| p. segment ( ) )
300
+ . map ( |p| p. name_ref ( ) . as_ref ( ) == Some ( name_ref) )
301
+ . unwrap_or ( false )
302
+ }
303
+
304
+ fn get_struct_def_name_for_struc_litetal_search (
305
+ syntax : & SyntaxNode ,
306
+ position : FilePosition ,
307
+ ) -> Option < ast:: Name > {
308
+ if let TokenAtOffset :: Between ( ref left, ref right) = syntax. token_at_offset ( position. offset ) {
309
+ if right. kind ( ) != SyntaxKind :: L_CURLY && right. kind ( ) != SyntaxKind :: L_PAREN {
310
+ return None ;
311
+ }
312
+ if let Some ( name) = find_node_at_offset :: < ast:: Name > ( & syntax, left. text_range ( ) . start ( ) ) {
313
+ return name. syntax ( ) . ancestors ( ) . find_map ( ast:: StructDef :: cast) . and_then ( |l| l. name ( ) ) ;
314
+ }
315
+ if find_node_at_offset :: < ast:: TypeParamList > ( & syntax, left. text_range ( ) . start ( ) ) . is_some ( ) {
316
+ return left. ancestors ( ) . find_map ( ast:: StructDef :: cast) . and_then ( |l| l. name ( ) ) ;
317
+ }
318
+ }
319
+ None
320
+ }
321
+
322
+ fn is_call_expr_name_ref ( name_ref : & ast:: NameRef ) -> bool {
323
+ name_ref
324
+ . syntax ( )
325
+ . ancestors ( )
326
+ . find_map ( ast:: CallExpr :: cast)
327
+ . and_then ( |c| match c. expr ( ) ? {
328
+ ast:: Expr :: PathExpr ( p) => {
329
+ Some ( p. path ( ) ?. segment ( ) ?. name_ref ( ) . as_ref ( ) == Some ( name_ref) )
330
+ }
331
+ _ => None ,
332
+ } )
333
+ . unwrap_or ( false )
334
+ }
335
+
304
336
#[ cfg( test) ]
305
337
mod tests {
306
338
use crate :: {
@@ -309,7 +341,7 @@ mod tests {
309
341
} ;
310
342
311
343
#[ test]
312
- fn test_struct_literal ( ) {
344
+ fn test_struct_literal_after_space ( ) {
313
345
let code = r#"
314
346
struct Foo <|>{
315
347
a: i32,
@@ -330,6 +362,58 @@ mod tests {
330
362
) ;
331
363
}
332
364
365
+ #[ test]
366
+ fn test_struct_literal_befor_space ( ) {
367
+ let code = r#"
368
+ struct Foo<|> {}
369
+ fn main() {
370
+ let f: Foo;
371
+ f = Foo {};
372
+ }"# ;
373
+
374
+ let refs = get_all_refs ( code) ;
375
+ check_result (
376
+ refs,
377
+ "Foo STRUCT_DEF FileId(1) [5; 18) [12; 15) Other" ,
378
+ & [ "FileId(1) [54; 57) Other" , "FileId(1) [71; 74) StructLiteral" ] ,
379
+ ) ;
380
+ }
381
+
382
+ #[ test]
383
+ fn test_struct_literal_with_generic_type ( ) {
384
+ let code = r#"
385
+ struct Foo<T> <|>{}
386
+ fn main() {
387
+ let f: Foo::<i32>;
388
+ f = Foo {};
389
+ }"# ;
390
+
391
+ let refs = get_all_refs ( code) ;
392
+ check_result (
393
+ refs,
394
+ "Foo STRUCT_DEF FileId(1) [5; 21) [12; 15) Other" ,
395
+ & [ "FileId(1) [81; 84) StructLiteral" ] ,
396
+ ) ;
397
+ }
398
+
399
+ #[ test]
400
+ fn test_struct_literal_for_tuple ( ) {
401
+ let code = r#"
402
+ struct Foo<|>(i32);
403
+
404
+ fn main() {
405
+ let f: Foo;
406
+ f = Foo(1);
407
+ }"# ;
408
+
409
+ let refs = get_all_refs ( code) ;
410
+ check_result (
411
+ refs,
412
+ "Foo STRUCT_DEF FileId(1) [5; 21) [12; 15) Other" ,
413
+ & [ "FileId(1) [71; 74) StructLiteral" ] ,
414
+ ) ;
415
+ }
416
+
333
417
#[ test]
334
418
fn test_find_all_refs_for_local ( ) {
335
419
let code = r#"
@@ -564,15 +648,15 @@ mod tests {
564
648
check_result (
565
649
refs,
566
650
"quux FN_DEF FileId(1) [18; 34) [25; 29) Other" ,
567
- & [ "FileId(2) [16; 20) Other " , "FileId(3) [16; 20) Other " ] ,
651
+ & [ "FileId(2) [16; 20) StructLiteral " , "FileId(3) [16; 20) StructLiteral " ] ,
568
652
) ;
569
653
570
654
let refs =
571
655
analysis. find_all_refs ( pos, Some ( SearchScope :: single_file ( bar) ) ) . unwrap ( ) . unwrap ( ) ;
572
656
check_result (
573
657
refs,
574
658
"quux FN_DEF FileId(1) [18; 34) [25; 29) Other" ,
575
- & [ "FileId(3) [16; 20) Other " ] ,
659
+ & [ "FileId(3) [16; 20) StructLiteral " ] ,
576
660
) ;
577
661
}
578
662
@@ -591,7 +675,7 @@ mod tests {
591
675
check_result (
592
676
refs,
593
677
"m1 MACRO_CALL FileId(1) [9; 63) [46; 48) Other" ,
594
- & [ "FileId(1) [96; 98) Other " , "FileId(1) [114; 116) Other " ] ,
678
+ & [ "FileId(1) [96; 98) StructLiteral " , "FileId(1) [114; 116) StructLiteral " ] ,
595
679
) ;
596
680
}
597
681
0 commit comments