11use std:: {
22 fmt:: { self , Write } ,
3+ hash:: { BuildHasher , BuildHasherDefault } ,
34 mem:: take,
45} ;
56
@@ -8,7 +9,7 @@ use hir::{
89 known, ClosureStyle , HasVisibility , HirDisplay , HirDisplayError , HirWrite , ModuleDef ,
910 ModuleDefId , Semantics ,
1011} ;
11- use ide_db:: { base_db:: FileRange , famous_defs:: FamousDefs , RootDatabase } ;
12+ use ide_db:: { base_db:: FileRange , famous_defs:: FamousDefs , FxHasher , RootDatabase } ;
1213use itertools:: Itertools ;
1314use smallvec:: { smallvec, SmallVec } ;
1415use stdx:: never;
@@ -116,7 +117,7 @@ pub enum AdjustmentHintsMode {
116117 PreferPostfix ,
117118}
118119
119- #[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
120+ #[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
120121pub enum InlayKind {
121122 Adjustment ,
122123 BindingMode ,
@@ -132,7 +133,7 @@ pub enum InlayKind {
132133 RangeExclusive ,
133134}
134135
135- #[ derive( Debug ) ]
136+ #[ derive( Debug , Hash ) ]
136137pub enum InlayHintPosition {
137138 Before ,
138139 After ,
@@ -153,6 +154,18 @@ pub struct InlayHint {
153154 pub text_edit : Option < TextEdit > ,
154155}
155156
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+
156169impl InlayHint {
157170 fn closing_paren_after ( kind : InlayKind , range : TextRange ) -> InlayHint {
158171 InlayHint {
@@ -183,13 +196,13 @@ impl InlayHint {
183196 }
184197}
185198
186- #[ derive( Debug ) ]
199+ #[ derive( Debug , Hash ) ]
187200pub enum InlayTooltip {
188201 String ( String ) ,
189202 Markdown ( String ) ,
190203}
191204
192- #[ derive( Default ) ]
205+ #[ derive( Default , Hash ) ]
193206pub struct InlayHintLabel {
194207 pub parts : SmallVec < [ InlayHintLabelPart ; 1 ] > ,
195208}
@@ -267,6 +280,7 @@ impl fmt::Debug for InlayHintLabel {
267280 }
268281}
269282
283+ #[ derive( Hash ) ]
270284pub struct InlayHintLabelPart {
271285 pub text : String ,
272286 /// 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<'_> {
315329
316330impl HirWrite for InlayHintLabelBuilder < ' _ > {
317331 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" ) ;
321333 self . make_new_part ( ) ;
322334 let Some ( location) = ModuleDef :: from ( def) . try_to_nav ( self . db ) else { return } ;
323335 let location = location. call_site ( ) ;
@@ -427,11 +439,6 @@ fn ty_to_text_edit(
427439 Some ( builder. finish ( ) )
428440}
429441
430- pub enum RangeLimit {
431- Fixed ( TextRange ) ,
432- NearestParent ( TextSize ) ,
433- }
434-
435442// Feature: Inlay Hints
436443//
437444// rust-analyzer shows additional information inline with the source code.
@@ -453,7 +460,7 @@ pub enum RangeLimit {
453460pub ( crate ) fn inlay_hints (
454461 db : & RootDatabase ,
455462 file_id : FileId ,
456- range_limit : Option < RangeLimit > ,
463+ range_limit : Option < TextRange > ,
457464 config : & InlayHintsConfig ,
458465) -> Vec < InlayHint > {
459466 let _p = tracing:: span!( tracing:: Level :: INFO , "inlay_hints" ) . entered ( ) ;
@@ -468,38 +475,53 @@ pub(crate) fn inlay_hints(
468475
469476 let hints = |node| hints ( & mut acc, & famous_defs, config, file_id, node) ;
470477 match range_limit {
471- Some ( RangeLimit :: Fixed ( range) ) => match file. covering_element ( range) {
478+ Some ( range) => match file. covering_element ( range) {
472479 NodeOrToken :: Token ( _) => return acc,
473480 NodeOrToken :: Node ( n) => n
474481 . descendants ( )
475482 . filter ( |descendant| range. intersect ( descendant. text_range ( ) ) . is_some ( ) )
476483 . for_each ( hints) ,
477484 } ,
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- }
496485 None => file. descendants ( ) . for_each ( hints) ,
497486 } ;
498487 }
499488
500489 acc
501490}
502491
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+
503525fn hints (
504526 hints : & mut Vec < InlayHint > ,
505527 famous_defs @ FamousDefs ( sema, _) : & FamousDefs < ' _ , ' _ > ,
0 commit comments