aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/code_model.rs39
-rw-r--r--crates/hir/src/lib.rs4
-rw-r--r--crates/ide/src/doc_links.rs35
-rw-r--r--crates/ide/src/hover.rs2
4 files changed, 27 insertions, 53 deletions
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index 9989b9b56..650b4fa40 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -35,7 +35,7 @@ use hir_ty::{
35 traits::SolutionVariables, 35 traits::SolutionVariables,
36 ApplicationTy, BoundVar, CallableDefId, Canonical, DebruijnIndex, FnSig, GenericPredicate, 36 ApplicationTy, BoundVar, CallableDefId, Canonical, DebruijnIndex, FnSig, GenericPredicate,
37 InEnvironment, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, Ty, 37 InEnvironment, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, Ty,
38 TyDefId, TyKind, TypeCtor, TyLoweringContext, 38 TyDefId, TyKind, TypeCtor,
39}; 39};
40use rustc_hash::FxHashSet; 40use rustc_hash::FxHashSet;
41use stdx::impl_from; 41use stdx::impl_from;
@@ -186,15 +186,6 @@ impl_from!(
186 for ModuleDef 186 for ModuleDef
187); 187);
188 188
189impl From<MethodOwner> for ModuleDef {
190 fn from(mowner: MethodOwner) -> Self {
191 match mowner {
192 MethodOwner::Trait(t) => t.into(),
193 MethodOwner::Adt(t) => t.into(),
194 }
195 }
196}
197
198impl From<VariantDef> for ModuleDef { 189impl From<VariantDef> for ModuleDef {
199 fn from(var: VariantDef) -> Self { 190 fn from(var: VariantDef) -> Self {
200 match var { 191 match var {
@@ -778,36 +769,8 @@ impl Function {
778 pub fn has_body(self, db: &dyn HirDatabase) -> bool { 769 pub fn has_body(self, db: &dyn HirDatabase) -> bool {
779 db.function_data(self.id).has_body 770 db.function_data(self.id).has_body
780 } 771 }
781
782 /// If this function is a method, the trait or type where it is declared.
783 pub fn method_owner(self, db: &dyn HirDatabase) -> Option<MethodOwner> {
784 match self.as_assoc_item(db).map(|assoc| assoc.container(db)) {
785 Some(AssocItemContainer::Trait(t)) => Some(t.into()),
786 Some(AssocItemContainer::ImplDef(imp)) => {
787 let resolver = ModuleId::from(imp.module(db)).resolver(db.upcast());
788 let ctx = TyLoweringContext::new(db, &resolver);
789 let adt = Ty::from_hir(
790 &ctx,
791 &imp.target_trait(db).unwrap_or_else(|| imp.target_type(db)),
792 )
793 .as_adt()
794 .map(|t| t.0)
795 .unwrap();
796 Some(Adt::from(adt).into())
797 }
798 None => None,
799 }
800 }
801} 772}
802 773
803#[derive(Debug)]
804pub enum MethodOwner {
805 Trait(Trait),
806 Adt(Adt),
807}
808
809impl_from!(Trait, Adt for MethodOwner);
810
811// Note: logically, this belongs to `hir_ty`, but we are not using it there yet. 774// Note: logically, this belongs to `hir_ty`, but we are not using it there yet.
812pub enum Access { 775pub enum Access {
813 Shared, 776 Shared,
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 687abe6ca..4094a76cb 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, MethodOwner, Module, ModuleDef, 38 GenericDef, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, ScopeDef, Static,
39 ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility, 39 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/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs
index 5ef708647..06af36b73 100644
--- a/crates/ide/src/doc_links.rs
+++ b/crates/ide/src/doc_links.rs
@@ -3,13 +3,14 @@
3use std::iter::once; 3use std::iter::once;
4 4
5use itertools::Itertools; 5use itertools::Itertools;
6use pulldown_cmark_to_cmark::{cmark_with_options, Options as CmarkOptions};
7use pulldown_cmark::{CowStr, Event, LinkType, Options, Parser, Tag}; 6use pulldown_cmark::{CowStr, Event, LinkType, Options, Parser, Tag};
7use pulldown_cmark_to_cmark::{cmark_with_options, Options as CmarkOptions};
8use url::Url; 8use url::Url;
9 9
10use hir::{ 10use hir::{
11 db::{DefDatabase, HirDatabase}, 11 db::{DefDatabase, HirDatabase},
12 Adt, AsName, AssocItem, Crate, Field, HasAttrs, ItemInNs, ModuleDef, AssocItemContainer, AsAssocItem 12 Adt, AsAssocItem, AsName, AssocItem, AssocItemContainer, Crate, Field, HasAttrs, ItemInNs,
13 ModuleDef,
13}; 14};
14use ide_db::{ 15use ide_db::{
15 defs::{classify_name, classify_name_ref, Definition}, 16 defs::{classify_name, classify_name_ref, Definition},
@@ -97,18 +98,23 @@ pub fn remove_links(markdown: &str) -> String {
97// BUG: For Option::Some 98// BUG: For Option::Some
98// Returns https://doc.rust-lang.org/nightly/core/prelude/v1/enum.Option.html#variant.Some 99// Returns https://doc.rust-lang.org/nightly/core/prelude/v1/enum.Option.html#variant.Some
99// Instead of https://doc.rust-lang.org/nightly/core/option/enum.Option.html 100// Instead of https://doc.rust-lang.org/nightly/core/option/enum.Option.html
100// This could be worked around by turning the `EnumVariant` into `Enum` before attempting resolution, 101//
101// but it's really just working around the problem. Ideally we need to implement a slightly different 102// This should cease to be a problem if RFC2988 (Stable Rustdoc URLs) is implemented
102// version of import map which follows the same process as rustdoc. Otherwise there'll always be some 103// https://github.com/rust-lang/rfcs/pull/2988
103// edge cases where we select the wrong import path.
104fn get_doc_link(db: &RootDatabase, definition: Definition) -> Option<String> { 104fn get_doc_link(db: &RootDatabase, definition: Definition) -> Option<String> {
105 // Get the outermost definition for the moduledef. This is used to resolve the public path to the type, 105 // Get the outermost definition for the moduledef. This is used to resolve the public path to the type,
106 // then we can join the method, field, etc onto it if required. 106 // then we can join the method, field, etc onto it if required.
107 let target_def: ModuleDef = match definition { 107 let target_def: ModuleDef = match definition {
108 Definition::ModuleDef(moddef) => match moddef { 108 Definition::ModuleDef(moddef) => match moddef {
109 ModuleDef::Function(f) => { 109 ModuleDef::Function(f) => f
110 f.method_owner(db).map(|mowner| mowner.into()).unwrap_or_else(|| f.clone().into()) 110 .as_assoc_item(db)
111 } 111 .and_then(|assoc| match assoc.container(db) {
112 AssocItemContainer::Trait(t) => Some(t.into()),
113 AssocItemContainer::ImplDef(impld) => {
114 impld.target_ty(db).as_adt().map(|adt| adt.into())
115 }
116 })
117 .unwrap_or_else(|| f.clone().into()),
112 moddef => moddef, 118 moddef => moddef,
113 }, 119 },
114 Definition::Field(f) => f.parent_def(db).into(), 120 Definition::Field(f) => f.parent_def(db).into(),
@@ -211,7 +217,10 @@ fn rewrite_url_link(db: &RootDatabase, def: ModuleDef, target: &str) -> Option<S
211} 217}
212 218
213/// Retrieve a link to documentation for the given symbol. 219/// Retrieve a link to documentation for the given symbol.
214pub(crate) fn external_docs(db: &RootDatabase, position: &FilePosition) -> Option<DocumentationLink> { 220pub(crate) fn external_docs(
221 db: &RootDatabase,
222 position: &FilePosition,
223) -> Option<DocumentationLink> {
215 let sema = Semantics::new(db); 224 let sema = Semantics::new(db);
216 let file = sema.parse(position.file_id).syntax().clone(); 225 let file = sema.parse(position.file_id).syntax().clone();
217 let token = pick_best(file.token_at_offset(position.offset))?; 226 let token = pick_best(file.token_at_offset(position.offset))?;
@@ -392,8 +401,10 @@ fn get_symbol_fragment(db: &dyn HirDatabase, field_or_assoc: &FieldOrAssocItem)
392 FieldOrAssocItem::Field(field) => format!("#structfield.{}", field.name(db)), 401 FieldOrAssocItem::Field(field) => format!("#structfield.{}", field.name(db)),
393 FieldOrAssocItem::AssocItem(assoc) => match assoc { 402 FieldOrAssocItem::AssocItem(assoc) => match assoc {
394 AssocItem::Function(function) => { 403 AssocItem::Function(function) => {
395 let is_trait_method = 404 let is_trait_method = matches!(
396 matches!(function.as_assoc_item(db).map(|assoc| assoc.container(db)), Some(AssocItemContainer::Trait(..))); 405 function.as_assoc_item(db).map(|assoc| assoc.container(db)),
406 Some(AssocItemContainer::Trait(..))
407 );
397 // This distinction may get more complicated when specialisation is available. 408 // This distinction may get more complicated when specialisation is available.
398 // Rustdoc makes this decision based on whether a method 'has defaultness'. 409 // Rustdoc makes this decision based on whether a method 'has defaultness'.
399 // Currently this is only the case for provided trait methods. 410 // Currently this is only the case for provided trait methods.
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index a53359d03..6290b35bd 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -14,8 +14,8 @@ use test_utils::mark;
14 14
15use crate::{ 15use crate::{
16 display::{macro_label, ShortLabel, ToNav, TryToNav}, 16 display::{macro_label, ShortLabel, ToNav, TryToNav},
17 markdown_remove::remove_markdown,
18 doc_links::{remove_links, rewrite_links}, 17 doc_links::{remove_links, rewrite_links},
18 markdown_remove::remove_markdown,
19 markup::Markup, 19 markup::Markup,
20 runnables::runnable, 20 runnables::runnable,
21 FileId, FilePosition, NavigationTarget, RangeInfo, Runnable, 21 FileId, FilePosition, NavigationTarget, RangeInfo, Runnable,