Skip to content

Commit 32f5276

Browse files
Show mod path in hover tooltip
1 parent aff82cf commit 32f5276

File tree

4 files changed

+132
-29
lines changed

4 files changed

+132
-29
lines changed

crates/ra_hir/src/code_model.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,14 @@ impl Adt {
480480
pub fn krate(self, db: &impl HirDatabase) -> Option<Crate> {
481481
Some(self.module(db).krate())
482482
}
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+
}
483491
}
484492

485493
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
@@ -507,6 +515,14 @@ impl VariantDef {
507515
}
508516
}
509517

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+
510526
pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
511527
match self {
512528
VariantDef::Struct(it) => it.variant_data(db),
@@ -534,6 +550,14 @@ impl DefWithBody {
534550
DefWithBody::Static(s) => s.module(db),
535551
}
536552
}
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+
}
537561
}
538562

539563
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]

crates/ra_ide/src/display.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,23 @@ pub(crate) fn macro_label(node: &ast::MacroCall) -> String {
6868
}
6969

7070
pub(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)
7272
}
7373

74-
pub(crate) fn rust_code_markup_with_doc<CODE, DOC>(val: CODE, doc: Option<DOC>) -> String
74+
pub(crate) fn rust_code_markup_with_doc<CODE, DOC>(
75+
val: CODE,
76+
doc: Option<DOC>,
77+
mod_path: Option<String>,
78+
) -> String
7579
where
7680
CODE: AsRef<str>,
7781
DOC: AsRef<str>,
7882
{
83+
let mod_path =
84+
mod_path.filter(|path| !path.is_empty()).map(|path| path + "\n").unwrap_or_default();
7985
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())
8187
} else {
82-
format!("```rust\n{}\n```", val.as_ref())
88+
format!("```rust\n{}{}\n```", mod_path, val.as_ref())
8389
}
8490
}

crates/ra_ide/src/hover.rs

Lines changed: 94 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
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+
};
46
use 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+
94137
fn 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\nfield_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\nfield_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\nSome"));
419465

420466
let (analysis, position) = single_file_with_position(
421467
"
@@ -442,6 +488,7 @@ fn main() {
442488
}
443489
"#,
444490
&["
491+
Option
445492
None
446493
```
447494
@@ -462,6 +509,7 @@ The None variant
462509
}
463510
"#,
464511
&["
512+
Option
465513
Some
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\npub fn whatever()"],
885+
);
886+
}
818887
}

crates/ra_ide_db/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ impl RootDatabase {
104104
db.query_mut(hir::db::MacroExpandQuery).set_lru_capacity(lru_capacity);
105105
db
106106
}
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+
}
107111
}
108112

109113
impl salsa::ParallelDatabase for RootDatabase {

0 commit comments

Comments
 (0)