Impl hovering for TypeParams

This commit is contained in:
Lukas Wirth 2021-01-02 00:05:51 +01:00
parent 5b86ff3e91
commit 47900dd3bc
3 changed files with 67 additions and 7 deletions

View file

@ -5,9 +5,7 @@ use arrayvec::ArrayVec;
use base_db::{CrateDisplayName, CrateId, Edition, FileId}; use base_db::{CrateDisplayName, CrateId, Edition, FileId};
use either::Either; use either::Either;
use hir_def::{ use hir_def::{
adt::ReprKind, adt::{ReprKind, StructKind, VariantData},
adt::StructKind,
adt::VariantData,
builtin_type::BuiltinType, builtin_type::BuiltinType,
expr::{BindingAnnotation, LabelId, Pat, PatId}, expr::{BindingAnnotation, LabelId, Pat, PatId},
import_map, import_map,
@ -31,7 +29,7 @@ use hir_expand::{
}; };
use hir_ty::{ use hir_ty::{
autoderef, autoderef,
display::{HirDisplayError, HirFormatter}, display::{write_bounds_like_dyn_trait, HirDisplayError, HirFormatter},
method_resolution, method_resolution,
traits::{FnTrait, Solution, SolutionVariables}, traits::{FnTrait, Solution, SolutionVariables},
ApplicationTy, BoundVar, CallableDefId, Canonical, DebruijnIndex, FnSig, GenericPredicate, ApplicationTy, BoundVar, CallableDefId, Canonical, DebruijnIndex, FnSig, GenericPredicate,
@ -1293,6 +1291,20 @@ impl TypeParam {
} }
} }
impl HirDisplay for TypeParam {
fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
write!(f, "{}", self.name(f.db))?;
let bounds = f.db.generic_predicates_for_param(self.id);
let substs = Substs::type_params(f.db, self.id.parent);
let predicates = bounds.iter().cloned().map(|b| b.subst(&substs)).collect::<Vec<_>>();
if !(predicates.is_empty() || f.omit_verbose_types()) {
write!(f, ": ")?;
write_bounds_like_dyn_trait(&predicates, f)?;
}
Ok(())
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct LifetimeParam { pub struct LifetimeParam {
pub(crate) id: LifetimeParamId, pub(crate) id: LifetimeParamId,

View file

@ -595,7 +595,7 @@ impl HirDisplay for FnSig {
} }
} }
fn write_bounds_like_dyn_trait( pub fn write_bounds_like_dyn_trait(
predicates: &[GenericPredicate], predicates: &[GenericPredicate],
f: &mut HirFormatter, f: &mut HirFormatter,
) -> Result<(), HirDisplayError> { ) -> Result<(), HirDisplayError> {

View file

@ -370,8 +370,9 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
} }
Definition::Label(it) => Some(Markup::fenced_block(&it.name(db))), Definition::Label(it) => Some(Markup::fenced_block(&it.name(db))),
Definition::LifetimeParam(it) => Some(Markup::fenced_block(&it.name(db))), Definition::LifetimeParam(it) => Some(Markup::fenced_block(&it.name(db))),
Definition::TypeParam(_) | Definition::ConstParam(_) => { Definition::TypeParam(type_param) => Some(Markup::fenced_block(&type_param.display(db))),
// FIXME: Hover for generic param Definition::ConstParam(_) => {
// FIXME: Hover for generic const param
None None
} }
}; };
@ -3257,4 +3258,51 @@ fn foo() {
"#]], "#]],
); );
} }
#[test]
fn hover_type_param() {
check(
r#"
struct Foo<T>(T);
trait Copy {}
trait Clone {}
trait Sized {}
impl<T: Copy + Clone> Foo<T<|>> where T: Sized {}
"#,
expect![[r#"
*T*
```rust
T: Copy + Clone + Sized
```
"#]],
);
check(
r#"
struct Foo<T>(T);
impl<T> Foo<T<|>> {}
"#,
expect![[r#"
*T*
```rust
T
```
"#]],
);
// lifetimes aren't being substituted yet
check(
r#"
struct Foo<T>(T);
impl<T: 'static> Foo<T<|>> {}
"#,
expect![[r#"
*T*
```rust
T: {error}
```
"#]],
);
}
} }