@@ -3,10 +3,10 @@ mod render;
33#[ cfg( test) ]
44mod tests;
55
6- use std:: iter;
6+ use std:: { iter, ops :: Not } ;
77
88use either:: Either ;
9- use hir:: { db:: DefDatabase , DescendPreference , HasSource , LangItem , Semantics } ;
9+ use hir:: { db:: DefDatabase , DescendPreference , HasCrate , HasSource , LangItem , Semantics } ;
1010use ide_db:: {
1111 base_db:: FileRange ,
1212 defs:: { Definition , IdentClass , NameRefClass , OperatorClass } ,
@@ -64,7 +64,7 @@ pub enum HoverAction {
6464}
6565
6666impl HoverAction {
67- fn goto_type_from_targets ( db : & RootDatabase , targets : Vec < hir:: ModuleDef > ) -> Self {
67+ fn goto_type_from_targets ( db : & RootDatabase , targets : Vec < hir:: ModuleDef > ) -> Option < Self > {
6868 let targets = targets
6969 . into_iter ( )
7070 . filter_map ( |it| {
@@ -77,8 +77,8 @@ impl HoverAction {
7777 nav : it. try_to_nav ( db) ?. call_site ( ) ,
7878 } )
7979 } )
80- . collect ( ) ;
81- HoverAction :: GoToType ( targets)
80+ . collect :: < Vec < _ > > ( ) ;
81+ targets . is_empty ( ) . not ( ) . then_some ( HoverAction :: GoToType ( targets) )
8282 }
8383}
8484
@@ -315,7 +315,7 @@ fn hover_simple(
315315 ast:: IntNumber ( num) => {
316316 res. markup = match num. value( ) {
317317 Ok ( num) => {
318- Markup :: fenced_block_text( format_args!( "{num} (0x{num:X}|0x {num:b})" ) )
318+ Markup :: fenced_block_text( format_args!( "{num} (0x{num:X}|0b {num:b})" ) )
319319 } ,
320320 Err ( e) => {
321321 Markup :: fenced_block_text( format_args!( "{e}" ) )
@@ -365,25 +365,44 @@ fn hover_ranged(
365365 } )
366366}
367367
368+ // FIXME: Why is this pub(crate)?
368369pub ( crate ) fn hover_for_definition (
369370 sema : & Semantics < ' _ , RootDatabase > ,
370371 file_id : FileId ,
371- definition : Definition ,
372+ def : Definition ,
372373 scope_node : & SyntaxNode ,
373374 config : & HoverConfig ,
374375) -> Option < HoverResult > {
375- let famous_defs = match & definition {
376+ let famous_defs = match & def {
376377 Definition :: BuiltinType ( _) => Some ( FamousDefs ( sema, sema. scope ( scope_node) ?. krate ( ) ) ) ,
377378 _ => None ,
378379 } ;
379- render:: definition ( sema. db , definition, famous_defs. as_ref ( ) , config) . map ( |markup| {
380+
381+ let db = sema. db ;
382+ let def_ty = match def {
383+ Definition :: Local ( it) => Some ( it. ty ( db) ) ,
384+ Definition :: GenericParam ( hir:: GenericParam :: ConstParam ( it) ) => Some ( it. ty ( db) ) ,
385+ Definition :: GenericParam ( hir:: GenericParam :: TypeParam ( it) ) => Some ( it. ty ( db) ) ,
386+ Definition :: Field ( field) => Some ( field. ty ( db) ) ,
387+ Definition :: TupleField ( it) => Some ( it. ty ( db) ) ,
388+ Definition :: Function ( it) => Some ( it. ty ( db) ) ,
389+ Definition :: Adt ( it) => Some ( it. ty ( db) ) ,
390+ Definition :: Const ( it) => Some ( it. ty ( db) ) ,
391+ Definition :: Static ( it) => Some ( it. ty ( db) ) ,
392+ Definition :: TypeAlias ( it) => Some ( it. ty ( db) ) ,
393+ Definition :: BuiltinType ( it) => Some ( it. ty ( db) ) ,
394+ _ => None ,
395+ } ;
396+ let notable_traits = def_ty. map ( |ty| notable_traits ( db, & ty) ) . unwrap_or_default ( ) ;
397+
398+ render:: definition ( sema. db , def, famous_defs. as_ref ( ) , & notable_traits, config) . map ( |markup| {
380399 HoverResult {
381- markup : render:: process_markup ( sema. db , definition , & markup, config) ,
400+ markup : render:: process_markup ( sema. db , def , & markup, config) ,
382401 actions : [
383- show_implementations_action ( sema. db , definition ) ,
384- show_fn_references_action ( sema. db , definition ) ,
385- runnable_action ( sema, definition , file_id) ,
386- goto_type_action_for_def ( sema. db , definition ) ,
402+ show_implementations_action ( sema. db , def ) ,
403+ show_fn_references_action ( sema. db , def ) ,
404+ runnable_action ( sema, def , file_id) ,
405+ goto_type_action_for_def ( sema. db , def , & notable_traits ) ,
387406 ]
388407 . into_iter ( )
389408 . flatten ( )
@@ -392,6 +411,32 @@ pub(crate) fn hover_for_definition(
392411 } )
393412}
394413
414+ fn notable_traits (
415+ db : & RootDatabase ,
416+ ty : & hir:: Type ,
417+ ) -> Vec < ( hir:: Trait , Vec < ( Option < hir:: Type > , hir:: Name ) > ) > {
418+ db. notable_traits_in_deps ( ty. krate ( db) . into ( ) )
419+ . iter ( )
420+ . flat_map ( |it| & * * it)
421+ . filter_map ( move |& trait_| {
422+ let trait_ = trait_. into ( ) ;
423+ ty. impls_trait ( db, trait_, & [ ] ) . then ( || {
424+ (
425+ trait_,
426+ trait_
427+ . items ( db)
428+ . into_iter ( )
429+ . filter_map ( hir:: AssocItem :: as_type_alias)
430+ . map ( |alias| {
431+ ( ty. normalize_trait_assoc_type ( db, & [ ] , alias) , alias. name ( db) )
432+ } )
433+ . collect :: < Vec < _ > > ( ) ,
434+ )
435+ } )
436+ } )
437+ . collect :: < Vec < _ > > ( )
438+ }
439+
395440fn show_implementations_action ( db : & RootDatabase , def : Definition ) -> Option < HoverAction > {
396441 fn to_action ( nav_target : NavigationTarget ) -> HoverAction {
397442 HoverAction :: Implementation ( FilePosition {
@@ -446,14 +491,25 @@ fn runnable_action(
446491 }
447492}
448493
449- fn goto_type_action_for_def ( db : & RootDatabase , def : Definition ) -> Option < HoverAction > {
494+ fn goto_type_action_for_def (
495+ db : & RootDatabase ,
496+ def : Definition ,
497+ notable_traits : & [ ( hir:: Trait , Vec < ( Option < hir:: Type > , hir:: Name ) > ) ] ,
498+ ) -> Option < HoverAction > {
450499 let mut targets: Vec < hir:: ModuleDef > = Vec :: new ( ) ;
451500 let mut push_new_def = |item : hir:: ModuleDef | {
452501 if !targets. contains ( & item) {
453502 targets. push ( item) ;
454503 }
455504 } ;
456505
506+ for & ( trait_, ref assocs) in notable_traits {
507+ push_new_def ( trait_. into ( ) ) ;
508+ assocs. iter ( ) . filter_map ( |( ty, _) | ty. as_ref ( ) ) . for_each ( |ty| {
509+ walk_and_push_ty ( db, ty, & mut push_new_def) ;
510+ } ) ;
511+ }
512+
457513 if let Definition :: GenericParam ( hir:: GenericParam :: TypeParam ( it) ) = def {
458514 let krate = it. module ( db) . krate ( ) ;
459515 let sized_trait =
@@ -469,13 +525,13 @@ fn goto_type_action_for_def(db: &RootDatabase, def: Definition) -> Option<HoverA
469525 Definition :: GenericParam ( hir:: GenericParam :: ConstParam ( it) ) => it. ty ( db) ,
470526 Definition :: Field ( field) => field. ty ( db) ,
471527 Definition :: Function ( function) => function. ret_type ( db) ,
472- _ => return None ,
528+ _ => return HoverAction :: goto_type_from_targets ( db , targets ) ,
473529 } ;
474530
475531 walk_and_push_ty ( db, & ty, & mut push_new_def) ;
476532 }
477533
478- Some ( HoverAction :: goto_type_from_targets ( db, targets) )
534+ HoverAction :: goto_type_from_targets ( db, targets)
479535}
480536
481537fn walk_and_push_ty (
@@ -530,7 +586,9 @@ fn dedupe_or_merge_hover_actions(actions: Vec<HoverAction>) -> Vec<HoverAction>
530586 }
531587
532588 if !go_to_type_targets. is_empty ( ) {
533- deduped_actions. push ( HoverAction :: GoToType ( go_to_type_targets. into_iter ( ) . collect ( ) ) ) ;
589+ deduped_actions. push ( HoverAction :: GoToType (
590+ go_to_type_targets. into_iter ( ) . sorted_by ( |a, b| a. mod_path . cmp ( & b. mod_path ) ) . collect ( ) ,
591+ ) ) ;
534592 }
535593
536594 deduped_actions
0 commit comments