@@ -301,103 +301,108 @@ impl<'a> CompletionContext<'a> {
301
301
. find_map ( ast:: Impl :: cast) ;
302
302
}
303
303
304
+ fn expected_type_and_name ( & self ) -> ( Option < Type > , Option < NameOrNameRef > ) {
305
+ let mut node = match self . token . parent ( ) {
306
+ Some ( it) => it,
307
+ None => return ( None , None ) ,
308
+ } ;
309
+ loop {
310
+ break match_ast ! {
311
+ match node {
312
+ ast:: LetStmt ( it) => {
313
+ cov_mark:: hit!( expected_type_let_with_leading_char) ;
314
+ cov_mark:: hit!( expected_type_let_without_leading_char) ;
315
+ let ty = it. pat( )
316
+ . and_then( |pat| self . sema. type_of_pat( & pat) ) ;
317
+ let name = if let Some ( ast:: Pat :: IdentPat ( ident) ) = it. pat( ) {
318
+ ident. name( ) . map( NameOrNameRef :: Name )
319
+ } else {
320
+ None
321
+ } ;
322
+
323
+ ( ty, name)
324
+ } ,
325
+ ast:: ArgList ( _it) => {
326
+ cov_mark:: hit!( expected_type_fn_param_with_leading_char) ;
327
+ cov_mark:: hit!( expected_type_fn_param_without_leading_char) ;
328
+ ActiveParameter :: at_token(
329
+ & self . sema,
330
+ self . token. clone( ) ,
331
+ ) . map( |ap| {
332
+ let name = ap. ident( ) . map( NameOrNameRef :: Name ) ;
333
+ ( Some ( ap. ty) , name)
334
+ } )
335
+ . unwrap_or( ( None , None ) )
336
+ } ,
337
+ ast:: RecordExprFieldList ( _it) => {
338
+ cov_mark:: hit!( expected_type_struct_field_without_leading_char) ;
339
+ self . token. prev_sibling_or_token( )
340
+ . and_then( |se| se. into_node( ) )
341
+ . and_then( |node| ast:: RecordExprField :: cast( node) )
342
+ . and_then( |rf| self . sema. resolve_record_field( & rf) . zip( Some ( rf) ) )
343
+ . map( |( f, rf) |(
344
+ Some ( f. 0 . ty( self . db) ) ,
345
+ rf. field_name( ) . map( NameOrNameRef :: NameRef ) ,
346
+ ) )
347
+ . unwrap_or( ( None , None ) )
348
+ } ,
349
+ ast:: RecordExprField ( it) => {
350
+ cov_mark:: hit!( expected_type_struct_field_with_leading_char) ;
351
+ self . sema
352
+ . resolve_record_field( & it)
353
+ . map( |f|(
354
+ Some ( f. 0 . ty( self . db) ) ,
355
+ it. field_name( ) . map( NameOrNameRef :: NameRef ) ,
356
+ ) )
357
+ . unwrap_or( ( None , None ) )
358
+ } ,
359
+ ast:: MatchExpr ( it) => {
360
+ cov_mark:: hit!( expected_type_match_arm_without_leading_char) ;
361
+ let ty = it. expr( )
362
+ . and_then( |e| self . sema. type_of_expr( & e) ) ;
363
+ ( ty, None )
364
+ } ,
365
+ ast:: IfExpr ( it) => {
366
+ cov_mark:: hit!( expected_type_if_let_without_leading_char) ;
367
+ let ty = it. condition( )
368
+ . and_then( |cond| cond. expr( ) )
369
+ . and_then( |e| self . sema. type_of_expr( & e) ) ;
370
+ ( ty, None )
371
+ } ,
372
+ ast:: IdentPat ( it) => {
373
+ cov_mark:: hit!( expected_type_if_let_with_leading_char) ;
374
+ cov_mark:: hit!( expected_type_match_arm_with_leading_char) ;
375
+ let ty = self . sema. type_of_pat( & ast:: Pat :: from( it) ) ;
376
+ ( ty, None )
377
+ } ,
378
+ ast:: Fn ( it) => {
379
+ cov_mark:: hit!( expected_type_fn_ret_with_leading_char) ;
380
+ cov_mark:: hit!( expected_type_fn_ret_without_leading_char) ;
381
+ let def = self . sema. to_def( & it) ;
382
+ ( def. map( |def| def. ret_type( self . db) ) , None )
383
+ } ,
384
+ ast:: Stmt ( it) => ( None , None ) ,
385
+ _ => {
386
+ match node. parent( ) {
387
+ Some ( n) => {
388
+ node = n;
389
+ continue ;
390
+ } ,
391
+ None => ( None , None ) ,
392
+ }
393
+ } ,
394
+ }
395
+ } ;
396
+ }
397
+ }
398
+
304
399
fn fill (
305
400
& mut self ,
306
401
original_file : & SyntaxNode ,
307
402
file_with_fake_ident : SyntaxNode ,
308
403
offset : TextSize ,
309
404
) {
310
- let ( expected_type, expected_name) = {
311
- let mut node = match self . token . parent ( ) {
312
- Some ( it) => it,
313
- None => return ,
314
- } ;
315
- loop {
316
- break match_ast ! {
317
- match node {
318
- ast:: LetStmt ( it) => {
319
- cov_mark:: hit!( expected_type_let_with_leading_char) ;
320
- cov_mark:: hit!( expected_type_let_without_leading_char) ;
321
- let ty = it. pat( )
322
- . and_then( |pat| self . sema. type_of_pat( & pat) ) ;
323
- let name = if let Some ( ast:: Pat :: IdentPat ( ident) ) = it. pat( ) {
324
- ident. name( ) . map( NameOrNameRef :: Name )
325
- } else {
326
- None
327
- } ;
328
-
329
- ( ty, name)
330
- } ,
331
- ast:: ArgList ( _it) => {
332
- cov_mark:: hit!( expected_type_fn_param_with_leading_char) ;
333
- cov_mark:: hit!( expected_type_fn_param_without_leading_char) ;
334
- ActiveParameter :: at_token(
335
- & self . sema,
336
- self . token. clone( ) ,
337
- ) . map( |ap| {
338
- let name = ap. ident( ) . map( NameOrNameRef :: Name ) ;
339
- ( Some ( ap. ty) , name)
340
- } )
341
- . unwrap_or( ( None , None ) )
342
- } ,
343
- ast:: RecordExprFieldList ( _it) => {
344
- cov_mark:: hit!( expected_type_struct_field_without_leading_char) ;
345
- self . token. prev_sibling_or_token( )
346
- . and_then( |se| se. into_node( ) )
347
- . and_then( |node| ast:: RecordExprField :: cast( node) )
348
- . and_then( |rf| self . sema. resolve_record_field( & rf) . zip( Some ( rf) ) )
349
- . map( |( f, rf) |(
350
- Some ( f. 0 . ty( self . db) ) ,
351
- rf. field_name( ) . map( NameOrNameRef :: NameRef ) ,
352
- ) )
353
- . unwrap_or( ( None , None ) )
354
- } ,
355
- ast:: RecordExprField ( it) => {
356
- cov_mark:: hit!( expected_type_struct_field_with_leading_char) ;
357
- self . sema
358
- . resolve_record_field( & it)
359
- . map( |f|(
360
- Some ( f. 0 . ty( self . db) ) ,
361
- it. field_name( ) . map( NameOrNameRef :: NameRef ) ,
362
- ) )
363
- . unwrap_or( ( None , None ) )
364
- } ,
365
- ast:: MatchExpr ( it) => {
366
- cov_mark:: hit!( expected_type_match_arm_without_leading_char) ;
367
- let ty = it. expr( )
368
- . and_then( |e| self . sema. type_of_expr( & e) ) ;
369
-
370
- ( ty, None )
371
- } ,
372
- ast:: IdentPat ( it) => {
373
- cov_mark:: hit!( expected_type_if_let_with_leading_char) ;
374
- cov_mark:: hit!( expected_type_match_arm_with_leading_char) ;
375
- let ty = self . sema. type_of_pat( & ast:: Pat :: from( it) ) ;
376
-
377
- ( ty, None )
378
- } ,
379
- ast:: Fn ( _it) => {
380
- cov_mark:: hit!( expected_type_fn_ret_with_leading_char) ;
381
- cov_mark:: hit!( expected_type_fn_ret_without_leading_char) ;
382
- let ty = self . token. ancestors( )
383
- . find_map( |ancestor| ast:: Expr :: cast( ancestor) )
384
- . and_then( |expr| self . sema. type_of_expr( & expr) ) ;
385
-
386
- ( ty, None )
387
- } ,
388
- _ => {
389
- match node. parent( ) {
390
- Some ( n) => {
391
- node = n;
392
- continue ;
393
- } ,
394
- None => ( None , None ) ,
395
- }
396
- } ,
397
- }
398
- } ;
399
- }
400
- } ;
405
+ let ( expected_type, expected_name) = self . expected_type_and_name ( ) ;
401
406
self . expected_type = expected_type;
402
407
self . expected_name = expected_name;
403
408
self . attribute_under_caret = find_node_at_offset ( & file_with_fake_ident, offset) ;
@@ -802,6 +807,7 @@ fn foo() {
802
807
803
808
#[ test]
804
809
fn expected_type_if_let_without_leading_char ( ) {
810
+ cov_mark:: check!( expected_type_if_let_without_leading_char) ;
805
811
check_expected_type_and_name (
806
812
r#"
807
813
enum Foo { Bar, Baz, Quux }
@@ -811,8 +817,8 @@ fn foo() {
811
817
if let $0 = f { }
812
818
}
813
819
"# ,
814
- expect ! [ [ r#"ty: () , name: ?"# ] ] ,
815
- ) // FIXME should be `ty: u32, name: ?`
820
+ expect ! [ [ r#"ty: Foo , name: ?"# ] ] ,
821
+ )
816
822
}
817
823
818
824
#[ test]
@@ -840,8 +846,8 @@ fn foo() -> u32 {
840
846
$0
841
847
}
842
848
"# ,
843
- expect ! [ [ r#"ty: () , name: ?"# ] ] ,
844
- ) // FIXME this should be `ty: u32, name: ?`
849
+ expect ! [ [ r#"ty: u32 , name: ?"# ] ] ,
850
+ )
845
851
}
846
852
847
853
#[ test]
@@ -852,6 +858,18 @@ fn foo() -> u32 {
852
858
fn foo() -> u32 {
853
859
c$0
854
860
}
861
+ "# ,
862
+ expect ! [ [ r#"ty: u32, name: ?"# ] ] ,
863
+ )
864
+ }
865
+
866
+ #[ test]
867
+ fn expected_type_fn_ret_fn_ref_fully_typed ( ) {
868
+ check_expected_type_and_name (
869
+ r#"
870
+ fn foo() -> u32 {
871
+ foo$0
872
+ }
855
873
"# ,
856
874
expect ! [ [ r#"ty: u32, name: ?"# ] ] ,
857
875
)
0 commit comments