aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src')
-rw-r--r--crates/ra_ide/src/hover.rs80
1 files changed, 22 insertions, 58 deletions
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index a227bf546..35e39f965 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -12,10 +12,7 @@ use ra_syntax::{
12 12
13use crate::{ 13use crate::{
14 db::RootDatabase, 14 db::RootDatabase,
15 display::{ 15 display::{macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel},
16 description_from_symbol, docs_from_symbol, macro_label, rust_code_markup,
17 rust_code_markup_with_doc, ShortLabel,
18 },
19 expand::descend_into_macros, 16 expand::descend_into_macros,
20 references::{classify_name, classify_name_ref, NameKind, NameKind::*}, 17 references::{classify_name, classify_name_ref, NameKind, NameKind::*},
21 FilePosition, FileRange, RangeInfo, 18 FilePosition, FileRange, RangeInfo,
@@ -95,11 +92,7 @@ fn hover_text(docs: Option<String>, desc: Option<String>) -> Option<String> {
95 } 92 }
96} 93}
97 94
98fn hover_text_from_name_kind( 95fn hover_text_from_name_kind(db: &RootDatabase, name_kind: NameKind) -> Option<String> {
99 db: &RootDatabase,
100 name_kind: NameKind,
101 no_fallback: &mut bool,
102) -> Option<String> {
103 return match name_kind { 96 return match name_kind {
104 Macro(it) => { 97 Macro(it) => {
105 let src = it.source(db); 98 let src = it.source(db);
@@ -135,11 +128,7 @@ fn hover_text_from_name_kind(
135 hir::ModuleDef::TypeAlias(it) => from_def_source(db, it), 128 hir::ModuleDef::TypeAlias(it) => from_def_source(db, it),
136 hir::ModuleDef::BuiltinType(it) => Some(it.to_string()), 129 hir::ModuleDef::BuiltinType(it) => Some(it.to_string()),
137 }, 130 },
138 Local(_) => { 131 Local(_) => None,
139 // Hover for these shows type names
140 *no_fallback = true;
141 None
142 }
143 TypeParam(_) | SelfType(_) => { 132 TypeParam(_) | SelfType(_) => {
144 // FIXME: Hover for generic param 133 // FIXME: Hover for generic param
145 None 134 None
@@ -163,60 +152,35 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
163 152
164 let mut res = HoverResult::new(); 153 let mut res = HoverResult::new();
165 154
166 let mut range = match_ast! { 155 if let Some((range, name_kind)) = match_ast! {
167 match (token.value.parent()) { 156 match (token.value.parent()) {
168 ast::NameRef(name_ref) => { 157 ast::NameRef(name_ref) => {
169 let mut no_fallback = false; 158 classify_name_ref(db, token.with_value(&name_ref)).map(|d| (name_ref.syntax().text_range(), d.kind))
170 if let Some(name_kind) =
171 classify_name_ref(db, token.with_value(&name_ref)).map(|d| d.kind)
172 {
173 res.extend(hover_text_from_name_kind(db, name_kind, &mut no_fallback))
174 }
175
176 if res.is_empty() && !no_fallback {
177 // Fallback index based approach:
178 let symbols = crate::symbol_index::index_resolve(db, &name_ref);
179 for sym in symbols {
180 let docs = docs_from_symbol(db, &sym);
181 let desc = description_from_symbol(db, &sym);
182 res.extend(hover_text(docs, desc));
183 }
184 }
185
186 if !res.is_empty() {
187 Some(name_ref.syntax().text_range())
188 } else {
189 None
190 }
191 }, 159 },
192 ast::Name(name) => { 160 ast::Name(name) => {
193 if let Some(name_kind) = classify_name(db, token.with_value(&name)).map(|d| d.kind) { 161 classify_name(db, token.with_value(&name)).map(|d| (name.syntax().text_range(), d.kind))
194 res.extend(hover_text_from_name_kind(db, name_kind, &mut true));
195 }
196
197 if !res.is_empty() {
198 Some(name.syntax().text_range())
199 } else {
200 None
201 }
202 }, 162 },
203 _ => None, 163 _ => None,
204 } 164 }
205 }; 165 } {
166 res.extend(hover_text_from_name_kind(db, name_kind));
206 167
207 if range.is_none() { 168 if !res.is_empty() {
208 let node = token.value.ancestors().find(|n| { 169 return Some(RangeInfo::new(range, res));
209 ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some() 170 }
210 })?; 171 }
211 let frange = FileRange { file_id: position.file_id, range: node.text_range() };
212 res.extend(type_of(db, frange).map(rust_code_markup));
213 range = Some(node.text_range());
214 };
215 172
216 let range = range?; 173 let node = token
174 .value
175 .ancestors()
176 .find(|n| ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some())?;
177 let frange = FileRange { file_id: position.file_id, range: node.text_range() };
178 res.extend(type_of(db, frange).map(rust_code_markup));
217 if res.is_empty() { 179 if res.is_empty() {
218 return None; 180 return None;
219 } 181 }
182 let range = node.text_range();
183
220 Some(RangeInfo::new(range, res)) 184 Some(RangeInfo::new(range, res))
221} 185}
222 186
@@ -314,7 +278,7 @@ mod tests {
314 &["pub fn foo() -> u32"], 278 &["pub fn foo() -> u32"],
315 ); 279 );
316 280
317 // Multiple results 281 // Multiple candidates but results are ambiguous.
318 check_hover_result( 282 check_hover_result(
319 r#" 283 r#"
320 //- /a.rs 284 //- /a.rs
@@ -335,7 +299,7 @@ mod tests {
335 let foo_test = fo<|>o(); 299 let foo_test = fo<|>o();
336 } 300 }
337 "#, 301 "#,
338 &["pub fn foo() -> &str", "pub fn foo() -> u32", "pub fn foo(a: u32, b: u32)"], 302 &["{unknown}"],
339 ); 303 );
340 } 304 }
341 305