Skip to content

Commit 91d5d56

Browse files
committed
Auto merge of #55682 - GuillaumeGomez:primitive-sidebar-link-gen, r=QuietMisdreavus
Fixes primitive sidebar link generation Fixes #50746. Fixes #55656. r? @QuietMisdreavus
2 parents 5912a69 + c746ecf commit 91d5d56

File tree

2 files changed

+80
-30
lines changed

2 files changed

+80
-30
lines changed

src/librustdoc/html/render.rs

+57-30
Original file line numberDiff line numberDiff line change
@@ -4249,13 +4249,30 @@ impl<'a> fmt::Display for Sidebar<'a> {
42494249
}
42504250
}
42514251

4252-
fn get_methods(i: &clean::Impl, for_deref: bool) -> Vec<String> {
4252+
fn get_next_url(used_links: &mut FxHashSet<String>, url: String) -> String {
4253+
if used_links.insert(url.clone()) {
4254+
return url;
4255+
}
4256+
let mut add = 1;
4257+
while used_links.insert(format!("{}-{}", url, add)) == false {
4258+
add += 1;
4259+
}
4260+
format!("{}-{}", url, add)
4261+
}
4262+
4263+
fn get_methods(
4264+
i: &clean::Impl,
4265+
for_deref: bool,
4266+
used_links: &mut FxHashSet<String>,
4267+
) -> Vec<String> {
42534268
i.items.iter().filter_map(|item| {
42544269
match item.name {
42554270
// Maybe check with clean::Visibility::Public as well?
42564271
Some(ref name) if !name.is_empty() && item.visibility.is_some() && item.is_method() => {
42574272
if !for_deref || should_render_item(item, false) {
4258-
Some(format!("<a href=\"#method.{name}\">{name}</a>", name = name))
4273+
Some(format!("<a href=\"#{}\">{}</a>",
4274+
get_next_url(used_links, format!("method.{}", name)),
4275+
name))
42594276
} else {
42604277
None
42614278
}
@@ -4285,13 +4302,20 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
42854302
let mut out = String::new();
42864303
let c = cache();
42874304
if let Some(v) = c.impls.get(&it.def_id) {
4288-
let ret = v.iter()
4289-
.filter(|i| i.inner_impl().trait_.is_none())
4290-
.flat_map(|i| get_methods(i.inner_impl(), false))
4291-
.collect::<String>();
4292-
if !ret.is_empty() {
4293-
out.push_str(&format!("<a class=\"sidebar-title\" href=\"#methods\">Methods\
4294-
</a><div class=\"sidebar-links\">{}</div>", ret));
4305+
let mut used_links = FxHashSet::default();
4306+
4307+
{
4308+
let used_links_bor = Rc::new(RefCell::new(&mut used_links));
4309+
let ret = v.iter()
4310+
.filter(|i| i.inner_impl().trait_.is_none())
4311+
.flat_map(move |i| get_methods(i.inner_impl(),
4312+
false,
4313+
&mut used_links_bor.borrow_mut()))
4314+
.collect::<String>();
4315+
if !ret.is_empty() {
4316+
out.push_str(&format!("<a class=\"sidebar-title\" href=\"#methods\">Methods\
4317+
</a><div class=\"sidebar-links\">{}</div>", ret));
4318+
}
42954319
}
42964320

42974321
if v.iter().any(|i| i.inner_impl().trait_.is_some()) {
@@ -4316,35 +4340,38 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
43164340
out.push_str("</a>");
43174341
let ret = impls.iter()
43184342
.filter(|i| i.inner_impl().trait_.is_none())
4319-
.flat_map(|i| get_methods(i.inner_impl(), true))
4343+
.flat_map(|i| get_methods(i.inner_impl(),
4344+
true,
4345+
&mut used_links))
43204346
.collect::<String>();
43214347
out.push_str(&format!("<div class=\"sidebar-links\">{}</div>", ret));
43224348
}
43234349
}
43244350
}
43254351
let format_impls = |impls: Vec<&Impl>| {
43264352
let mut links = FxHashSet::default();
4353+
43274354
impls.iter()
4328-
.filter_map(|i| {
4329-
let is_negative_impl = is_negative_impl(i.inner_impl());
4330-
if let Some(ref i) = i.inner_impl().trait_ {
4331-
let i_display = format!("{:#}", i);
4332-
let out = Escape(&i_display);
4333-
let encoded = small_url_encode(&format!("{:#}", i));
4334-
let generated = format!("<a href=\"#impl-{}\">{}{}</a>",
4335-
encoded,
4336-
if is_negative_impl { "!" } else { "" },
4337-
out);
4338-
if links.insert(generated.clone()) {
4339-
Some(generated)
4340-
} else {
4341-
None
4342-
}
4343-
} else {
4344-
None
4345-
}
4346-
})
4347-
.collect::<String>()
4355+
.filter_map(|i| {
4356+
let is_negative_impl = is_negative_impl(i.inner_impl());
4357+
if let Some(ref i) = i.inner_impl().trait_ {
4358+
let i_display = format!("{:#}", i);
4359+
let out = Escape(&i_display);
4360+
let encoded = small_url_encode(&format!("{:#}", i));
4361+
let generated = format!("<a href=\"#impl-{}\">{}{}</a>",
4362+
encoded,
4363+
if is_negative_impl { "!" } else { "" },
4364+
out);
4365+
if links.insert(generated.clone()) {
4366+
Some(generated)
4367+
} else {
4368+
None
4369+
}
4370+
} else {
4371+
None
4372+
}
4373+
})
4374+
.collect::<String>()
43484375
};
43494376

43504377
let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) = v
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![crate_name = "foo"]
12+
13+
// @has foo/struct.SomeStruct.html '//*[@class="sidebar-links"]/a[@href="#method.some_fn-1"]' \
14+
// "some_fn"
15+
pub struct SomeStruct<T> { _inner: T }
16+
17+
impl SomeStruct<()> {
18+
pub fn some_fn(&self) {}
19+
}
20+
21+
impl SomeStruct<usize> {
22+
pub fn some_fn(&self) {}
23+
}

0 commit comments

Comments
 (0)