1
1
//! FIXME: write short doc here
2
2
3
- use hir:: { Adt , HasSource , HirDisplay , Semantics } ;
3
+ use hir:: {
4
+ Adt , AsAssocItem , AssocItemContainer , HasSource , HirDisplay , ModuleDef , ModuleSource , Semantics ,
5
+ } ;
4
6
use ra_ide_db:: {
5
7
defs:: { classify_name, classify_name_ref, Definition } ,
6
8
RootDatabase ,
@@ -16,6 +18,8 @@ use crate::{
16
18
display:: { macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel } ,
17
19
FilePosition , RangeInfo ,
18
20
} ;
21
+ use itertools:: Itertools ;
22
+ use std:: iter:: once;
19
23
20
24
/// Contains the results when hovering over an item
21
25
#[ derive( Debug , Clone ) ]
@@ -83,44 +87,86 @@ impl HoverResult {
83
87
}
84
88
}
85
89
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) ,
90
98
_ => None ,
91
99
}
92
100
}
93
101
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
+
94
137
fn hover_text_from_name_kind ( db : & RootDatabase , def : Definition ) -> Option < String > {
138
+ let mod_path = determine_mod_path ( db, & def) ;
95
139
return match def {
96
140
Definition :: Macro ( it) => {
97
141
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 )
99
143
}
100
144
Definition :: StructField ( it) => {
101
145
let src = it. source ( db) ;
102
146
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
+ }
104
150
_ => None ,
105
151
}
106
152
}
107
153
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 )
111
157
}
112
158
_ => None ,
113
159
} ,
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 ( ) ) ,
124
170
} ,
125
171
Definition :: Local ( it) => {
126
172
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
131
177
}
132
178
} ;
133
179
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 >
135
181
where
136
182
D : HasSource < Ast = A > ,
137
183
A : ast:: DocCommentsOwner + ast:: NameOwner + ShortLabel ,
138
184
{
139
185
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 )
141
187
}
142
188
}
143
189
@@ -345,7 +391,7 @@ mod tests {
345
391
};
346
392
}
347
393
"# ,
348
- & [ "field_a : u32" ] ,
394
+ & [ "Foo \n field_a : u32" ] ,
349
395
) ;
350
396
351
397
// Hovering over the field in the definition
@@ -362,7 +408,7 @@ mod tests {
362
408
};
363
409
}
364
410
"# ,
365
- & [ "field_a : u32" ] ,
411
+ & [ "Foo \n field_a : u32" ] ,
366
412
) ;
367
413
}
368
414
@@ -415,7 +461,7 @@ fn main() {
415
461
" ,
416
462
) ;
417
463
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 " ) ) ;
419
465
420
466
let ( analysis, position) = single_file_with_position (
421
467
"
@@ -442,6 +488,7 @@ fn main() {
442
488
}
443
489
"# ,
444
490
& [ "
491
+ Option
445
492
None
446
493
```
447
494
@@ -462,6 +509,7 @@ The None variant
462
509
}
463
510
"# ,
464
511
& [ "
512
+ Option
465
513
Some
466
514
```
467
515
@@ -815,4 +863,25 @@ fn func(foo: i32) { if true { <|>foo; }; }
815
863
& [ "fn foo()\n ```\n \n <- `\u{3000} ` here" ] ,
816
864
) ;
817
865
}
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
+ }
818
887
}
0 commit comments