aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/hover.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api/src/hover.rs')
-rw-r--r--crates/ra_ide_api/src/hover.rs140
1 files changed, 128 insertions, 12 deletions
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs
index cb676eb12..1f454be21 100644
--- a/crates/ra_ide_api/src/hover.rs
+++ b/crates/ra_ide_api/src/hover.rs
@@ -1,6 +1,6 @@
1use ra_db::SourceDatabase; 1use ra_db::SourceDatabase;
2use ra_syntax::{ 2use ra_syntax::{
3 AstNode, ast, 3 AstNode, ast::{self, DocCommentsOwner},
4 algo::{find_covering_element, find_node_at_offset, ancestors_at_offset}, 4 algo::{find_covering_element, find_node_at_offset, ancestors_at_offset},
5}; 5};
6use hir::HirDisplay; 6use hir::HirDisplay;
@@ -8,7 +8,8 @@ use hir::HirDisplay;
8use crate::{ 8use crate::{
9 db::RootDatabase, 9 db::RootDatabase,
10 RangeInfo, FilePosition, FileRange, 10 RangeInfo, FilePosition, FileRange,
11 display::{rust_code_markup, doc_text_for}, 11 display::{rust_code_markup, doc_text_for, rust_code_markup_with_doc, ShortLabel, docs_from_symbol, description_from_symbol},
12 name_ref_kind::{NameRefKind::*, classify_name_ref},
12}; 13};
13 14
14/// Contains the results when hovering over an item 15/// Contains the results when hovering over an item
@@ -77,25 +78,140 @@ impl HoverResult {
77 } 78 }
78} 79}
79 80
81fn hover_text(docs: Option<String>, desc: Option<String>) -> Option<String> {
82 match (desc, docs) {
83 (Some(desc), docs) => Some(rust_code_markup_with_doc(desc, docs)),
84 (None, Some(docs)) => Some(docs.to_string()),
85 _ => None,
86 }
87}
88
80pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeInfo<HoverResult>> { 89pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeInfo<HoverResult>> {
81 let file = db.parse(position.file_id).tree; 90 let file = db.parse(position.file_id).tree;
82 let mut res = HoverResult::new(); 91 let mut res = HoverResult::new();
83 92
84 let mut range = None; 93 let mut range = None;
85 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) { 94 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) {
86 use crate::goto_definition::{ReferenceResult::*, reference_definition}; 95 let analyzer = hir::SourceAnalyzer::new(db, position.file_id, name_ref.syntax(), None);
87 let ref_result = reference_definition(db, position.file_id, name_ref); 96
88 match ref_result { 97 match classify_name_ref(db, &analyzer, name_ref) {
89 Exact(nav) => res.extend(doc_text_for(nav)), 98 Some(Method(it)) => {
90 Approximate(navs) => { 99 let it = it.source(db).1;
91 // We are no longer exact 100 res.extend(hover_text(it.doc_comment_text(), it.short_label()));
92 res.exact = false; 101 }
93 102 Some(Macro(it)) => {
94 for nav in navs { 103 let it = it.source(db).1;
95 res.extend(doc_text_for(nav)) 104 res.extend(hover_text(it.doc_comment_text(), None));
105 }
106 Some(FieldAccess(it)) => {
107 let it = it.source(db).1;
108 if let hir::FieldSource::Named(it) = it {
109 res.extend(hover_text(it.doc_comment_text(), it.short_label()));
110 }
111 }
112 Some(AssocItem(it)) => match it {
113 hir::ImplItem::Method(it) => {
114 let it = it.source(db).1;
115 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
116 }
117 hir::ImplItem::Const(it) => {
118 let it = it.source(db).1;
119 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
120 }
121 hir::ImplItem::TypeAlias(it) => {
122 let it = it.source(db).1;
123 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
96 } 124 }
125 },
126 Some(Def(it)) => {
127 match it {
128 hir::ModuleDef::Module(it) => {
129 let it = it.definition_source(db).1;
130 if let hir::ModuleSource::Module(it) = it {
131 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
132 }
133 }
134 hir::ModuleDef::Function(it) => {
135 let it = it.source(db).1;
136 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
137 }
138 hir::ModuleDef::Struct(it) => {
139 let it = it.source(db).1;
140 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
141 }
142 hir::ModuleDef::Union(it) => {
143 let it = it.source(db).1;
144 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
145 }
146 hir::ModuleDef::Enum(it) => {
147 let it = it.source(db).1;
148 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
149 }
150 hir::ModuleDef::EnumVariant(it) => {
151 let it = it.source(db).1;
152 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
153 }
154 hir::ModuleDef::Const(it) => {
155 let it = it.source(db).1;
156 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
157 }
158 hir::ModuleDef::Static(it) => {
159 let it = it.source(db).1;
160 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
161 }
162 hir::ModuleDef::Trait(it) => {
163 let it = it.source(db).1;
164 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
165 }
166 hir::ModuleDef::TypeAlias(it) => {
167 let it = it.source(db).1;
168 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
169 }
170 hir::ModuleDef::BuiltinType(_) => {
171 // FIXME: hover for builtin Type ?
172 }
173 }
174 }
175 Some(SelfType(ty)) => {
176 if let Some((adt_def, _)) = ty.as_adt() {
177 match adt_def {
178 hir::AdtDef::Struct(it) => {
179 let it = it.source(db).1;
180 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
181 }
182 hir::AdtDef::Union(it) => {
183 let it = it.source(db).1;
184 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
185 }
186 hir::AdtDef::Enum(it) => {
187 let it = it.source(db).1;
188 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
189 }
190 }
191 }
192 }
193 Some(Pat(_)) => {
194 res.extend(None);
195 }
196 Some(SelfParam(_)) => {
197 res.extend(None);
97 } 198 }
199 Some(GenericParam(_)) => {
200 // FIXME: Hover for generic param
201 }
202 None => {}
98 } 203 }
204
205 if res.is_empty() {
206 // Fallback index based approach:
207 let symbols = crate::symbol_index::index_resolve(db, name_ref);
208 for sym in symbols {
209 let docs = docs_from_symbol(db, &sym);
210 let desc = description_from_symbol(db, &sym);
211 res.extend(hover_text(docs, desc));
212 }
213 }
214
99 if !res.is_empty() { 215 if !res.is_empty() {
100 range = Some(name_ref.syntax().range()) 216 range = Some(name_ref.syntax().range())
101 } 217 }