aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/hover.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/hover.rs')
-rw-r--r--crates/ra_ide/src/hover.rs119
1 files changed, 94 insertions, 25 deletions
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index e9c682557..da3b67943 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -1,6 +1,8 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir::{Adt, HasSource, HirDisplay, Semantics}; 3use hir::{
4 Adt, AsAssocItem, AssocItemContainer, HasSource, HirDisplay, ModuleDef, ModuleSource, Semantics,
5};
4use ra_ide_db::{ 6use ra_ide_db::{
5 defs::{classify_name, classify_name_ref, Definition}, 7 defs::{classify_name, classify_name_ref, Definition},
6 RootDatabase, 8 RootDatabase,
@@ -16,6 +18,8 @@ use crate::{
16 display::{macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel}, 18 display::{macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel},
17 FilePosition, RangeInfo, 19 FilePosition, RangeInfo,
18}; 20};
21use itertools::Itertools;
22use std::iter::once;
19 23
20/// Contains the results when hovering over an item 24/// Contains the results when hovering over an item
21#[derive(Debug, Clone)] 25#[derive(Debug, Clone)]
@@ -83,44 +87,86 @@ impl HoverResult {
83 } 87 }
84} 88}
85 89
86fn hover_text(docs: Option<String>, desc: Option<String>) -> Option<String> { 90fn hover_text(
87 match (desc, docs) { 91 docs: Option<String>,
88 (Some(desc), docs) => Some(rust_code_markup_with_doc(desc, docs)), 92 desc: Option<String>,
89 (None, Some(docs)) => Some(docs), 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 _ => None, 98 _ => None,
91 } 99 }
92} 100}
93 101
102fn 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
120fn 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
94fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<String> { 137fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<String> {
138 let mod_path = determine_mod_path(db, &def);
95 return match def { 139 return match def {
96 Definition::Macro(it) => { 140 Definition::Macro(it) => {
97 let src = it.source(db); 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 Definition::StructField(it) => { 144 Definition::StructField(it) => {
101 let src = it.source(db); 145 let src = it.source(db);
102 match src.value { 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 _ => None, 150 _ => None,
105 } 151 }
106 } 152 }
107 Definition::ModuleDef(it) => match it { 153 Definition::ModuleDef(it) => match it {
108 hir::ModuleDef::Module(it) => match it.definition_source(db).value { 154 ModuleDef::Module(it) => match it.definition_source(db).value {
109 hir::ModuleSource::Module(it) => { 155 ModuleSource::Module(it) => {
110 hover_text(it.doc_comment_text(), it.short_label()) 156 hover_text(it.doc_comment_text(), it.short_label(), mod_path)
111 } 157 }
112 _ => None, 158 _ => None,
113 }, 159 },
114 hir::ModuleDef::Function(it) => from_def_source(db, it), 160 ModuleDef::Function(it) => from_def_source(db, it, mod_path),
115 hir::ModuleDef::Adt(Adt::Struct(it)) => from_def_source(db, it), 161 ModuleDef::Adt(Adt::Struct(it)) => from_def_source(db, it, mod_path),
116 hir::ModuleDef::Adt(Adt::Union(it)) => from_def_source(db, it), 162 ModuleDef::Adt(Adt::Union(it)) => from_def_source(db, it, mod_path),
117 hir::ModuleDef::Adt(Adt::Enum(it)) => from_def_source(db, it), 163 ModuleDef::Adt(Adt::Enum(it)) => from_def_source(db, it, mod_path),
118 hir::ModuleDef::EnumVariant(it) => from_def_source(db, it), 164 ModuleDef::EnumVariant(it) => from_def_source(db, it, mod_path),
119 hir::ModuleDef::Const(it) => from_def_source(db, it), 165 ModuleDef::Const(it) => from_def_source(db, it, mod_path),
120 hir::ModuleDef::Static(it) => from_def_source(db, it), 166 ModuleDef::Static(it) => from_def_source(db, it, mod_path),
121 hir::ModuleDef::Trait(it) => from_def_source(db, it), 167 ModuleDef::Trait(it) => from_def_source(db, it, mod_path),
122 hir::ModuleDef::TypeAlias(it) => from_def_source(db, it), 168 ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path),
123 hir::ModuleDef::BuiltinType(it) => Some(it.to_string()), 169 ModuleDef::BuiltinType(it) => Some(it.to_string()),
124 }, 170 },
125 Definition::Local(it) => { 171 Definition::Local(it) => {
126 Some(rust_code_markup(it.ty(db).display_truncated(db, None).to_string())) 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 where 181 where
136 D: HasSource<Ast = A>, 182 D: HasSource<Ast = A>,
137 A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel, 183 A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel,
138 { 184 {
139 let src = def.source(db); 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\nfield_a: u32"],
349 ); 395 );
350 396
351 // Hovering over the field in the definition 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\nfield_a: u32"],
366 ); 412 );
367 } 413 }
368 414
@@ -415,7 +461,7 @@ fn main() {
415 ", 461 ",
416 ); 462 );
417 let hover = analysis.hover(position).unwrap().unwrap(); 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\nSome"));
419 465
420 let (analysis, position) = single_file_with_position( 466 let (analysis, position) = single_file_with_position(
421 " 467 "
@@ -442,6 +488,7 @@ fn main() {
442 } 488 }
443 "#, 489 "#,
444 &[" 490 &["
491Option
445None 492None
446``` 493```
447 494
@@ -462,6 +509,7 @@ The None variant
462 } 509 }
463 "#, 510 "#,
464 &[" 511 &["
512Option
465Some 513Some
466``` 514```
467 515
@@ -815,4 +863,25 @@ fn func(foo: i32) { if true { <|>foo; }; }
815 &["fn foo()\n```\n\n<- `\u{3000}` here"], 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\npub fn whatever()"],
885 );
886 }
818} 887}