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.rs188
1 files changed, 114 insertions, 74 deletions
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index ea45086ce..325014622 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -1,7 +1,7 @@
1use either::Either; 1use either::Either;
2use hir::{ 2use hir::{
3 Adt, AsAssocItem, AssocItemContainer, FieldSource, GenericParam, HasAttrs, HasSource, 3 AsAssocItem, AssocItemContainer, GenericParam, HasAttrs, HasSource, HirDisplay, Module,
4 HirDisplay, Module, ModuleDef, ModuleSource, Semantics, 4 ModuleDef, Semantics,
5}; 5};
6use ide_db::{ 6use ide_db::{
7 base_db::SourceDatabase, 7 base_db::SourceDatabase,
@@ -14,7 +14,7 @@ use stdx::format_to;
14use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T}; 14use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T};
15 15
16use crate::{ 16use crate::{
17 display::{macro_label, ShortLabel, TryToNav}, 17 display::{macro_label, TryToNav},
18 doc_links::{remove_links, rewrite_links}, 18 doc_links::{remove_links, rewrite_links},
19 markdown_remove::remove_markdown, 19 markdown_remove::remove_markdown,
20 markup::Markup, 20 markup::Markup,
@@ -92,7 +92,7 @@ pub(crate) fn hover(
92 92
93 let mut res = HoverResult::default(); 93 let mut res = HoverResult::default();
94 94
95 let node = token.parent(); 95 let node = token.parent()?;
96 let definition = match_ast! { 96 let definition = match_ast! {
97 match node { 97 match node {
98 // we don't use NameClass::referenced_or_defined here as we do not want to resolve 98 // we don't use NameClass::referenced_or_defined here as we do not want to resolve
@@ -335,61 +335,34 @@ fn hover_for_definition(
335 let label = macro_label(&it.source(db)?.value); 335 let label = macro_label(&it.source(db)?.value);
336 from_def_source_labeled(db, it, Some(label), mod_path) 336 from_def_source_labeled(db, it, Some(label), mod_path)
337 } 337 }
338 Definition::Field(def) => { 338 Definition::Field(def) => from_hir_fmt(db, def, mod_path),
339 let src = def.source(db)?.value;
340 if let FieldSource::Named(it) = src {
341 from_def_source_labeled(db, def, it.short_label(), mod_path)
342 } else {
343 None
344 }
345 }
346 Definition::ModuleDef(it) => match it { 339 Definition::ModuleDef(it) => match it {
347 ModuleDef::Module(it) => from_def_source_labeled( 340 ModuleDef::Module(it) => from_hir_fmt(db, it, mod_path),
348 db, 341 ModuleDef::Function(it) => from_hir_fmt(db, it, mod_path),
349 it, 342 ModuleDef::Adt(it) => from_hir_fmt(db, it, mod_path),
350 match it.definition_source(db).value { 343 ModuleDef::Variant(it) => from_hir_fmt(db, it, mod_path),
351 ModuleSource::Module(it) => it.short_label(), 344 ModuleDef::Const(it) => from_hir_fmt(db, it, mod_path),
352 ModuleSource::SourceFile(it) => it.short_label(), 345 ModuleDef::Static(it) => from_hir_fmt(db, it, mod_path),
353 ModuleSource::BlockExpr(it) => it.short_label(), 346 ModuleDef::Trait(it) => from_hir_fmt(db, it, mod_path),
354 }, 347 ModuleDef::TypeAlias(it) => from_hir_fmt(db, it, mod_path),
355 mod_path,
356 ),
357 ModuleDef::Function(it) => from_def_source(db, it, mod_path),
358 ModuleDef::Adt(Adt::Struct(it)) => from_def_source(db, it, mod_path),
359 ModuleDef::Adt(Adt::Union(it)) => from_def_source(db, it, mod_path),
360 ModuleDef::Adt(Adt::Enum(it)) => from_def_source(db, it, mod_path),
361 ModuleDef::Variant(it) => from_def_source(db, it, mod_path),
362 ModuleDef::Const(it) => from_def_source(db, it, mod_path),
363 ModuleDef::Static(it) => from_def_source(db, it, mod_path),
364 ModuleDef::Trait(it) => from_def_source(db, it, mod_path),
365 ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path),
366 ModuleDef::BuiltinType(it) => famous_defs 348 ModuleDef::BuiltinType(it) => famous_defs
367 .and_then(|fd| hover_for_builtin(fd, it)) 349 .and_then(|fd| hover_for_builtin(fd, it))
368 .or_else(|| Some(Markup::fenced_block(&it.name()))), 350 .or_else(|| Some(Markup::fenced_block(&it.name()))),
369 }, 351 },
370 Definition::Local(it) => hover_for_local(it, db), 352 Definition::Local(it) => hover_for_local(it, db),
371 Definition::SelfType(impl_def) => { 353 Definition::SelfType(impl_def) => {
372 impl_def.target_ty(db).as_adt().and_then(|adt| match adt { 354 impl_def.target_ty(db).as_adt().and_then(|adt| from_hir_fmt(db, adt, mod_path))
373 Adt::Struct(it) => from_def_source(db, it, mod_path),
374 Adt::Union(it) => from_def_source(db, it, mod_path),
375 Adt::Enum(it) => from_def_source(db, it, mod_path),
376 })
377 } 355 }
356 Definition::GenericParam(it) => from_hir_fmt(db, it, None),
378 Definition::Label(it) => Some(Markup::fenced_block(&it.name(db))), 357 Definition::Label(it) => Some(Markup::fenced_block(&it.name(db))),
379 Definition::GenericParam(it) => match it {
380 GenericParam::TypeParam(it) => Some(Markup::fenced_block(&it.display(db))),
381 GenericParam::LifetimeParam(it) => Some(Markup::fenced_block(&it.name(db))),
382 GenericParam::ConstParam(it) => from_def_source(db, it, None),
383 },
384 }; 358 };
385 359
386 fn from_def_source<A, D>(db: &RootDatabase, def: D, mod_path: Option<String>) -> Option<Markup> 360 fn from_hir_fmt<D>(db: &RootDatabase, def: D, mod_path: Option<String>) -> Option<Markup>
387 where 361 where
388 D: HasSource<Ast = A> + HasAttrs + Copy, 362 D: HasAttrs + HirDisplay,
389 A: ShortLabel,
390 { 363 {
391 let short_label = def.source(db)?.value.short_label(); 364 let label = def.display(db).to_string();
392 from_def_source_labeled(db, def, short_label, mod_path) 365 from_def_source_labeled(db, def, Some(label), mod_path)
393 } 366 }
394 367
395 fn from_def_source_labeled<D>( 368 fn from_def_source_labeled<D>(
@@ -438,7 +411,7 @@ fn hover_for_keyword(
438 if !token.kind().is_keyword() { 411 if !token.kind().is_keyword() {
439 return None; 412 return None;
440 } 413 }
441 let famous_defs = FamousDefs(&sema, sema.scope(&token.parent()).krate()); 414 let famous_defs = FamousDefs(&sema, sema.scope(&token.parent()?).krate());
442 // std exposes {}_keyword modules with docstrings on the root to document keywords 415 // std exposes {}_keyword modules with docstrings on the root to document keywords
443 let keyword_mod = format!("{}_keyword", token.text()); 416 let keyword_mod = format!("{}_keyword", token.text());
444 let doc_owner = find_std_module(&famous_defs, &keyword_mod)?; 417 let doc_owner = find_std_module(&famous_defs, &keyword_mod)?;
@@ -670,7 +643,9 @@ fn main() { let foo_test = fo$0o(); }
670 ``` 643 ```
671 644
672 ```rust 645 ```rust
673 pub fn foo<'a, T: AsRef<str>>(b: &'a T) -> &'a str 646 pub fn foo<'a, T>(b: &'a T) -> &'a str
647 where
648 T: AsRef<str>,
674 ``` 649 ```
675 "#]], 650 "#]],
676 ); 651 );
@@ -878,7 +853,7 @@ fn main() { So$0me(12); }
878 ``` 853 ```
879 854
880 ```rust 855 ```rust
881 Some 856 Some(T)
882 ``` 857 ```
883 "#]], 858 "#]],
884 ); 859 );
@@ -944,7 +919,7 @@ fn main() {
944 ``` 919 ```
945 920
946 ```rust 921 ```rust
947 Some 922 Some(T)
948 ``` 923 ```
949 924
950 --- 925 ---
@@ -1441,13 +1416,14 @@ fn bar() { fo$0o(); }
1441 ``` 1416 ```
1442 "#]], 1417 "#]],
1443 ); 1418 );
1419 // Top level `pub(crate)` will be displayed as no visibility.
1444 check( 1420 check(
1445 r#"pub(crate) async unsafe extern "C" fn foo$0() {}"#, 1421 r#"mod m { pub(crate) async unsafe extern "C" fn foo$0() {} }"#,
1446 expect![[r#" 1422 expect![[r#"
1447 *foo* 1423 *foo*
1448 1424
1449 ```rust 1425 ```rust
1450 test 1426 test::m
1451 ``` 1427 ```
1452 1428
1453 ```rust 1429 ```rust
@@ -1489,11 +1465,18 @@ extern crate st$0d;
1489//! abc123 1465//! abc123
1490 "#, 1466 "#,
1491 expect![[r#" 1467 expect![[r#"
1492 *std* 1468 *std*
1493 Standard library for this test 1469
1470 ```rust
1471 extern crate std
1472 ```
1473
1474 ---
1494 1475
1495 Printed? 1476 Standard library for this test
1496 abc123 1477
1478 Printed?
1479 abc123
1497 "#]], 1480 "#]],
1498 ); 1481 );
1499 check( 1482 check(
@@ -1507,11 +1490,18 @@ extern crate std as ab$0c;
1507//! abc123 1490//! abc123
1508 "#, 1491 "#,
1509 expect![[r#" 1492 expect![[r#"
1510 *abc* 1493 *abc*
1511 Standard library for this test 1494
1495 ```rust
1496 extern crate std
1497 ```
1512 1498
1513 Printed? 1499 ---
1514 abc123 1500
1501 Standard library for this test
1502
1503 Printed?
1504 abc123
1515 "#]], 1505 "#]],
1516 ); 1506 );
1517 } 1507 }
@@ -2021,7 +2011,7 @@ enum E {
2021 ``` 2011 ```
2022 2012
2023 ```rust 2013 ```rust
2024 V 2014 V { field: i32 }
2025 ``` 2015 ```
2026 2016
2027 --- 2017 ---
@@ -2417,7 +2407,7 @@ fn main() { let s$0t = S{ f1:Arg(0) }; }
2417 focus_range: 24..25, 2407 focus_range: 24..25,
2418 name: "S", 2408 name: "S",
2419 kind: Struct, 2409 kind: Struct,
2420 description: "struct S", 2410 description: "struct S<T>",
2421 }, 2411 },
2422 }, 2412 },
2423 HoverGotoTypeData { 2413 HoverGotoTypeData {
@@ -2463,7 +2453,7 @@ fn main() { let s$0t = S{ f1: S{ f1: Arg(0) } }; }
2463 focus_range: 24..25, 2453 focus_range: 24..25,
2464 name: "S", 2454 name: "S",
2465 kind: Struct, 2455 kind: Struct,
2466 description: "struct S", 2456 description: "struct S<T>",
2467 }, 2457 },
2468 }, 2458 },
2469 HoverGotoTypeData { 2459 HoverGotoTypeData {
@@ -2605,7 +2595,7 @@ fn main() { let s$0t = foo(); }
2605 focus_range: 6..9, 2595 focus_range: 6..9,
2606 name: "Foo", 2596 name: "Foo",
2607 kind: Trait, 2597 kind: Trait,
2608 description: "trait Foo", 2598 description: "trait Foo<T>",
2609 }, 2599 },
2610 }, 2600 },
2611 HoverGotoTypeData { 2601 HoverGotoTypeData {
@@ -2702,7 +2692,7 @@ fn main() { let s$0t = foo(); }
2702 focus_range: 6..9, 2692 focus_range: 6..9,
2703 name: "Foo", 2693 name: "Foo",
2704 kind: Trait, 2694 kind: Trait,
2705 description: "trait Foo", 2695 description: "trait Foo<T>",
2706 }, 2696 },
2707 }, 2697 },
2708 HoverGotoTypeData { 2698 HoverGotoTypeData {
@@ -2715,7 +2705,7 @@ fn main() { let s$0t = foo(); }
2715 focus_range: 22..25, 2705 focus_range: 22..25,
2716 name: "Bar", 2706 name: "Bar",
2717 kind: Trait, 2707 kind: Trait,
2718 description: "trait Bar", 2708 description: "trait Bar<T>",
2719 }, 2709 },
2720 }, 2710 },
2721 HoverGotoTypeData { 2711 HoverGotoTypeData {
@@ -2819,7 +2809,7 @@ fn foo(ar$0g: &impl Foo + Bar<S>) {}
2819 focus_range: 19..22, 2809 focus_range: 19..22,
2820 name: "Bar", 2810 name: "Bar",
2821 kind: Trait, 2811 kind: Trait,
2822 description: "trait Bar", 2812 description: "trait Bar<T>",
2823 }, 2813 },
2824 }, 2814 },
2825 HoverGotoTypeData { 2815 HoverGotoTypeData {
@@ -2916,7 +2906,7 @@ fn foo(ar$0g: &impl Foo<S>) {}
2916 focus_range: 6..9, 2906 focus_range: 6..9,
2917 name: "Foo", 2907 name: "Foo",
2918 kind: Trait, 2908 kind: Trait,
2919 description: "trait Foo", 2909 description: "trait Foo<T>",
2920 }, 2910 },
2921 }, 2911 },
2922 HoverGotoTypeData { 2912 HoverGotoTypeData {
@@ -2966,7 +2956,7 @@ fn main() { let s$0t = foo(); }
2966 focus_range: 49..50, 2956 focus_range: 49..50,
2967 name: "B", 2957 name: "B",
2968 kind: Struct, 2958 kind: Struct,
2969 description: "struct B", 2959 description: "struct B<T>",
2970 }, 2960 },
2971 }, 2961 },
2972 HoverGotoTypeData { 2962 HoverGotoTypeData {
@@ -3042,7 +3032,7 @@ fn foo(ar$0g: &dyn Foo<S>) {}
3042 focus_range: 6..9, 3032 focus_range: 6..9,
3043 name: "Foo", 3033 name: "Foo",
3044 kind: Trait, 3034 kind: Trait,
3045 description: "trait Foo", 3035 description: "trait Foo<T>",
3046 }, 3036 },
3047 }, 3037 },
3048 HoverGotoTypeData { 3038 HoverGotoTypeData {
@@ -3090,7 +3080,7 @@ fn foo(a$0rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
3090 focus_range: 6..15, 3080 focus_range: 6..15,
3091 name: "ImplTrait", 3081 name: "ImplTrait",
3092 kind: Trait, 3082 kind: Trait,
3093 description: "trait ImplTrait", 3083 description: "trait ImplTrait<T>",
3094 }, 3084 },
3095 }, 3085 },
3096 HoverGotoTypeData { 3086 HoverGotoTypeData {
@@ -3103,7 +3093,7 @@ fn foo(a$0rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
3103 focus_range: 50..51, 3093 focus_range: 50..51,
3104 name: "B", 3094 name: "B",
3105 kind: Struct, 3095 kind: Struct,
3106 description: "struct B", 3096 description: "struct B<T>",
3107 }, 3097 },
3108 }, 3098 },
3109 HoverGotoTypeData { 3099 HoverGotoTypeData {
@@ -3116,7 +3106,7 @@ fn foo(a$0rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
3116 focus_range: 28..36, 3106 focus_range: 28..36,
3117 name: "DynTrait", 3107 name: "DynTrait",
3118 kind: Trait, 3108 kind: Trait,
3119 description: "trait DynTrait", 3109 description: "trait DynTrait<T>",
3120 }, 3110 },
3121 }, 3111 },
3122 HoverGotoTypeData { 3112 HoverGotoTypeData {
@@ -3582,6 +3572,17 @@ mod foo$0;
3582"#, 3572"#,
3583 expect![[r#" 3573 expect![[r#"
3584 *foo* 3574 *foo*
3575
3576 ```rust
3577 test
3578 ```
3579
3580 ```rust
3581 mod foo
3582 ```
3583
3584 ---
3585
3585 For the horde! 3586 For the horde!
3586 "#]], 3587 "#]],
3587 ); 3588 );
@@ -3606,7 +3607,7 @@ use foo::bar::{self$0};
3606 ``` 3607 ```
3607 3608
3608 ```rust 3609 ```rust
3609 pub mod bar 3610 mod bar
3610 ``` 3611 ```
3611 3612
3612 --- 3613 ---
@@ -3657,4 +3658,43 @@ cosnt _: &str$0 = ""; }"#;
3657 "#]], 3658 "#]],
3658 ); 3659 );
3659 } 3660 }
3661
3662 #[test]
3663 fn hover_macro_expanded_function() {
3664 check(
3665 r#"
3666struct S<'a, T>(&'a T);
3667trait Clone {}
3668macro_rules! foo {
3669 () => {
3670 fn bar<'t, T: Clone + 't>(s: &mut S<'t, T>, t: u32) -> *mut u32 where
3671 't: 't + 't,
3672 for<'a> T: Clone + 'a
3673 { 0 as _ }
3674 };
3675}
3676
3677foo!();
3678
3679fn main() {
3680 bar$0;
3681}
3682"#,
3683 expect![[r#"
3684 *bar*
3685
3686 ```rust
3687 test
3688 ```
3689
3690 ```rust
3691 fn bar<'t, T>(s: &mut S<'t, T>, t: u32) -> *mut u32
3692 where
3693 T: Clone + 't,
3694 't: 't + 't,
3695 for<'a> T: Clone + 'a,
3696 ```
3697 "#]],
3698 )
3699 }
3660} 3700}