|
1 | 1 | //! Logic for rendering the different hover messages |
| 2 | +use std::{mem, ops::Not}; |
| 3 | + |
2 | 4 | use either::Either; |
3 | 5 | use hir::{ |
4 | | - Adt, AsAssocItem, CaptureKind, HasSource, HirDisplay, Layout, LayoutError, Semantics, TypeInfo, |
| 6 | + db::DefDatabase, Adt, AsAssocItem, AssocItem, CaptureKind, HasCrate, HasSource, HirDisplay, |
| 7 | + Layout, LayoutError, Semantics, TypeInfo, |
5 | 8 | }; |
6 | 9 | use ide_db::{ |
7 | 10 | base_db::SourceDatabase, |
@@ -390,7 +393,6 @@ pub(super) fn definition( |
390 | 393 | let mod_path = definition_mod_path(db, &def); |
391 | 394 | let label = def.label(db)?; |
392 | 395 | let docs = def.docs(db, famous_defs); |
393 | | - |
394 | 396 | let value = match def { |
395 | 397 | Definition::Variant(it) => { |
396 | 398 | if !it.parent_enum(db).is_data_carrying(db) { |
@@ -462,14 +464,75 @@ pub(super) fn definition( |
462 | 464 | _ => None, |
463 | 465 | }; |
464 | 466 |
|
465 | | - let label = match (value, layout_info) { |
466 | | - (Some(value), Some(layout_info)) => format!("{layout_info}\n{label} = {value}"), |
467 | | - (Some(value), None) => format!("{label} = {value}"), |
468 | | - (None, Some(layout_info)) => format!("{layout_info}\n{label}"), |
469 | | - (None, None) => label, |
| 467 | + let def_ty = match def { |
| 468 | + Definition::Local(it) => Some(it.ty(db)), |
| 469 | + Definition::GenericParam(hir::GenericParam::ConstParam(it)) => Some(it.ty(db)), |
| 470 | + Definition::GenericParam(hir::GenericParam::TypeParam(it)) => Some(it.ty(db)), |
| 471 | + Definition::Field(field) => Some(field.ty(db)), |
| 472 | + Definition::TupleField(it) => Some(it.ty(db)), |
| 473 | + Definition::Function(it) => Some(it.ty(db)), |
| 474 | + Definition::Adt(it) => Some(it.ty(db)), |
| 475 | + Definition::Const(it) => Some(it.ty(db)), |
| 476 | + Definition::Static(it) => Some(it.ty(db)), |
| 477 | + Definition::TypeAlias(it) => Some(it.ty(db)), |
| 478 | + Definition::BuiltinType(it) => Some(it.ty(db)), |
| 479 | + _ => None, |
470 | 480 | }; |
| 481 | + let notable_traits = def_ty.and_then(|ty| { |
| 482 | + let mut desc = String::new(); |
| 483 | + let mut needs_impl_header = true; |
| 484 | + for &trait_ in db.notable_traits_in_deps(ty.krate(db).into()).iter().flat_map(|it| &**it) { |
| 485 | + let trait_ = trait_.into(); |
| 486 | + if ty.impls_trait(db, trait_, &[]) { |
| 487 | + let aliases: Vec<_> = trait_ |
| 488 | + .items(db) |
| 489 | + .into_iter() |
| 490 | + .filter_map(AssocItem::as_type_alias) |
| 491 | + .map(|alias| (ty.normalize_trait_assoc_type(db, &[], alias), alias.name(db))) |
| 492 | + .collect(); |
| 493 | + desc.push_str(if mem::take(&mut needs_impl_header) { |
| 494 | + " // notable traits impls: " |
| 495 | + } else { |
| 496 | + ", " |
| 497 | + }); |
| 498 | + format_to!(desc, "{}", trait_.name(db).display(db),); |
| 499 | + if !aliases.is_empty() { |
| 500 | + desc.push('<'); |
| 501 | + format_to!( |
| 502 | + desc, |
| 503 | + "{}", |
| 504 | + aliases.into_iter().format_with(", ", |(ty, name), f| { |
| 505 | + f(&name.display(db))?; |
| 506 | + f(&" = ")?; |
| 507 | + match ty { |
| 508 | + Some(ty) => f(&ty.display(db)), |
| 509 | + None => f(&"?"), |
| 510 | + } |
| 511 | + }) |
| 512 | + ); |
| 513 | + desc.push('>'); |
| 514 | + } |
| 515 | + } |
| 516 | + } |
| 517 | + desc.is_empty().not().then(|| desc) |
| 518 | + }); |
| 519 | + |
| 520 | + let mut desc = String::new(); |
| 521 | + if let Some(notable_traits) = notable_traits { |
| 522 | + desc.push_str(¬able_traits); |
| 523 | + desc.push('\n'); |
| 524 | + } |
| 525 | + if let Some(layout_info) = layout_info { |
| 526 | + desc.push_str(&layout_info); |
| 527 | + desc.push('\n'); |
| 528 | + } |
| 529 | + desc.push_str(&label); |
| 530 | + if let Some(value) = value { |
| 531 | + desc.push_str(" = "); |
| 532 | + desc.push_str(&value); |
| 533 | + } |
471 | 534 |
|
472 | | - markup(docs.map(Into::into), label, mod_path) |
| 535 | + markup(docs.map(Into::into), desc, mod_path) |
473 | 536 | } |
474 | 537 |
|
475 | 538 | fn type_info( |
|
0 commit comments