Skip to content

Commit 2c17099

Browse files
committed
Rustdoc-Json: Correcty handle intra-doc-links to items without HTML page
Closes #101531
1 parent 98f3001 commit 2c17099

File tree

5 files changed

+63
-7
lines changed

5 files changed

+63
-7
lines changed

src/librustdoc/clean/types.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ impl Item {
510510
.get(&self.item_id)
511511
.map_or(&[][..], |v| v.as_slice())
512512
.iter()
513-
.filter_map(|ItemLink { link: s, link_text, did, ref fragment }| {
513+
.filter_map(|ItemLink { link: s, link_text, page_id: did, ref fragment }| {
514514
debug!(?did);
515515
if let Ok((mut href, ..)) = href(*did, cx) {
516516
debug!(?href);
@@ -1134,7 +1134,10 @@ pub(crate) struct ItemLink {
11341134
/// This may not be the same as `link` if there was a disambiguator
11351135
/// in an intra-doc link (e.g. \[`fn@f`\])
11361136
pub(crate) link_text: String,
1137-
pub(crate) did: DefId,
1137+
/// The `DefId` of the Item whose **HTML Page** contains the item being
1138+
/// linked to. This will be different to `item_id` on item's that don't
1139+
/// have their own page, such as struct fields and enum variants.
1140+
pub(crate) page_id: DefId,
11381141
/// The url fragment to append to the link
11391142
pub(crate) fragment: Option<UrlFragment>,
11401143
}

src/librustdoc/json/conversions.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use crate::clean::utils::print_const_expr;
1919
use crate::clean::{self, ItemId};
2020
use crate::formats::item_type::ItemType;
2121
use crate::json::JsonRenderer;
22+
use crate::passes::collect_intra_doc_links::UrlFragment;
2223

2324
impl JsonRenderer<'_> {
2425
pub(super) fn convert_item(&self, item: clean::Item) -> Option<Item> {
@@ -29,8 +30,14 @@ impl JsonRenderer<'_> {
2930
.get(&item.item_id)
3031
.into_iter()
3132
.flatten()
32-
.map(|clean::ItemLink { link, did, .. }| {
33-
(link.clone(), from_item_id((*did).into(), self.tcx))
33+
.map(|clean::ItemLink { link, page_id, fragment, .. }| {
34+
let id = match fragment {
35+
Some(UrlFragment::Item(frag_id)) => *frag_id,
36+
// FIXME: Pass the `UserWritten` segment to JSON consumer.
37+
Some(UrlFragment::UserWritten(_)) | None => *page_id,
38+
};
39+
40+
(link.clone(), from_item_id(id.into(), self.tcx))
3441
})
3542
.collect();
3643
let docs = item.attrs.collapsed_doc_value();

src/librustdoc/passes/collect_intra_doc_links.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,9 @@ enum MalformedGenerics {
223223
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
224224
pub(crate) enum UrlFragment {
225225
Item(DefId),
226+
/// A part of a page that isn't a rust item.
227+
///
228+
/// Eg: `[Vector Examples](std::vec::Vec#examples)`
226229
UserWritten(String),
227230
}
228231

@@ -1127,7 +1130,7 @@ impl LinkCollector<'_, '_> {
11271130
Some(ItemLink {
11281131
link: ori_link.link.clone(),
11291132
link_text: link_text.clone(),
1130-
did: res.def_id(self.cx.tcx),
1133+
page_id: res.def_id(self.cx.tcx),
11311134
fragment,
11321135
})
11331136
}
@@ -1146,11 +1149,12 @@ impl LinkCollector<'_, '_> {
11461149
item,
11471150
&diag_info,
11481151
)?;
1149-
let id = clean::register_res(self.cx, rustc_hir::def::Res::Def(kind, id));
1152+
1153+
let page_id = clean::register_res(self.cx, rustc_hir::def::Res::Def(kind, id));
11501154
Some(ItemLink {
11511155
link: ori_link.link.clone(),
11521156
link_text: link_text.clone(),
1153-
did: id,
1157+
page_id,
11541158
fragment,
11551159
})
11561160
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Regression test for <https://github.com/rust-lang/rust/issues/101531>,
2+
// where links where to the item who's HTML page had the item linked to.
3+
4+
//! [`Struct::struct_field`]
5+
//! [`Enum::Variant`]
6+
//! [`Trait::AssocType`]
7+
//! [`Trait::ASSOC_CONST`]
8+
//! [`Trait::method`]
9+
10+
// @set struct_field = "$.index[*][?(@.name=='struct_field')].id"
11+
// @set Variant = "$.index[*][?(@.name=='Variant')].id"
12+
// @set AssocType = "$.index[*][?(@.name=='AssocType')].id"
13+
// @set ASSOC_CONST = "$.index[*][?(@.name=='ASSOC_CONST')].id"
14+
// @set method = "$.index[*][?(@.name=='method')].id"
15+
16+
// @is "$.index[*][?(@.name=='non_page')].links['`Struct::struct_field`']" $struct_field
17+
// @is "$.index[*][?(@.name=='non_page')].links['`Enum::Variant`']" $Variant
18+
// @is "$.index[*][?(@.name=='non_page')].links['`Trait::AssocType`']" $AssocType
19+
// @is "$.index[*][?(@.name=='non_page')].links['`Trait::ASSOC_CONST`']" $ASSOC_CONST
20+
// @is "$.index[*][?(@.name=='non_page')].links['`Trait::method`']" $method
21+
22+
pub struct Struct {
23+
pub struct_field: i32,
24+
}
25+
26+
pub enum Enum {
27+
Variant(),
28+
}
29+
30+
pub trait Trait {
31+
const ASSOC_CONST: i32;
32+
type AssocType;
33+
fn method();
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
//! For motivation, see [the reasons](foo#reasons)
2+
3+
/// # Reasons
4+
/// To test rustdoc json
5+
pub fn foo() {}
6+
7+
// @set foo = "$.index[*][?(@.name=='foo')].id"
8+
// @is "$.index[*][?(@.name=='user_written')].links['foo#reasons']" $foo

0 commit comments

Comments
 (0)