From f5b97e52c97fe6cc12aba3587c12e37b403deea4 Mon Sep 17 00:00:00 2001 From: Daiki Ihara Date: Wed, 20 Jan 2021 00:43:06 +0900 Subject: Fix broken link in intra-doc --- crates/hir/src/attrs.rs | 6 ++++++ crates/hir_def/src/resolver.rs | 13 +++++++++++++ crates/ide/src/doc_links.rs | 23 ++++++++++++++++++++--- crates/ide/src/hover.rs | 29 +++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 3 deletions(-) (limited to 'crates') diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index 99fb65bac..9e6a3e155 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs @@ -2,6 +2,7 @@ use hir_def::{ attr::{Attrs, Documentation}, path::ModPath, + per_ns::PerNs, resolver::HasResolver, AttrDefId, GenericParamId, ModuleDefId, }; @@ -112,6 +113,11 @@ fn resolve_doc_path( let path = ast::Path::parse(link).ok()?; let modpath = ModPath::from_src(path, &Hygiene::new_unhygienic()).unwrap(); let resolved = resolver.resolve_module_path_in_items(db.upcast(), &modpath); + if resolved == PerNs::none() { + if let Some(trait_id) = resolver.resolve_module_path_in_trait_items(db.upcast(), &modpath) { + return Some(ModuleDefId::TraitId(trait_id)); + }; + } let def = match ns { Some(Namespace::Types) => resolved.take_types()?, Some(Namespace::Values) => resolved.take_values()?, diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index d48029b7d..b2f577649 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs @@ -146,6 +146,19 @@ impl Resolver { self.resolve_module_path(db, path, BuiltinShadowMode::Module) } + pub fn resolve_module_path_in_trait_items( + &self, + db: &dyn DefDatabase, + path: &ModPath, + ) -> Option { + let (item_map, module) = self.module_scope()?; + let (module_res, ..) = item_map.resolve_path(db, module, &path, BuiltinShadowMode::Module); + match module_res.take_types()? { + ModuleDefId::TraitId(it) => Some(it), + _ => None, + } + } + pub fn resolve_path_in_type_ns( &self, db: &dyn DefDatabase, diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs index 1f08d7810..730e0dd0a 100644 --- a/crates/ide/src/doc_links.rs +++ b/crates/ide/src/doc_links.rs @@ -221,14 +221,31 @@ fn rewrite_intra_doc_link( }?; let krate = resolved.module(db)?.krate(); let canonical_path = resolved.canonical_path(db)?; - let new_target = get_doc_url(db, &krate)? + let mut new_url = get_doc_url(db, &krate)? .join(&format!("{}/", krate.display_name(db)?)) .ok()? .join(&canonical_path.replace("::", "/")) .ok()? .join(&get_symbol_filename(db, &resolved)?) - .ok()? - .into_string(); + .ok()?; + + if let ModuleDef::Trait(t) = resolved { + let items = t.items(db); + if let Some(field_or_assoc_item) = items.iter().find_map(|assoc_item| { + if let Some(name) = assoc_item.name(db) { + if link.to_string() == format!("{}::{}", canonical_path, name) { + return Some(FieldOrAssocItem::AssocItem(*assoc_item)); + } + } + None + }) { + if let Some(fragment) = get_symbol_fragment(db, &field_or_assoc_item) { + new_url = new_url.join(&fragment).ok()?; + } + }; + } + + let new_target = new_url.into_string(); let new_title = strip_prefixes_suffixes(title); Some((new_target, new_title.to_string())) } diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index ec1631486..d47a4cb0f 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -1826,6 +1826,35 @@ pub struct B$0ar "#]], ); } + #[test] + fn test_hover_intra_link_reference_to_trait_method() { + check( + r#" +pub trait Foo { + fn buzz() -> usize; +} +/// [Foo][buzz] +/// +/// [buzz]: Foo::buzz +pub struct B$0ar +"#, + expect![[r#" + *Bar* + + ```rust + test + ``` + + ```rust + pub struct Bar + ``` + + --- + + [Foo](https://docs.rs/test/*/test/trait.Foo.html#tymethod.buzz) + "#]], + ); + } #[test] fn test_hover_external_url() { -- cgit v1.2.3