aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide')
-rw-r--r--crates/ra_ide/src/display.rs14
-rw-r--r--crates/ra_ide/src/hover.rs114
-rw-r--r--crates/ra_ide/src/lib.rs12
-rw-r--r--crates/ra_ide/src/mock_analysis.rs10
-rw-r--r--crates/ra_ide/src/parent_module.rs1
5 files changed, 111 insertions, 40 deletions
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..8b8af35fc 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -1,6 +1,10 @@
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, FieldSource, HasSource, HirDisplay, ModuleDef,
5 ModuleSource, Semantics,
6};
7use ra_db::SourceDatabase;
4use ra_ide_db::{ 8use ra_ide_db::{
5 defs::{classify_name, classify_name_ref, Definition}, 9 defs::{classify_name, classify_name_ref, Definition},
6 RootDatabase, 10 RootDatabase,
@@ -16,6 +20,8 @@ use crate::{
16 display::{macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel}, 20 display::{macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel},
17 FilePosition, RangeInfo, 21 FilePosition, RangeInfo,
18}; 22};
23use itertools::Itertools;
24use std::iter::once;
19 25
20/// Contains the results when hovering over an item 26/// Contains the results when hovering over an item
21#[derive(Debug, Clone)] 27#[derive(Debug, Clone)]
@@ -83,44 +89,86 @@ impl HoverResult {
83 } 89 }
84} 90}
85 91
86fn hover_text(docs: Option<String>, desc: Option<String>) -> Option<String> { 92fn hover_text(
87 match (desc, docs) { 93 docs: Option<String>,
88 (Some(desc), docs) => Some(rust_code_markup_with_doc(desc, docs)), 94 desc: Option<String>,
89 (None, Some(docs)) => Some(docs), 95 mod_path: Option<String>,
96) -> Option<String> {
97 match (desc, docs, mod_path) {
98 (Some(desc), docs, mod_path) => Some(rust_code_markup_with_doc(desc, docs, mod_path)),
99 (None, Some(docs), _) => Some(docs),
100 _ => None,
101 }
102}
103
104fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String> {
105 match def {
106 Definition::StructField(f) => Some(f.parent_def(db).name(db)),
107 Definition::Local(l) => l.parent(db).name(db),
108 Definition::ModuleDef(md) => match md {
109 ModuleDef::Function(f) => match f.as_assoc_item(db)?.container(db) {
110 AssocItemContainer::Trait(t) => Some(t.name(db)),
111 AssocItemContainer::ImplDef(i) => i.target_ty(db).as_adt().map(|adt| adt.name(db)),
112 },
113 ModuleDef::EnumVariant(e) => Some(e.parent_enum(db).name(db)),
114 _ => None,
115 },
116 Definition::SelfType(i) => i.target_ty(db).as_adt().map(|adt| adt.name(db)),
90 _ => None, 117 _ => None,
91 } 118 }
119 .map(|name| name.to_string())
120}
121
122fn determine_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> {
123 let mod_path = def.module(db).map(|module| {
124 once(db.crate_graph().crate_data(&module.krate().into()).display_name.clone())
125 .chain(
126 module
127 .path_to_root(db)
128 .into_iter()
129 .rev()
130 .map(|it| it.name(db).map(|name| name.to_string())),
131 )
132 .chain(once(definition_owner_name(db, def)))
133 .flatten()
134 .join("::")
135 });
136 mod_path
92} 137}
93 138
94fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<String> { 139fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<String> {
140 let mod_path = determine_mod_path(db, &def);
95 return match def { 141 return match def {
96 Definition::Macro(it) => { 142 Definition::Macro(it) => {
97 let src = it.source(db); 143 let src = it.source(db);
98 hover_text(src.value.doc_comment_text(), Some(macro_label(&src.value))) 144 hover_text(src.value.doc_comment_text(), Some(macro_label(&src.value)), mod_path)
99 } 145 }
100 Definition::StructField(it) => { 146 Definition::StructField(it) => {
101 let src = it.source(db); 147 let src = it.source(db);
102 match src.value { 148 match src.value {
103 hir::FieldSource::Named(it) => hover_text(it.doc_comment_text(), it.short_label()), 149 FieldSource::Named(it) => {
150 hover_text(it.doc_comment_text(), it.short_label(), mod_path)
151 }
104 _ => None, 152 _ => None,
105 } 153 }
106 } 154 }
107 Definition::ModuleDef(it) => match it { 155 Definition::ModuleDef(it) => match it {
108 hir::ModuleDef::Module(it) => match it.definition_source(db).value { 156 ModuleDef::Module(it) => match it.definition_source(db).value {
109 hir::ModuleSource::Module(it) => { 157 ModuleSource::Module(it) => {
110 hover_text(it.doc_comment_text(), it.short_label()) 158 hover_text(it.doc_comment_text(), it.short_label(), mod_path)
111 } 159 }
112 _ => None, 160 _ => None,
113 }, 161 },
114 hir::ModuleDef::Function(it) => from_def_source(db, it), 162 ModuleDef::Function(it) => from_def_source(db, it, mod_path),
115 hir::ModuleDef::Adt(Adt::Struct(it)) => from_def_source(db, it), 163 ModuleDef::Adt(Adt::Struct(it)) => from_def_source(db, it, mod_path),
116 hir::ModuleDef::Adt(Adt::Union(it)) => from_def_source(db, it), 164 ModuleDef::Adt(Adt::Union(it)) => from_def_source(db, it, mod_path),
117 hir::ModuleDef::Adt(Adt::Enum(it)) => from_def_source(db, it), 165 ModuleDef::Adt(Adt::Enum(it)) => from_def_source(db, it, mod_path),
118 hir::ModuleDef::EnumVariant(it) => from_def_source(db, it), 166 ModuleDef::EnumVariant(it) => from_def_source(db, it, mod_path),
119 hir::ModuleDef::Const(it) => from_def_source(db, it), 167 ModuleDef::Const(it) => from_def_source(db, it, mod_path),
120 hir::ModuleDef::Static(it) => from_def_source(db, it), 168 ModuleDef::Static(it) => from_def_source(db, it, mod_path),
121 hir::ModuleDef::Trait(it) => from_def_source(db, it), 169 ModuleDef::Trait(it) => from_def_source(db, it, mod_path),
122 hir::ModuleDef::TypeAlias(it) => from_def_source(db, it), 170 ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path),
123 hir::ModuleDef::BuiltinType(it) => Some(it.to_string()), 171 ModuleDef::BuiltinType(it) => Some(it.to_string()),
124 }, 172 },
125 Definition::Local(it) => { 173 Definition::Local(it) => {
126 Some(rust_code_markup(it.ty(db).display_truncated(db, None).to_string())) 174 Some(rust_code_markup(it.ty(db).display_truncated(db, None).to_string()))
@@ -131,13 +179,13 @@ fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<Strin
131 } 179 }
132 }; 180 };
133 181
134 fn from_def_source<A, D>(db: &RootDatabase, def: D) -> Option<String> 182 fn from_def_source<A, D>(db: &RootDatabase, def: D, mod_path: Option<String>) -> Option<String>
135 where 183 where
136 D: HasSource<Ast = A>, 184 D: HasSource<Ast = A>,
137 A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel, 185 A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel,
138 { 186 {
139 let src = def.source(db); 187 let src = def.source(db);
140 hover_text(src.value.doc_comment_text(), src.value.short_label()) 188 hover_text(src.value.doc_comment_text(), src.value.short_label(), mod_path)
141 } 189 }
142} 190}
143 191
@@ -345,7 +393,7 @@ mod tests {
345 }; 393 };
346 } 394 }
347 "#, 395 "#,
348 &["field_a: u32"], 396 &["Foo\nfield_a: u32"],
349 ); 397 );
350 398
351 // Hovering over the field in the definition 399 // Hovering over the field in the definition
@@ -362,7 +410,7 @@ mod tests {
362 }; 410 };
363 } 411 }
364 "#, 412 "#,
365 &["field_a: u32"], 413 &["Foo\nfield_a: u32"],
366 ); 414 );
367 } 415 }
368 416
@@ -415,7 +463,7 @@ fn main() {
415 ", 463 ",
416 ); 464 );
417 let hover = analysis.hover(position).unwrap().unwrap(); 465 let hover = analysis.hover(position).unwrap().unwrap();
418 assert_eq!(trim_markup_opt(hover.info.first()), Some("Some")); 466 assert_eq!(trim_markup_opt(hover.info.first()), Some("Option\nSome"));
419 467
420 let (analysis, position) = single_file_with_position( 468 let (analysis, position) = single_file_with_position(
421 " 469 "
@@ -442,6 +490,7 @@ fn main() {
442 } 490 }
443 "#, 491 "#,
444 &[" 492 &["
493Option
445None 494None
446``` 495```
447 496
@@ -462,6 +511,7 @@ The None variant
462 } 511 }
463 "#, 512 "#,
464 &[" 513 &["
514Option
465Some 515Some
466``` 516```
467 517
@@ -528,21 +578,23 @@ fn func(foo: i32) { if true { <|>foo; }; }
528 fn test_hover_infer_associated_method_exact() { 578 fn test_hover_infer_associated_method_exact() {
529 let (analysis, position) = single_file_with_position( 579 let (analysis, position) = single_file_with_position(
530 " 580 "
531 struct Thing { x: u32 } 581 mod wrapper {
582 struct Thing { x: u32 }
532 583
533 impl Thing { 584 impl Thing {
534 fn new() -> Thing { 585 fn new() -> Thing {
535 Thing { x: 0 } 586 Thing { x: 0 }
587 }
536 } 588 }
537 } 589 }
538 590
539 fn main() { 591 fn main() {
540 let foo_test = Thing::new<|>(); 592 let foo_test = wrapper::Thing::new<|>();
541 } 593 }
542 ", 594 ",
543 ); 595 );
544 let hover = analysis.hover(position).unwrap().unwrap(); 596 let hover = analysis.hover(position).unwrap().unwrap();
545 assert_eq!(trim_markup_opt(hover.info.first()), Some("fn new() -> Thing")); 597 assert_eq!(trim_markup_opt(hover.info.first()), Some("wrapper::Thing\nfn new() -> Thing"));
546 assert_eq!(hover.info.is_exact(), true); 598 assert_eq!(hover.info.is_exact(), true);
547 } 599 }
548 600
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs
index 4dfe0553e..903624381 100644
--- a/crates/ra_ide/src/lib.rs
+++ b/crates/ra_ide/src/lib.rs
@@ -211,7 +211,13 @@ impl Analysis {
211 // Default to enable test for single file. 211 // Default to enable test for single file.
212 let mut cfg_options = CfgOptions::default(); 212 let mut cfg_options = CfgOptions::default();
213 cfg_options.insert_atom("test".into()); 213 cfg_options.insert_atom("test".into());
214 crate_graph.add_crate_root(file_id, Edition::Edition2018, cfg_options, Env::default()); 214 crate_graph.add_crate_root(
215 file_id,
216 Edition::Edition2018,
217 None,
218 cfg_options,
219 Env::default(),
220 );
215 change.add_file(source_root, file_id, "main.rs".into(), Arc::new(text)); 221 change.add_file(source_root, file_id, "main.rs".into(), Arc::new(text));
216 change.set_crate_graph(crate_graph); 222 change.set_crate_graph(crate_graph);
217 host.apply_change(change); 223 host.apply_change(change);
@@ -415,12 +421,12 @@ impl Analysis {
415 421
416 /// Returns the edition of the given crate. 422 /// Returns the edition of the given crate.
417 pub fn crate_edition(&self, crate_id: CrateId) -> Cancelable<Edition> { 423 pub fn crate_edition(&self, crate_id: CrateId) -> Cancelable<Edition> {
418 self.with_db(|db| db.crate_graph().edition(crate_id)) 424 self.with_db(|db| db.crate_graph().crate_data(&crate_id).edition)
419 } 425 }
420 426
421 /// Returns the root file of the given crate. 427 /// Returns the root file of the given crate.
422 pub fn crate_root(&self, crate_id: CrateId) -> Cancelable<FileId> { 428 pub fn crate_root(&self, crate_id: CrateId) -> Cancelable<FileId> {
423 self.with_db(|db| db.crate_graph().crate_root(crate_id)) 429 self.with_db(|db| db.crate_graph().crate_data(&crate_id).root_file_id)
424 } 430 }
425 431
426 /// Returns the set of possible targets to run for the current file. 432 /// Returns the set of possible targets to run for the current file.
diff --git a/crates/ra_ide/src/mock_analysis.rs b/crates/ra_ide/src/mock_analysis.rs
index f4cd6deb7..90f84b052 100644
--- a/crates/ra_ide/src/mock_analysis.rs
+++ b/crates/ra_ide/src/mock_analysis.rs
@@ -99,13 +99,19 @@ impl MockAnalysis {
99 root_crate = Some(crate_graph.add_crate_root( 99 root_crate = Some(crate_graph.add_crate_root(
100 file_id, 100 file_id,
101 Edition2018, 101 Edition2018,
102 None,
102 cfg_options, 103 cfg_options,
103 Env::default(), 104 Env::default(),
104 )); 105 ));
105 } else if path.ends_with("/lib.rs") { 106 } else if path.ends_with("/lib.rs") {
106 let other_crate =
107 crate_graph.add_crate_root(file_id, Edition2018, cfg_options, Env::default());
108 let crate_name = path.parent().unwrap().file_name().unwrap(); 107 let crate_name = path.parent().unwrap().file_name().unwrap();
108 let other_crate = crate_graph.add_crate_root(
109 file_id,
110 Edition2018,
111 Some(crate_name.to_owned()),
112 cfg_options,
113 Env::default(),
114 );
109 if let Some(root_crate) = root_crate { 115 if let Some(root_crate) = root_crate {
110 crate_graph 116 crate_graph
111 .add_dep(root_crate, CrateName::new(crate_name).unwrap(), other_crate) 117 .add_dep(root_crate, CrateName::new(crate_name).unwrap(), other_crate)
diff --git a/crates/ra_ide/src/parent_module.rs b/crates/ra_ide/src/parent_module.rs
index 2c4bdb039..b73cefd97 100644
--- a/crates/ra_ide/src/parent_module.rs
+++ b/crates/ra_ide/src/parent_module.rs
@@ -133,6 +133,7 @@ mod tests {
133 let crate_id = crate_graph.add_crate_root( 133 let crate_id = crate_graph.add_crate_root(
134 root_file, 134 root_file,
135 Edition2018, 135 Edition2018,
136 None,
136 CfgOptions::default(), 137 CfgOptions::default(),
137 Env::default(), 138 Env::default(),
138 ); 139 );