aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/code_model.rs9
-rw-r--r--crates/hir/src/lib.rs4
-rw-r--r--crates/hir_def/src/data.rs2
-rw-r--r--crates/hir_def/src/item_tree.rs1
-rw-r--r--crates/hir_def/src/item_tree/lower.rs3
-rw-r--r--crates/ide/src/doc_links.rs19
-rw-r--r--editors/code/src/commands.ts2
7 files changed, 31 insertions, 9 deletions
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index 1dd6d73f3..0b24f247c 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -772,7 +772,14 @@ impl Function {
772 hir_ty::diagnostics::validate_body(db, self.id.into(), sink) 772 hir_ty::diagnostics::validate_body(db, self.id.into(), sink)
773 } 773 }
774 774
775 pub fn parent_def(self, db: &dyn HirDatabase) -> Option<MethodOwner> { 775 /// Whether this function declaration has a definition.
776 ///
777 /// This is false in the case of required (not provided) trait methods.
778 pub fn has_body(self, db: &dyn HirDatabase) -> bool {
779 db.function_data(self.id).has_body
780 }
781
782 pub fn method_owner(self, db: &dyn HirDatabase) -> Option<MethodOwner> {
776 match self.as_assoc_item(db).map(|assoc| assoc.container(db)) { 783 match self.as_assoc_item(db).map(|assoc| assoc.container(db)) {
777 Some(AssocItemContainer::Trait(t)) => Some(t.into()), 784 Some(AssocItemContainer::Trait(t)) => Some(t.into()),
778 Some(AssocItemContainer::ImplDef(imp)) => { 785 Some(AssocItemContainer::ImplDef(imp)) => {
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 4094a76cb..687abe6ca 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -35,8 +35,8 @@ pub use crate::{
35 code_model::{ 35 code_model::{
36 Access, Adt, AsAssocItem, AssocItem, AssocItemContainer, Callable, CallableKind, Const, 36 Access, Adt, AsAssocItem, AssocItem, AssocItemContainer, Callable, CallableKind, Const,
37 Crate, CrateDependency, DefWithBody, Enum, EnumVariant, Field, FieldSource, Function, 37 Crate, CrateDependency, DefWithBody, Enum, EnumVariant, Field, FieldSource, Function,
38 GenericDef, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, ScopeDef, Static, 38 GenericDef, HasVisibility, ImplDef, Local, MacroDef, MethodOwner, Module, ModuleDef,
39 Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility, 39 ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility,
40 }, 40 },
41 has_source::HasSource, 41 has_source::HasSource,
42 semantics::{original_range, PathResolution, Semantics, SemanticsScope}, 42 semantics::{original_range, PathResolution, Semantics, SemanticsScope},
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs
index 6190906da..ff1ef0df6 100644
--- a/crates/hir_def/src/data.rs
+++ b/crates/hir_def/src/data.rs
@@ -25,6 +25,7 @@ pub struct FunctionData {
25 /// True if the first param is `self`. This is relevant to decide whether this 25 /// True if the first param is `self`. This is relevant to decide whether this
26 /// can be called as a method. 26 /// can be called as a method.
27 pub has_self_param: bool, 27 pub has_self_param: bool,
28 pub has_body: bool,
28 pub is_unsafe: bool, 29 pub is_unsafe: bool,
29 pub is_varargs: bool, 30 pub is_varargs: bool,
30 pub visibility: RawVisibility, 31 pub visibility: RawVisibility,
@@ -42,6 +43,7 @@ impl FunctionData {
42 ret_type: func.ret_type.clone(), 43 ret_type: func.ret_type.clone(),
43 attrs: item_tree.attrs(ModItem::from(loc.id.value).into()).clone(), 44 attrs: item_tree.attrs(ModItem::from(loc.id.value).into()).clone(),
44 has_self_param: func.has_self_param, 45 has_self_param: func.has_self_param,
46 has_body: func.has_body,
45 is_unsafe: func.is_unsafe, 47 is_unsafe: func.is_unsafe,
46 is_varargs: func.is_varargs, 48 is_varargs: func.is_varargs,
47 visibility: item_tree[func.visibility].clone(), 49 visibility: item_tree[func.visibility].clone(),
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index 0fd91b9d0..8a1121bbd 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -505,6 +505,7 @@ pub struct Function {
505 pub visibility: RawVisibilityId, 505 pub visibility: RawVisibilityId,
506 pub generic_params: GenericParamsId, 506 pub generic_params: GenericParamsId,
507 pub has_self_param: bool, 507 pub has_self_param: bool,
508 pub has_body: bool,
508 pub is_unsafe: bool, 509 pub is_unsafe: bool,
509 pub params: Box<[TypeRef]>, 510 pub params: Box<[TypeRef]>,
510 pub is_varargs: bool, 511 pub is_varargs: bool,
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index 54814f141..3328639cf 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -330,12 +330,15 @@ impl Ctx {
330 ret_type 330 ret_type
331 }; 331 };
332 332
333 let has_body = func.body().is_some();
334
333 let ast_id = self.source_ast_id_map.ast_id(func); 335 let ast_id = self.source_ast_id_map.ast_id(func);
334 let mut res = Function { 336 let mut res = Function {
335 name, 337 name,
336 visibility, 338 visibility,
337 generic_params: GenericParamsId::EMPTY, 339 generic_params: GenericParamsId::EMPTY,
338 has_self_param, 340 has_self_param,
341 has_body,
339 is_unsafe: func.unsafe_token().is_some(), 342 is_unsafe: func.unsafe_token().is_some(),
340 params: params.into_boxed_slice(), 343 params: params.into_boxed_slice(),
341 is_varargs, 344 is_varargs,
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs
index 512c42c4d..2f6c59c40 100644
--- a/crates/ide/src/doc_links.rs
+++ b/crates/ide/src/doc_links.rs
@@ -13,7 +13,7 @@ use ide_db::{defs::Definition, RootDatabase};
13 13
14use hir::{ 14use hir::{
15 db::{DefDatabase, HirDatabase}, 15 db::{DefDatabase, HirDatabase},
16 Adt, AsName, AssocItem, Crate, Field, HasAttrs, ItemInNs, ModuleDef, 16 Adt, AsName, AssocItem, Crate, Field, HasAttrs, ItemInNs, MethodOwner, ModuleDef,
17}; 17};
18use ide_db::{ 18use ide_db::{
19 defs::{classify_name, classify_name_ref, Definition}, 19 defs::{classify_name, classify_name_ref, Definition},
@@ -117,7 +117,7 @@ fn get_doc_link(db: &RootDatabase, definition: Definition) -> Option<String> {
117 let target_def: ModuleDef = match definition { 117 let target_def: ModuleDef = match definition {
118 Definition::ModuleDef(moddef) => match moddef { 118 Definition::ModuleDef(moddef) => match moddef {
119 ModuleDef::Function(f) => { 119 ModuleDef::Function(f) => {
120 f.parent_def(db).map(|mowner| mowner.into()).unwrap_or_else(|| f.clone().into()) 120 f.method_owner(db).map(|mowner| mowner.into()).unwrap_or_else(|| f.clone().into())
121 } 121 }
122 moddef => moddef, 122 moddef => moddef,
123 }, 123 },
@@ -401,9 +401,18 @@ fn get_symbol_fragment(db: &dyn HirDatabase, field_or_assoc: &FieldOrAssocItem)
401 Some(match field_or_assoc { 401 Some(match field_or_assoc {
402 FieldOrAssocItem::Field(field) => format!("#structfield.{}", field.name(db)), 402 FieldOrAssocItem::Field(field) => format!("#structfield.{}", field.name(db)),
403 FieldOrAssocItem::AssocItem(assoc) => match assoc { 403 FieldOrAssocItem::AssocItem(assoc) => match assoc {
404 // TODO: Rustdoc sometimes uses tymethod instead of method. This case needs to be investigated. 404 AssocItem::Function(function) => {
405 AssocItem::Function(function) => format!("#method.{}", function.name(db)), 405 let is_trait_method =
406 // TODO: This might be the old method for documenting associated constants, i32::MAX uses a separate page... 406 matches!(function.method_owner(db), Some(MethodOwner::Trait(..)));
407 // This distinction may get more complicated when specialisation is available.
408 // In particular this decision is made based on whether a method 'has defaultness'.
409 // Currently this is only the case for provided trait methods.
410 if is_trait_method && !function.has_body(db) {
411 format!("#tymethod.{}", function.name(db))
412 } else {
413 format!("#method.{}", function.name(db))
414 }
415 }
407 AssocItem::Const(constant) => format!("#associatedconstant.{}", constant.name(db)?), 416 AssocItem::Const(constant) => format!("#associatedconstant.{}", constant.name(db)?),
408 AssocItem::TypeAlias(ty) => format!("#associatedtype.{}", ty.name(db)), 417 AssocItem::TypeAlias(ty) => format!("#associatedtype.{}", ty.name(db)),
409 }, 418 },
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index 24c2e196d..1445e41d3 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -425,7 +425,7 @@ export function openDocs(ctx: Ctx): Cmd {
425 const client = ctx.client; 425 const client = ctx.client;
426 const editor = vscode.window.activeTextEditor; 426 const editor = vscode.window.activeTextEditor;
427 if (!editor || !client) { 427 if (!editor || !client) {
428 return 428 return;
429 }; 429 };
430 430
431 const position = editor.selection.active; 431 const position = editor.selection.active;