Rustdoc-Json: Correcty handle intra-doc-links to items without HTML page
Closes #101531
This commit is contained in:
parent
98f3001eec
commit
2c17099671
@ -510,7 +510,7 @@ pub(crate) fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
|
||||
.get(&self.item_id)
|
||||
.map_or(&[][..], |v| v.as_slice())
|
||||
.iter()
|
||||
.filter_map(|ItemLink { link: s, link_text, did, ref fragment }| {
|
||||
.filter_map(|ItemLink { link: s, link_text, page_id: did, ref fragment }| {
|
||||
debug!(?did);
|
||||
if let Ok((mut href, ..)) = href(*did, cx) {
|
||||
debug!(?href);
|
||||
@ -1134,7 +1134,10 @@ pub(crate) struct ItemLink {
|
||||
/// This may not be the same as `link` if there was a disambiguator
|
||||
/// in an intra-doc link (e.g. \[`fn@f`\])
|
||||
pub(crate) link_text: String,
|
||||
pub(crate) did: DefId,
|
||||
/// The `DefId` of the Item whose **HTML Page** contains the item being
|
||||
/// linked to. This will be different to `item_id` on item's that don't
|
||||
/// have their own page, such as struct fields and enum variants.
|
||||
pub(crate) page_id: DefId,
|
||||
/// The url fragment to append to the link
|
||||
pub(crate) fragment: Option<UrlFragment>,
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
use crate::clean::{self, ItemId};
|
||||
use crate::formats::item_type::ItemType;
|
||||
use crate::json::JsonRenderer;
|
||||
use crate::passes::collect_intra_doc_links::UrlFragment;
|
||||
|
||||
impl JsonRenderer<'_> {
|
||||
pub(super) fn convert_item(&self, item: clean::Item) -> Option<Item> {
|
||||
@ -29,8 +30,14 @@ pub(super) fn convert_item(&self, item: clean::Item) -> Option<Item> {
|
||||
.get(&item.item_id)
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.map(|clean::ItemLink { link, did, .. }| {
|
||||
(link.clone(), from_item_id((*did).into(), self.tcx))
|
||||
.map(|clean::ItemLink { link, page_id, fragment, .. }| {
|
||||
let id = match fragment {
|
||||
Some(UrlFragment::Item(frag_id)) => *frag_id,
|
||||
// FIXME: Pass the `UserWritten` segment to JSON consumer.
|
||||
Some(UrlFragment::UserWritten(_)) | None => *page_id,
|
||||
};
|
||||
|
||||
(link.clone(), from_item_id(id.into(), self.tcx))
|
||||
})
|
||||
.collect();
|
||||
let docs = item.attrs.collapsed_doc_value();
|
||||
|
@ -223,6 +223,9 @@ enum MalformedGenerics {
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub(crate) enum UrlFragment {
|
||||
Item(DefId),
|
||||
/// A part of a page that isn't a rust item.
|
||||
///
|
||||
/// Eg: `[Vector Examples](std::vec::Vec#examples)`
|
||||
UserWritten(String),
|
||||
}
|
||||
|
||||
@ -1127,7 +1130,7 @@ fn resolve_link(
|
||||
Some(ItemLink {
|
||||
link: ori_link.link.clone(),
|
||||
link_text: link_text.clone(),
|
||||
did: res.def_id(self.cx.tcx),
|
||||
page_id: res.def_id(self.cx.tcx),
|
||||
fragment,
|
||||
})
|
||||
}
|
||||
@ -1146,11 +1149,12 @@ fn resolve_link(
|
||||
item,
|
||||
&diag_info,
|
||||
)?;
|
||||
let id = clean::register_res(self.cx, rustc_hir::def::Res::Def(kind, id));
|
||||
|
||||
let page_id = clean::register_res(self.cx, rustc_hir::def::Res::Def(kind, id));
|
||||
Some(ItemLink {
|
||||
link: ori_link.link.clone(),
|
||||
link_text: link_text.clone(),
|
||||
did: id,
|
||||
page_id,
|
||||
fragment,
|
||||
})
|
||||
}
|
||||
|
34
src/test/rustdoc-json/intra-doc-links/non_page.rs
Normal file
34
src/test/rustdoc-json/intra-doc-links/non_page.rs
Normal file
@ -0,0 +1,34 @@
|
||||
// Regression test for <https://github.com/rust-lang/rust/issues/101531>,
|
||||
// where links where to the item who's HTML page had the item linked to.
|
||||
|
||||
//! [`Struct::struct_field`]
|
||||
//! [`Enum::Variant`]
|
||||
//! [`Trait::AssocType`]
|
||||
//! [`Trait::ASSOC_CONST`]
|
||||
//! [`Trait::method`]
|
||||
|
||||
// @set struct_field = "$.index[*][?(@.name=='struct_field')].id"
|
||||
// @set Variant = "$.index[*][?(@.name=='Variant')].id"
|
||||
// @set AssocType = "$.index[*][?(@.name=='AssocType')].id"
|
||||
// @set ASSOC_CONST = "$.index[*][?(@.name=='ASSOC_CONST')].id"
|
||||
// @set method = "$.index[*][?(@.name=='method')].id"
|
||||
|
||||
// @is "$.index[*][?(@.name=='non_page')].links['`Struct::struct_field`']" $struct_field
|
||||
// @is "$.index[*][?(@.name=='non_page')].links['`Enum::Variant`']" $Variant
|
||||
// @is "$.index[*][?(@.name=='non_page')].links['`Trait::AssocType`']" $AssocType
|
||||
// @is "$.index[*][?(@.name=='non_page')].links['`Trait::ASSOC_CONST`']" $ASSOC_CONST
|
||||
// @is "$.index[*][?(@.name=='non_page')].links['`Trait::method`']" $method
|
||||
|
||||
pub struct Struct {
|
||||
pub struct_field: i32,
|
||||
}
|
||||
|
||||
pub enum Enum {
|
||||
Variant(),
|
||||
}
|
||||
|
||||
pub trait Trait {
|
||||
const ASSOC_CONST: i32;
|
||||
type AssocType;
|
||||
fn method();
|
||||
}
|
8
src/test/rustdoc-json/intra-doc-links/user_written.rs
Normal file
8
src/test/rustdoc-json/intra-doc-links/user_written.rs
Normal file
@ -0,0 +1,8 @@
|
||||
//! For motivation, see [the reasons](foo#reasons)
|
||||
|
||||
/// # Reasons
|
||||
/// To test rustdoc json
|
||||
pub fn foo() {}
|
||||
|
||||
// @set foo = "$.index[*][?(@.name=='foo')].id"
|
||||
// @is "$.index[*][?(@.name=='user_written')].links['foo#reasons']" $foo
|
Loading…
Reference in New Issue
Block a user