7348: Fix broken link in intra-doc r=edwin0cheng a=sasurau4

Fix #5546 
The intra-doc link doesn't work fine for trait associated method.

Co-authored-by: Daiki Ihara <sasurau4@gmail.com>
This commit is contained in:
bors[bot] 2021-01-22 12:29:42 +00:00 committed by GitHub
commit 1b96c79ab5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 68 additions and 3 deletions

View File

@ -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()?,

View File

@ -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<TraitId> {
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,

View File

@ -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()))
}

View File

@ -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() {