1
1
use std:: {
2
2
fmt:: { self , Write } ,
3
+ hash:: { BuildHasher , BuildHasherDefault } ,
3
4
mem:: take,
4
5
} ;
5
6
@@ -8,7 +9,7 @@ use hir::{
8
9
known, ClosureStyle , HasVisibility , HirDisplay , HirDisplayError , HirWrite , ModuleDef ,
9
10
ModuleDefId , Semantics ,
10
11
} ;
11
- use ide_db:: { base_db:: FileRange , famous_defs:: FamousDefs , RootDatabase } ;
12
+ use ide_db:: { base_db:: FileRange , famous_defs:: FamousDefs , FxHasher , RootDatabase } ;
12
13
use itertools:: Itertools ;
13
14
use smallvec:: { smallvec, SmallVec } ;
14
15
use stdx:: never;
@@ -116,7 +117,7 @@ pub enum AdjustmentHintsMode {
116
117
PreferPostfix ,
117
118
}
118
119
119
- #[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
120
+ #[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
120
121
pub enum InlayKind {
121
122
Adjustment ,
122
123
BindingMode ,
@@ -132,7 +133,7 @@ pub enum InlayKind {
132
133
RangeExclusive ,
133
134
}
134
135
135
- #[ derive( Debug ) ]
136
+ #[ derive( Debug , Hash ) ]
136
137
pub enum InlayHintPosition {
137
138
Before ,
138
139
After ,
@@ -153,6 +154,18 @@ pub struct InlayHint {
153
154
pub text_edit : Option < TextEdit > ,
154
155
}
155
156
157
+ impl std:: hash:: Hash for InlayHint {
158
+ fn hash < H : std:: hash:: Hasher > ( & self , state : & mut H ) {
159
+ self . range . hash ( state) ;
160
+ self . position . hash ( state) ;
161
+ self . pad_left . hash ( state) ;
162
+ self . pad_right . hash ( state) ;
163
+ self . kind . hash ( state) ;
164
+ self . label . hash ( state) ;
165
+ self . text_edit . is_some ( ) . hash ( state) ;
166
+ }
167
+ }
168
+
156
169
impl InlayHint {
157
170
fn closing_paren_after ( kind : InlayKind , range : TextRange ) -> InlayHint {
158
171
InlayHint {
@@ -183,13 +196,13 @@ impl InlayHint {
183
196
}
184
197
}
185
198
186
- #[ derive( Debug ) ]
199
+ #[ derive( Debug , Hash ) ]
187
200
pub enum InlayTooltip {
188
201
String ( String ) ,
189
202
Markdown ( String ) ,
190
203
}
191
204
192
- #[ derive( Default ) ]
205
+ #[ derive( Default , Hash ) ]
193
206
pub struct InlayHintLabel {
194
207
pub parts : SmallVec < [ InlayHintLabelPart ; 1 ] > ,
195
208
}
@@ -267,6 +280,7 @@ impl fmt::Debug for InlayHintLabel {
267
280
}
268
281
}
269
282
283
+ #[ derive( Hash ) ]
270
284
pub struct InlayHintLabelPart {
271
285
pub text : String ,
272
286
/// Source location represented by this label part. The client will use this to fetch the part's
@@ -315,9 +329,7 @@ impl fmt::Write for InlayHintLabelBuilder<'_> {
315
329
316
330
impl HirWrite for InlayHintLabelBuilder < ' _ > {
317
331
fn start_location_link ( & mut self , def : ModuleDefId ) {
318
- if self . location . is_some ( ) {
319
- never ! ( "location link is already started" ) ;
320
- }
332
+ never ! ( self . location. is_some( ) , "location link is already started" ) ;
321
333
self . make_new_part ( ) ;
322
334
let Some ( location) = ModuleDef :: from ( def) . try_to_nav ( self . db ) else { return } ;
323
335
let location = location. call_site ( ) ;
@@ -427,11 +439,6 @@ fn ty_to_text_edit(
427
439
Some ( builder. finish ( ) )
428
440
}
429
441
430
- pub enum RangeLimit {
431
- Fixed ( TextRange ) ,
432
- NearestParent ( TextSize ) ,
433
- }
434
-
435
442
// Feature: Inlay Hints
436
443
//
437
444
// rust-analyzer shows additional information inline with the source code.
@@ -453,7 +460,7 @@ pub enum RangeLimit {
453
460
pub ( crate ) fn inlay_hints (
454
461
db : & RootDatabase ,
455
462
file_id : FileId ,
456
- range_limit : Option < RangeLimit > ,
463
+ range_limit : Option < TextRange > ,
457
464
config : & InlayHintsConfig ,
458
465
) -> Vec < InlayHint > {
459
466
let _p = tracing:: span!( tracing:: Level :: INFO , "inlay_hints" ) . entered ( ) ;
@@ -468,38 +475,53 @@ pub(crate) fn inlay_hints(
468
475
469
476
let hints = |node| hints ( & mut acc, & famous_defs, config, file_id, node) ;
470
477
match range_limit {
471
- Some ( RangeLimit :: Fixed ( range) ) => match file. covering_element ( range) {
478
+ Some ( range) => match file. covering_element ( range) {
472
479
NodeOrToken :: Token ( _) => return acc,
473
480
NodeOrToken :: Node ( n) => n
474
481
. descendants ( )
475
482
. filter ( |descendant| range. intersect ( descendant. text_range ( ) ) . is_some ( ) )
476
483
. for_each ( hints) ,
477
484
} ,
478
- Some ( RangeLimit :: NearestParent ( position) ) => {
479
- match file. token_at_offset ( position) . left_biased ( ) {
480
- Some ( token) => {
481
- if let Some ( parent_block) =
482
- token. parent_ancestors ( ) . find_map ( ast:: BlockExpr :: cast)
483
- {
484
- parent_block. syntax ( ) . descendants ( ) . for_each ( hints)
485
- } else if let Some ( parent_item) =
486
- token. parent_ancestors ( ) . find_map ( ast:: Item :: cast)
487
- {
488
- parent_item. syntax ( ) . descendants ( ) . for_each ( hints)
489
- } else {
490
- return acc;
491
- }
492
- }
493
- None => return acc,
494
- }
495
- }
496
485
None => file. descendants ( ) . for_each ( hints) ,
497
486
} ;
498
487
}
499
488
500
489
acc
501
490
}
502
491
492
+ pub ( crate ) fn inlay_hints_resolve (
493
+ db : & RootDatabase ,
494
+ file_id : FileId ,
495
+ position : TextSize ,
496
+ hash : u64 ,
497
+ config : & InlayHintsConfig ,
498
+ ) -> Option < InlayHint > {
499
+ let _p = tracing:: span!( tracing:: Level :: INFO , "inlay_hints" ) . entered ( ) ;
500
+ let sema = Semantics :: new ( db) ;
501
+ let file = sema. parse ( file_id) ;
502
+ let file = file. syntax ( ) ;
503
+
504
+ let scope = sema. scope ( file) ?;
505
+ let famous_defs = FamousDefs ( & sema, scope. krate ( ) ) ;
506
+ let mut acc = Vec :: new ( ) ;
507
+
508
+ let hints = |node| hints ( & mut acc, & famous_defs, config, file_id, node) ;
509
+ match file. token_at_offset ( position) . left_biased ( ) {
510
+ Some ( token) => {
511
+ if let Some ( parent_block) = token. parent_ancestors ( ) . find_map ( ast:: BlockExpr :: cast) {
512
+ parent_block. syntax ( ) . descendants ( ) . for_each ( hints)
513
+ } else if let Some ( parent_item) = token. parent_ancestors ( ) . find_map ( ast:: Item :: cast) {
514
+ parent_item. syntax ( ) . descendants ( ) . for_each ( hints)
515
+ } else {
516
+ return None ;
517
+ }
518
+ }
519
+ None => return None ,
520
+ }
521
+
522
+ acc. into_iter ( ) . find ( |hint| BuildHasherDefault :: < FxHasher > :: default ( ) . hash_one ( hint) == hash)
523
+ }
524
+
503
525
fn hints (
504
526
hints : & mut Vec < InlayHint > ,
505
527
famous_defs @ FamousDefs ( sema, _) : & FamousDefs < ' _ , ' _ > ,
0 commit comments