Differentiate method/tymethod by determining 'defaultness'

Currently a method only has defaultness if it is a provided trait
method, but this will change when specialisation is available and may
need to become a concept known to hir.

I opted to go for a 'fewest changes' approach given specialisation is
still under development.
This commit is contained in:
Zac Pullar-Strecker 2020-09-03 19:55:24 +12:00
parent 62b76e7004
commit c648884397
7 changed files with 31 additions and 9 deletions

View file

@ -13,7 +13,7 @@ use ide_db::{defs::Definition, RootDatabase};
use hir::{
db::{DefDatabase, HirDatabase},
Adt, AsName, AssocItem, Crate, Field, HasAttrs, ItemInNs, ModuleDef,
Adt, AsName, AssocItem, Crate, Field, HasAttrs, ItemInNs, MethodOwner, ModuleDef,
};
use ide_db::{
defs::{classify_name, classify_name_ref, Definition},
@ -117,7 +117,7 @@ fn get_doc_link(db: &RootDatabase, definition: Definition) -> Option<String> {
let target_def: ModuleDef = match definition {
Definition::ModuleDef(moddef) => match moddef {
ModuleDef::Function(f) => {
f.parent_def(db).map(|mowner| mowner.into()).unwrap_or_else(|| f.clone().into())
f.method_owner(db).map(|mowner| mowner.into()).unwrap_or_else(|| f.clone().into())
}
moddef => moddef,
},
@ -401,9 +401,18 @@ fn get_symbol_fragment(db: &dyn HirDatabase, field_or_assoc: &FieldOrAssocItem)
Some(match field_or_assoc {
FieldOrAssocItem::Field(field) => format!("#structfield.{}", field.name(db)),
FieldOrAssocItem::AssocItem(assoc) => match assoc {
// TODO: Rustdoc sometimes uses tymethod instead of method. This case needs to be investigated.
AssocItem::Function(function) => format!("#method.{}", function.name(db)),
// TODO: This might be the old method for documenting associated constants, i32::MAX uses a separate page...
AssocItem::Function(function) => {
let is_trait_method =
matches!(function.method_owner(db), Some(MethodOwner::Trait(..)));
// This distinction may get more complicated when specialisation is available.
// In particular this decision is made based on whether a method 'has defaultness'.
// Currently this is only the case for provided trait methods.
if is_trait_method && !function.has_body(db) {
format!("#tymethod.{}", function.name(db))
} else {
format!("#method.{}", function.name(db))
}
}
AssocItem::Const(constant) => format!("#associatedconstant.{}", constant.name(db)?),
AssocItem::TypeAlias(ty) => format!("#associatedtype.{}", ty.name(db)),
},