aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src/hover.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide/src/hover.rs')
-rw-r--r--crates/ide/src/hover.rs74
1 files changed, 55 insertions, 19 deletions
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 73245fbe7..2737c900f 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -13,7 +13,7 @@ use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset,
13use test_utils::mark; 13use test_utils::mark;
14 14
15use crate::{ 15use crate::{
16 display::{macro_label, ShortLabel, ToNav, TryToNav}, 16 display::{macro_label, ShortLabel, TryToNav},
17 doc_links::{remove_links, rewrite_links}, 17 doc_links::{remove_links, rewrite_links},
18 markdown_remove::remove_markdown, 18 markdown_remove::remove_markdown,
19 markup::Markup, 19 markup::Markup,
@@ -109,6 +109,8 @@ pub(crate) fn hover(
109 match node { 109 match node {
110 ast::Name(name) => NameClass::classify(&sema, &name).and_then(|d| d.defined(sema.db)), 110 ast::Name(name) => NameClass::classify(&sema, &name).and_then(|d| d.defined(sema.db)),
111 ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)), 111 ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)),
112 ast::Lifetime(lifetime) => NameClass::classify_lifetime(&sema, &lifetime)
113 .map_or_else(|| NameRefClass::classify_lifetime(&sema, &lifetime).map(|d| d.referenced(sema.db)), |d| d.defined(sema.db)),
112 _ => None, 114 _ => None,
113 } 115 }
114 }; 116 };
@@ -181,10 +183,10 @@ fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<Hov
181 183
182 match def { 184 match def {
183 Definition::ModuleDef(it) => match it { 185 Definition::ModuleDef(it) => match it {
184 ModuleDef::Adt(Adt::Struct(it)) => Some(to_action(it.to_nav(db))), 186 ModuleDef::Adt(Adt::Struct(it)) => Some(to_action(it.try_to_nav(db)?)),
185 ModuleDef::Adt(Adt::Union(it)) => Some(to_action(it.to_nav(db))), 187 ModuleDef::Adt(Adt::Union(it)) => Some(to_action(it.try_to_nav(db)?)),
186 ModuleDef::Adt(Adt::Enum(it)) => Some(to_action(it.to_nav(db))), 188 ModuleDef::Adt(Adt::Enum(it)) => Some(to_action(it.try_to_nav(db)?)),
187 ModuleDef::Trait(it) => Some(to_action(it.to_nav(db))), 189 ModuleDef::Trait(it) => Some(to_action(it.try_to_nav(db)?)),
188 _ => None, 190 _ => None,
189 }, 191 },
190 _ => None, 192 _ => None,
@@ -204,7 +206,8 @@ fn runnable_action(
204 _ => None, 206 _ => None,
205 }, 207 },
206 ModuleDef::Function(it) => { 208 ModuleDef::Function(it) => {
207 let src = it.source(sema.db); 209 #[allow(deprecated)]
210 let src = it.source(sema.db)?;
208 if src.file_id != file_id.into() { 211 if src.file_id != file_id.into() {
209 mark::hit!(hover_macro_generated_struct_fn_doc_comment); 212 mark::hit!(hover_macro_generated_struct_fn_doc_comment);
210 mark::hit!(hover_macro_generated_struct_fn_doc_attr); 213 mark::hit!(hover_macro_generated_struct_fn_doc_attr);
@@ -324,17 +327,12 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
324 let mod_path = definition_mod_path(db, &def); 327 let mod_path = definition_mod_path(db, &def);
325 return match def { 328 return match def {
326 Definition::Macro(it) => { 329 Definition::Macro(it) => {
327 // FIXME: Currently proc-macro do not have ast-node, 330 let label = macro_label(&it.source(db)?.value);
328 // such that it does not have source
329 // more discussion: https://github.com/rust-analyzer/rust-analyzer/issues/6913
330 if it.is_proc_macro() {
331 return None;
332 }
333 let label = macro_label(&it.source(db).value);
334 from_def_source_labeled(db, it, Some(label), mod_path) 331 from_def_source_labeled(db, it, Some(label), mod_path)
335 } 332 }
336 Definition::Field(def) => { 333 Definition::Field(def) => {
337 let src = def.source(db).value; 334 #[allow(deprecated)]
335 let src = def.source(db)?.value;
338 if let FieldSource::Named(it) = src { 336 if let FieldSource::Named(it) = src {
339 from_def_source_labeled(db, def, it.short_label(), mod_path) 337 from_def_source_labeled(db, def, it.short_label(), mod_path)
340 } else { 338 } else {
@@ -360,9 +358,9 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
360 ModuleDef::Static(it) => from_def_source(db, it, mod_path), 358 ModuleDef::Static(it) => from_def_source(db, it, mod_path),
361 ModuleDef::Trait(it) => from_def_source(db, it, mod_path), 359 ModuleDef::Trait(it) => from_def_source(db, it, mod_path),
362 ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path), 360 ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path),
363 ModuleDef::BuiltinType(it) => return Some(it.to_string().into()), 361 ModuleDef::BuiltinType(it) => Some(Markup::fenced_block(&it)),
364 }, 362 },
365 Definition::Local(it) => return Some(Markup::fenced_block(&it.ty(db).display(db))), 363 Definition::Local(it) => Some(Markup::fenced_block(&it.ty(db).display(db))),
366 Definition::SelfType(impl_def) => { 364 Definition::SelfType(impl_def) => {
367 impl_def.target_ty(db).as_adt().and_then(|adt| match adt { 365 impl_def.target_ty(db).as_adt().and_then(|adt| match adt {
368 Adt::Struct(it) => from_def_source(db, it, mod_path), 366 Adt::Struct(it) => from_def_source(db, it, mod_path),
@@ -370,7 +368,9 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
370 Adt::Enum(it) => from_def_source(db, it, mod_path), 368 Adt::Enum(it) => from_def_source(db, it, mod_path),
371 }) 369 })
372 } 370 }
373 Definition::TypeParam(_) | Definition::LifetimeParam(_) | Definition::Label(_) => { 371 Definition::Label(it) => Some(Markup::fenced_block(&it.name(db))),
372 Definition::LifetimeParam(it) => Some(Markup::fenced_block(&it.name(db))),
373 Definition::TypeParam(_) | Definition::ConstParam(_) => {
374 // FIXME: Hover for generic param 374 // FIXME: Hover for generic param
375 None 375 None
376 } 376 }
@@ -381,7 +381,8 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
381 D: HasSource<Ast = A> + HasAttrs + Copy, 381 D: HasSource<Ast = A> + HasAttrs + Copy,
382 A: ShortLabel, 382 A: ShortLabel,
383 { 383 {
384 let short_label = def.source(db).value.short_label(); 384 #[allow(deprecated)]
385 let short_label = def.source(db)?.value.short_label();
385 from_def_source_labeled(db, def, short_label, mod_path) 386 from_def_source_labeled(db, def, short_label, mod_path)
386 } 387 }
387 388
@@ -403,7 +404,7 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
403 return tokens.max_by_key(priority); 404 return tokens.max_by_key(priority);
404 fn priority(n: &SyntaxToken) -> usize { 405 fn priority(n: &SyntaxToken) -> usize {
405 match n.kind() { 406 match n.kind() {
406 IDENT | INT_NUMBER => 3, 407 IDENT | INT_NUMBER | LIFETIME_IDENT => 3,
407 T!['('] | T![')'] => 2, 408 T!['('] | T![')'] => 2,
408 kind if kind.is_trivia() => 0, 409 kind if kind.is_trivia() => 0,
409 _ => 1, 410 _ => 1,
@@ -1169,7 +1170,10 @@ fn f() { fo<|>o!(); }
1169 r#"struct TS(String, i32<|>);"#, 1170 r#"struct TS(String, i32<|>);"#,
1170 expect![[r#" 1171 expect![[r#"
1171 *i32* 1172 *i32*
1173
1174 ```rust
1172 i32 1175 i32
1176 ```
1173 "#]], 1177 "#]],
1174 ) 1178 )
1175 } 1179 }
@@ -3221,4 +3225,36 @@ fn no_hover() {
3221"#, 3225"#,
3222 ); 3226 );
3223 } 3227 }
3228
3229 #[test]
3230 fn hover_label() {
3231 check(
3232 r#"
3233fn foo() {
3234 'label<|>: loop {}
3235}
3236"#,
3237 expect![[r#"
3238 *'label*
3239
3240 ```rust
3241 'label
3242 ```
3243 "#]],
3244 );
3245 }
3246
3247 #[test]
3248 fn hover_lifetime() {
3249 check(
3250 r#"fn foo<'lifetime>(_: &'lifetime<|> ()) {}"#,
3251 expect![[r#"
3252 *'lifetime*
3253
3254 ```rust
3255 'lifetime
3256 ```
3257 "#]],
3258 );
3259 }
3224} 3260}