@@ -112,25 +112,20 @@ impl IntoIterator for ReferenceSearchResult {
112112
113113pub ( crate ) fn find_all_refs (
114114 db : & RootDatabase ,
115- mut position : FilePosition ,
115+ position : FilePosition ,
116116 search_scope : Option < SearchScope > ,
117117) -> Option < RangeInfo < ReferenceSearchResult > > {
118118 let parse = db. parse ( position. file_id ) ;
119119 let syntax = parse. tree ( ) . syntax ( ) . clone ( ) ;
120120
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+ } ;
123127
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) ?;
134129
135130 let declaration = match def. kind {
136131 NameKind :: Macro ( mac) => mac. to_nav ( db) ,
@@ -170,9 +165,10 @@ fn find_name(
170165 db : & RootDatabase ,
171166 syntax : & SyntaxNode ,
172167 position : FilePosition ,
168+ opt_name : Option < ast:: Name > ,
173169) -> Option < RangeInfo < ( String , NameDefinition ) > > {
174170 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 {
176172 let def = classify_name ( & mut sb, InFile :: new ( position. file_id . into ( ) , & name) ) ?;
177173 let range = name. syntax ( ) . text_range ( ) ;
178174 return Some ( RangeInfo :: new ( range, ( name. text ( ) . to_string ( ) , def) ) ) ;
@@ -218,15 +214,8 @@ fn process_definition(
218214 if let Some ( d) = classify_name_ref ( & mut sb, InFile :: new ( file_id. into ( ) , & name_ref) )
219215 {
220216 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)
230219 {
231220 ReferenceKind :: StructLiteral
232221 } else {
@@ -301,6 +290,49 @@ fn reference_access(kind: &NameKind, name_ref: &ast::NameRef) -> Option<Referenc
301290 mode. or ( Some ( ReferenceAccess :: Read ) )
302291}
303292
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+
304336#[ cfg( test) ]
305337mod tests {
306338 use crate :: {
@@ -309,7 +341,7 @@ mod tests {
309341 } ;
310342
311343 #[ test]
312- fn test_struct_literal ( ) {
344+ fn test_struct_literal_after_space ( ) {
313345 let code = r#"
314346 struct Foo <|>{
315347 a: i32,
@@ -330,6 +362,58 @@ mod tests {
330362 ) ;
331363 }
332364
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+
333417 #[ test]
334418 fn test_find_all_refs_for_local ( ) {
335419 let code = r#"
@@ -564,15 +648,15 @@ mod tests {
564648 check_result (
565649 refs,
566650 "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 " ] ,
568652 ) ;
569653
570654 let refs =
571655 analysis. find_all_refs ( pos, Some ( SearchScope :: single_file ( bar) ) ) . unwrap ( ) . unwrap ( ) ;
572656 check_result (
573657 refs,
574658 "quux FN_DEF FileId(1) [18; 34) [25; 29) Other" ,
575- & [ "FileId(3) [16; 20) Other " ] ,
659+ & [ "FileId(3) [16; 20) StructLiteral " ] ,
576660 ) ;
577661 }
578662
@@ -591,7 +675,7 @@ mod tests {
591675 check_result (
592676 refs,
593677 "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 " ] ,
595679 ) ;
596680 }
597681
0 commit comments