11//! FIXME: write short doc here
22
3- use hir:: { Adt , HasSource , HirDisplay , Semantics } ;
3+ use hir:: {
4+ Adt , AsAssocItem , AssocItemContainer , HasSource , HirDisplay , ModuleDef , ModuleSource , Semantics ,
5+ } ;
46use ra_ide_db:: {
57 defs:: { classify_name, classify_name_ref, Definition } ,
68 RootDatabase ,
@@ -16,6 +18,8 @@ use crate::{
1618 display:: { macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel } ,
1719 FilePosition , RangeInfo ,
1820} ;
21+ use itertools:: Itertools ;
22+ use std:: iter:: once;
1923
2024/// Contains the results when hovering over an item
2125#[ derive( Debug , Clone ) ]
@@ -83,44 +87,86 @@ impl HoverResult {
8387 }
8488}
8589
86- fn hover_text ( docs : Option < String > , desc : Option < String > ) -> Option < String > {
87- match ( desc, docs) {
88- ( Some ( desc) , docs) => Some ( rust_code_markup_with_doc ( desc, docs) ) ,
89- ( None , Some ( docs) ) => Some ( docs) ,
90+ fn hover_text (
91+ docs : Option < String > ,
92+ desc : Option < String > ,
93+ mod_path : Option < String > ,
94+ ) -> Option < String > {
95+ match ( desc, docs, mod_path) {
96+ ( Some ( desc) , docs, mod_path) => Some ( rust_code_markup_with_doc ( desc, docs, mod_path) ) ,
97+ ( None , Some ( docs) , _) => Some ( docs) ,
9098 _ => None ,
9199 }
92100}
93101
102+ fn definition_owner_name ( db : & RootDatabase , def : & Definition ) -> Option < String > {
103+ match def {
104+ Definition :: StructField ( f) => Some ( f. parent_def ( db) . name ( db) ) ,
105+ Definition :: Local ( l) => l. parent ( db) . name ( db) ,
106+ Definition :: ModuleDef ( md) => match md {
107+ ModuleDef :: Function ( f) => match f. as_assoc_item ( db) ?. container ( db) {
108+ AssocItemContainer :: Trait ( t) => Some ( t. name ( db) ) ,
109+ AssocItemContainer :: ImplDef ( i) => i. target_ty ( db) . as_adt ( ) . map ( |adt| adt. name ( db) ) ,
110+ } ,
111+ ModuleDef :: EnumVariant ( e) => Some ( e. parent_enum ( db) . name ( db) ) ,
112+ _ => None ,
113+ } ,
114+ Definition :: SelfType ( i) => i. target_ty ( db) . as_adt ( ) . map ( |adt| adt. name ( db) ) ,
115+ _ => None ,
116+ }
117+ . map ( |name| name. to_string ( ) )
118+ }
119+
120+ fn determine_mod_path ( db : & RootDatabase , def : & Definition ) -> Option < String > {
121+ let mod_path = def. module ( db) . map ( |module| {
122+ once ( db. get_crate_original_name ( & module. krate ( ) . into ( ) ) )
123+ . chain (
124+ module
125+ . path_to_root ( db)
126+ . into_iter ( )
127+ . rev ( )
128+ . map ( |it| it. name ( db) . map ( |name| name. to_string ( ) ) ) ,
129+ )
130+ . chain ( once ( definition_owner_name ( db, def) ) )
131+ . filter_map ( std:: convert:: identity)
132+ . join ( "::" )
133+ } ) ;
134+ mod_path
135+ }
136+
94137fn hover_text_from_name_kind ( db : & RootDatabase , def : Definition ) -> Option < String > {
138+ let mod_path = determine_mod_path ( db, & def) ;
95139 return match def {
96140 Definition :: Macro ( it) => {
97141 let src = it. source ( db) ;
98- hover_text ( src. value . doc_comment_text ( ) , Some ( macro_label ( & src. value ) ) )
142+ hover_text ( src. value . doc_comment_text ( ) , Some ( macro_label ( & src. value ) ) , mod_path )
99143 }
100144 Definition :: StructField ( it) => {
101145 let src = it. source ( db) ;
102146 match src. value {
103- hir:: FieldSource :: Named ( it) => hover_text ( it. doc_comment_text ( ) , it. short_label ( ) ) ,
147+ hir:: FieldSource :: Named ( it) => {
148+ hover_text ( it. doc_comment_text ( ) , it. short_label ( ) , mod_path)
149+ }
104150 _ => None ,
105151 }
106152 }
107153 Definition :: ModuleDef ( it) => match it {
108- hir :: ModuleDef :: Module ( it) => match it. definition_source ( db) . value {
109- hir :: ModuleSource :: Module ( it) => {
110- hover_text ( it. doc_comment_text ( ) , it. short_label ( ) )
154+ ModuleDef :: Module ( it) => match it. definition_source ( db) . value {
155+ ModuleSource :: Module ( it) => {
156+ hover_text ( it. doc_comment_text ( ) , it. short_label ( ) , mod_path )
111157 }
112158 _ => None ,
113159 } ,
114- hir :: ModuleDef :: Function ( it) => from_def_source ( db, it) ,
115- hir :: ModuleDef :: Adt ( Adt :: Struct ( it) ) => from_def_source ( db, it) ,
116- hir :: ModuleDef :: Adt ( Adt :: Union ( it) ) => from_def_source ( db, it) ,
117- hir :: ModuleDef :: Adt ( Adt :: Enum ( it) ) => from_def_source ( db, it) ,
118- hir :: ModuleDef :: EnumVariant ( it) => from_def_source ( db, it) ,
119- hir :: ModuleDef :: Const ( it) => from_def_source ( db, it) ,
120- hir :: ModuleDef :: Static ( it) => from_def_source ( db, it) ,
121- hir :: ModuleDef :: Trait ( it) => from_def_source ( db, it) ,
122- hir :: ModuleDef :: TypeAlias ( it) => from_def_source ( db, it) ,
123- hir :: ModuleDef :: BuiltinType ( it) => Some ( it. to_string ( ) ) ,
160+ ModuleDef :: Function ( it) => from_def_source ( db, it, mod_path ) ,
161+ ModuleDef :: Adt ( Adt :: Struct ( it) ) => from_def_source ( db, it, mod_path ) ,
162+ ModuleDef :: Adt ( Adt :: Union ( it) ) => from_def_source ( db, it, mod_path ) ,
163+ ModuleDef :: Adt ( Adt :: Enum ( it) ) => from_def_source ( db, it, mod_path ) ,
164+ ModuleDef :: EnumVariant ( it) => from_def_source ( db, it, mod_path ) ,
165+ ModuleDef :: Const ( it) => from_def_source ( db, it, mod_path ) ,
166+ ModuleDef :: Static ( it) => from_def_source ( db, it, mod_path ) ,
167+ ModuleDef :: Trait ( it) => from_def_source ( db, it, mod_path ) ,
168+ ModuleDef :: TypeAlias ( it) => from_def_source ( db, it, mod_path ) ,
169+ ModuleDef :: BuiltinType ( it) => Some ( it. to_string ( ) ) ,
124170 } ,
125171 Definition :: Local ( it) => {
126172 Some ( rust_code_markup ( it. ty ( db) . display_truncated ( db, None ) . to_string ( ) ) )
@@ -131,13 +177,13 @@ fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<Strin
131177 }
132178 } ;
133179
134- fn from_def_source < A , D > ( db : & RootDatabase , def : D ) -> Option < String >
180+ fn from_def_source < A , D > ( db : & RootDatabase , def : D , mod_path : Option < String > ) -> Option < String >
135181 where
136182 D : HasSource < Ast = A > ,
137183 A : ast:: DocCommentsOwner + ast:: NameOwner + ShortLabel ,
138184 {
139185 let src = def. source ( db) ;
140- hover_text ( src. value . doc_comment_text ( ) , src. value . short_label ( ) )
186+ hover_text ( src. value . doc_comment_text ( ) , src. value . short_label ( ) , mod_path )
141187 }
142188}
143189
@@ -345,7 +391,7 @@ mod tests {
345391 };
346392 }
347393 "# ,
348- & [ "field_a : u32" ] ,
394+ & [ "Foo \n field_a : u32" ] ,
349395 ) ;
350396
351397 // Hovering over the field in the definition
@@ -362,7 +408,7 @@ mod tests {
362408 };
363409 }
364410 "# ,
365- & [ "field_a : u32" ] ,
411+ & [ "Foo \n field_a : u32" ] ,
366412 ) ;
367413 }
368414
@@ -415,7 +461,7 @@ fn main() {
415461 " ,
416462 ) ;
417463 let hover = analysis. hover ( position) . unwrap ( ) . unwrap ( ) ;
418- assert_eq ! ( trim_markup_opt( hover. info. first( ) ) , Some ( "Some " ) ) ;
464+ assert_eq ! ( trim_markup_opt( hover. info. first( ) ) , Some ( "Option \n Some " ) ) ;
419465
420466 let ( analysis, position) = single_file_with_position (
421467 "
@@ -442,6 +488,7 @@ fn main() {
442488 }
443489 "# ,
444490 & [ "
491+ Option
445492None
446493```
447494
@@ -462,6 +509,7 @@ The None variant
462509 }
463510 "# ,
464511 & [ "
512+ Option
465513Some
466514```
467515
@@ -815,4 +863,25 @@ fn func(foo: i32) { if true { <|>foo; }; }
815863 & [ "fn foo()\n ```\n \n <- `\u{3000} ` here" ] ,
816864 ) ;
817865 }
866+
867+ #[ test]
868+ fn zzz ( ) {
869+ check_hover_result (
870+ "
871+ //- /main.rs
872+ mod vvv {
873+ pub struct Test;
874+
875+ impl Test {
876+ pub fn whatever() {}
877+ }
878+ }
879+
880+ fn main() {
881+ vvv::Test::what<|>ever();
882+ }
883+ " ,
884+ & [ "vvv::Test\n pub fn whatever()" ] ,
885+ ) ;
886+ }
818887}
0 commit comments