aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKirill Bulatov <[email protected]>2020-03-05 23:02:14 +0000
committerKirill Bulatov <[email protected]>2020-03-07 21:20:18 +0000
commit32f5276465266522ebc01b8417feeba99bf00f6f (patch)
tree6388994a0cc67c7ca60658e81489a832569e3c4e
parentaff82cf7ac172f213cb5dcca637cb2c5332294c1 (diff)
Show mod path in hover tooltip
-rw-r--r--crates/ra_hir/src/code_model.rs24
-rw-r--r--crates/ra_ide/src/display.rs14
-rw-r--r--crates/ra_ide/src/hover.rs119
-rw-r--r--crates/ra_ide_db/src/lib.rs4
4 files changed, 132 insertions, 29 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 2944926e6..dca5f27b2 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -480,6 +480,14 @@ impl Adt {
480 pub fn krate(self, db: &impl HirDatabase) -> Option<Crate> { 480 pub fn krate(self, db: &impl HirDatabase) -> Option<Crate> {
481 Some(self.module(db).krate()) 481 Some(self.module(db).krate())
482 } 482 }
483
484 pub fn name(&self, db: &impl HirDatabase) -> Name {
485 match self {
486 Adt::Struct(s) => s.name(db),
487 Adt::Union(u) => u.name(db),
488 Adt::Enum(e) => e.name(db),
489 }
490 }
483} 491}
484 492
485#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 493#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
@@ -507,6 +515,14 @@ impl VariantDef {
507 } 515 }
508 } 516 }
509 517
518 pub fn name(&self, db: &impl HirDatabase) -> Name {
519 match self {
520 VariantDef::Struct(s) => s.name(db),
521 VariantDef::Union(u) => u.name(db),
522 VariantDef::EnumVariant(e) => e.name(db),
523 }
524 }
525
510 pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> { 526 pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
511 match self { 527 match self {
512 VariantDef::Struct(it) => it.variant_data(db), 528 VariantDef::Struct(it) => it.variant_data(db),
@@ -534,6 +550,14 @@ impl DefWithBody {
534 DefWithBody::Static(s) => s.module(db), 550 DefWithBody::Static(s) => s.module(db),
535 } 551 }
536 } 552 }
553
554 pub fn name(self, db: &impl HirDatabase) -> Option<Name> {
555 match self {
556 DefWithBody::Function(f) => Some(f.name(db)),
557 DefWithBody::Static(s) => s.name(db),
558 DefWithBody::Const(c) => c.name(db),
559 }
560 }
537} 561}
538 562
539#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 563#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
diff --git a/crates/ra_ide/src/display.rs b/crates/ra_ide/src/display.rs
index 1c26a8697..eaeaaa2b4 100644
--- a/crates/ra_ide/src/display.rs
+++ b/crates/ra_ide/src/display.rs
@@ -68,17 +68,23 @@ pub(crate) fn macro_label(node: &ast::MacroCall) -> String {
68} 68}
69 69
70pub(crate) fn rust_code_markup<CODE: AsRef<str>>(val: CODE) -> String { 70pub(crate) fn rust_code_markup<CODE: AsRef<str>>(val: CODE) -> String {
71 rust_code_markup_with_doc::<_, &str>(val, None) 71 rust_code_markup_with_doc::<_, &str>(val, None, None)
72} 72}
73 73
74pub(crate) fn rust_code_markup_with_doc<CODE, DOC>(val: CODE, doc: Option<DOC>) -> String 74pub(crate) fn rust_code_markup_with_doc<CODE, DOC>(
75 val: CODE,
76 doc: Option<DOC>,
77 mod_path: Option<String>,
78) -> String
75where 79where
76 CODE: AsRef<str>, 80 CODE: AsRef<str>,
77 DOC: AsRef<str>, 81 DOC: AsRef<str>,
78{ 82{
83 let mod_path =
84 mod_path.filter(|path| !path.is_empty()).map(|path| path + "\n").unwrap_or_default();
79 if let Some(doc) = doc { 85 if let Some(doc) = doc {
80 format!("```rust\n{}\n```\n\n{}", val.as_ref(), doc.as_ref()) 86 format!("```rust\n{}{}\n```\n\n{}", mod_path, val.as_ref(), doc.as_ref())
81 } else { 87 } else {
82 format!("```rust\n{}\n```", val.as_ref()) 88 format!("```rust\n{}{}\n```", mod_path, val.as_ref())
83 } 89 }
84} 90}
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}
diff --git a/crates/ra_ide_db/src/lib.rs b/crates/ra_ide_db/src/lib.rs
index 79f48c9e3..efa472c7d 100644
--- a/crates/ra_ide_db/src/lib.rs
+++ b/crates/ra_ide_db/src/lib.rs
@@ -104,6 +104,10 @@ impl RootDatabase {
104 db.query_mut(hir::db::MacroExpandQuery).set_lru_capacity(lru_capacity); 104 db.query_mut(hir::db::MacroExpandQuery).set_lru_capacity(lru_capacity);
105 db 105 db
106 } 106 }
107
108 pub fn get_crate_original_name(&self, crate_id: &CrateId) -> Option<String> {
109 self.debug_data.crate_names.get(crate_id).cloned()
110 }
107} 111}
108 112
109impl salsa::ParallelDatabase for RootDatabase { 113impl salsa::ParallelDatabase for RootDatabase {