1
1
use either:: Either ;
2
- use hir:: { known, Callable , HasVisibility , HirDisplay , Semantics , TypeInfo } ;
2
+ use hir:: { known, Callable , HasVisibility , HirDisplay , Mutability , Semantics , TypeInfo } ;
3
3
use ide_db:: {
4
4
base_db:: FileRange , famous_defs:: FamousDefs , syntax_helpers:: node_ext:: walk_ty, FxHashMap ,
5
5
RootDatabase ,
@@ -21,6 +21,7 @@ pub struct InlayHintsConfig {
21
21
pub chaining_hints : bool ,
22
22
pub reborrow_hints : ReborrowHints ,
23
23
pub closure_return_type_hints : bool ,
24
+ pub binding_mode_hints : bool ,
24
25
pub lifetime_elision_hints : LifetimeElisionHints ,
25
26
pub param_names_for_lifetime_elision_hints : bool ,
26
27
pub hide_named_constructor_hints : bool ,
@@ -43,10 +44,11 @@ pub enum ReborrowHints {
43
44
44
45
#[ derive( Clone , Debug , PartialEq , Eq ) ]
45
46
pub enum InlayKind {
47
+ BindingModeHint ,
46
48
ChainingHint ,
47
49
ClosureReturnTypeHint ,
48
50
GenericParamListHint ,
49
- ImplicitReborrow ,
51
+ ImplicitReborrowHint ,
50
52
LifetimeHint ,
51
53
ParameterHint ,
52
54
TypeHint ,
@@ -135,8 +137,11 @@ fn hints(
135
137
ast:: Expr :: PathExpr ( _) => reborrow_hints ( hints, sema, config, & expr) ,
136
138
_ => None ,
137
139
} ;
138
- } else if let Some ( it) = ast:: IdentPat :: cast ( node. clone ( ) ) {
139
- bind_pat_hints ( hints, sema, config, & it) ;
140
+ } else if let Some ( it) = ast:: Pat :: cast ( node. clone ( ) ) {
141
+ binding_mode_hints ( hints, sema, config, & it) ;
142
+ if let ast:: Pat :: IdentPat ( it) = it {
143
+ bind_pat_hints ( hints, sema, config, & it) ;
144
+ }
140
145
} else if let Some ( it) = ast:: Fn :: cast ( node) {
141
146
lifetime_hints ( hints, config, it) ;
142
147
}
@@ -383,15 +388,17 @@ fn reborrow_hints(
383
388
return None ;
384
389
}
385
390
386
- let mutability = sema. is_implicit_reborrow ( expr) ?;
391
+ let descended = sema. descend_node_into_attributes ( expr. clone ( ) ) . pop ( ) ;
392
+ let desc_expr = descended. as_ref ( ) . unwrap_or ( expr) ;
393
+ let mutability = sema. is_implicit_reborrow ( desc_expr) ?;
387
394
let label = match mutability {
388
395
hir:: Mutability :: Shared if config. reborrow_hints != ReborrowHints :: MutableOnly => "&*" ,
389
396
hir:: Mutability :: Mut => "&mut *" ,
390
397
_ => return None ,
391
398
} ;
392
399
acc. push ( InlayHint {
393
400
range : expr. syntax ( ) . text_range ( ) ,
394
- kind : InlayKind :: ImplicitReborrow ,
401
+ kind : InlayKind :: ImplicitReborrowHint ,
395
402
label : SmolStr :: new_inline ( label) ,
396
403
} ) ;
397
404
Some ( ( ) )
@@ -497,6 +504,51 @@ fn param_name_hints(
497
504
Some ( ( ) )
498
505
}
499
506
507
+ fn binding_mode_hints (
508
+ acc : & mut Vec < InlayHint > ,
509
+ sema : & Semantics < RootDatabase > ,
510
+ config : & InlayHintsConfig ,
511
+ pat : & ast:: Pat ,
512
+ ) -> Option < ( ) > {
513
+ if !config. binding_mode_hints {
514
+ return None ;
515
+ }
516
+
517
+ let range = pat. syntax ( ) . text_range ( ) ;
518
+ sema. pattern_adjustments ( & pat) . iter ( ) . for_each ( |ty| {
519
+ let reference = ty. is_reference ( ) ;
520
+ let mut_reference = ty. is_mutable_reference ( ) ;
521
+ let r = match ( reference, mut_reference) {
522
+ ( true , true ) => "&mut" ,
523
+ ( true , false ) => "&" ,
524
+ _ => return ,
525
+ } ;
526
+ acc. push ( InlayHint {
527
+ range,
528
+ kind : InlayKind :: BindingModeHint ,
529
+ label : SmolStr :: new_inline ( r) ,
530
+ } ) ;
531
+ } ) ;
532
+ match pat {
533
+ ast:: Pat :: IdentPat ( pat) if pat. ref_token ( ) . is_none ( ) && pat. mut_token ( ) . is_none ( ) => {
534
+ let bm = sema. binding_mode_of_pat ( pat) ?;
535
+ let bm = match bm {
536
+ hir:: BindingMode :: Move => return None ,
537
+ hir:: BindingMode :: Ref ( Mutability :: Mut ) => "ref mut" ,
538
+ hir:: BindingMode :: Ref ( Mutability :: Shared ) => "ref" ,
539
+ } ;
540
+ acc. push ( InlayHint {
541
+ range,
542
+ kind : InlayKind :: BindingModeHint ,
543
+ label : SmolStr :: new_inline ( bm) ,
544
+ } ) ;
545
+ }
546
+ _ => ( ) ,
547
+ }
548
+
549
+ Some ( ( ) )
550
+ }
551
+
500
552
fn bind_pat_hints (
501
553
acc : & mut Vec < InlayHint > ,
502
554
sema : & Semantics < RootDatabase > ,
@@ -681,6 +733,7 @@ fn should_not_display_type_hint(
681
733
match_ast ! {
682
734
match node {
683
735
ast:: LetStmt ( it) => return it. ty( ) . is_some( ) ,
736
+ // FIXME: We might wanna show type hints in parameters for non-top level patterns as well
684
737
ast:: Param ( it) => return it. ty( ) . is_some( ) ,
685
738
ast:: MatchArm ( _) => return pat_is_enum_variant( db, bind_pat, pat_ty) ,
686
739
ast:: LetExpr ( _) => return pat_is_enum_variant( db, bind_pat, pat_ty) ,
@@ -866,9 +919,10 @@ mod tests {
866
919
parameter_hints : false ,
867
920
chaining_hints : false ,
868
921
lifetime_elision_hints : LifetimeElisionHints :: Never ,
869
- hide_named_constructor_hints : false ,
870
922
closure_return_type_hints : false ,
871
923
reborrow_hints : ReborrowHints :: Always ,
924
+ binding_mode_hints : false ,
925
+ hide_named_constructor_hints : false ,
872
926
param_names_for_lifetime_elision_hints : false ,
873
927
max_length : None ,
874
928
} ;
@@ -878,6 +932,7 @@ mod tests {
878
932
chaining_hints : true ,
879
933
reborrow_hints : ReborrowHints :: Always ,
880
934
closure_return_type_hints : true ,
935
+ binding_mode_hints : true ,
881
936
lifetime_elision_hints : LifetimeElisionHints :: Always ,
882
937
..DISABLED_CONFIG
883
938
} ;
@@ -2191,6 +2246,51 @@ fn ref_mut_id(mut_ref: &mut ()) -> &mut () {
2191
2246
fn ref_id(shared_ref: &()) -> &() {
2192
2247
shared_ref
2193
2248
}
2249
+ "# ,
2250
+ ) ;
2251
+ }
2252
+
2253
+ #[ test]
2254
+ fn hints_binding_modes ( ) {
2255
+ check_with_config (
2256
+ InlayHintsConfig { binding_mode_hints : true , ..DISABLED_CONFIG } ,
2257
+ r#"
2258
+ fn __(
2259
+ (x,): (u32,),
2260
+ (x,): &(u32,),
2261
+ //^^^^&
2262
+ //^ ref
2263
+ (x,): &mut (u32,)
2264
+ //^^^^&mut
2265
+ //^ ref mut
2266
+ ) {
2267
+ let (x,) = (0,);
2268
+ let (x,) = &(0,);
2269
+ //^^^^ &
2270
+ //^ ref
2271
+ let (x,) = &mut (0,);
2272
+ //^^^^ &mut
2273
+ //^ ref mut
2274
+ let &mut (x,) = &mut (0,);
2275
+ let (ref mut x,) = &mut (0,);
2276
+ //^^^^^^^^^^^^ &mut
2277
+ let &mut (ref mut x,) = &mut (0,);
2278
+ let (mut x,) = &mut (0,);
2279
+ //^^^^^^^^ &mut
2280
+ match (0,) {
2281
+ (x,) => ()
2282
+ }
2283
+ match &(0,) {
2284
+ (x,) => ()
2285
+ //^^^^ &
2286
+ //^ ref
2287
+ }
2288
+ match &mut (0,) {
2289
+ (x,) => ()
2290
+ //^^^^ &mut
2291
+ //^ ref mut
2292
+ }
2293
+ }
2194
2294
"# ,
2195
2295
) ;
2196
2296
}
0 commit comments