|
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