Skip to content

Commit 6fa521c

Browse files
Fix weird bugs
1 parent 3dafd2c commit 6fa521c

File tree

2 files changed

+60
-31
lines changed

2 files changed

+60
-31
lines changed

src/librustdoc/html/render.rs

+43-31
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ pub use self::ExternalLocation::*;
3737
use std::ascii::AsciiExt;
3838
use std::cell::RefCell;
3939
use std::cmp::Ordering;
40-
use std::collections::BTreeMap;
40+
use std::collections::{BTreeMap, HashSet};
4141
use std::default::Default;
4242
use std::error;
4343
use std::fmt::{self, Display, Formatter, Write as FmtWrite};
@@ -3206,12 +3206,37 @@ fn render_deref_methods(w: &mut fmt::Formatter, cx: &Context, impl_: &Impl,
32063206
}
32073207
}
32083208

3209+
fn should_render_item(item: &clean::Item, deref_mut_: bool) -> bool {
3210+
let self_type_opt = match item.inner {
3211+
clean::MethodItem(ref method) => method.decl.self_type(),
3212+
clean::TyMethodItem(ref method) => method.decl.self_type(),
3213+
_ => None
3214+
};
3215+
3216+
if let Some(self_ty) = self_type_opt {
3217+
let (by_mut_ref, by_box) = match self_ty {
3218+
SelfTy::SelfBorrowed(_, mutability) |
3219+
SelfTy::SelfExplicit(clean::BorrowedRef { mutability, .. }) => {
3220+
(mutability == Mutability::Mutable, false)
3221+
},
3222+
SelfTy::SelfExplicit(clean::ResolvedPath { did, .. }) => {
3223+
(false, Some(did) == cache().owned_box_did)
3224+
},
3225+
_ => (false, false),
3226+
};
3227+
3228+
(deref_mut_ || !by_mut_ref) && !by_box
3229+
} else {
3230+
false
3231+
}
3232+
}
3233+
32093234
fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLink,
32103235
render_mode: RenderMode, outer_version: Option<&str>,
32113236
show_def_docs: bool) -> fmt::Result {
32123237
if render_mode == RenderMode::Normal {
32133238
let id = derive_id(match i.inner_impl().trait_ {
3214-
Some(ref t) => format!("impl-{}", Escape(&format!("{:#}", t))),
3239+
Some(ref t) => format!("impl-{}", small_url_encode(&format!("{:#}", t))),
32153240
None => "impl".to_string(),
32163241
});
32173242
write!(w, "<h3 id='{}' class='impl'><span class='in-band'><code>{}</code>",
@@ -3243,30 +3268,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
32433268

32443269
let render_method_item: bool = match render_mode {
32453270
RenderMode::Normal => true,
3246-
RenderMode::ForDeref { mut_: deref_mut_ } => {
3247-
let self_type_opt = match item.inner {
3248-
clean::MethodItem(ref method) => method.decl.self_type(),
3249-
clean::TyMethodItem(ref method) => method.decl.self_type(),
3250-
_ => None
3251-
};
3252-
3253-
if let Some(self_ty) = self_type_opt {
3254-
let (by_mut_ref, by_box) = match self_ty {
3255-
SelfTy::SelfBorrowed(_, mutability) |
3256-
SelfTy::SelfExplicit(clean::BorrowedRef { mutability, .. }) => {
3257-
(mutability == Mutability::Mutable, false)
3258-
},
3259-
SelfTy::SelfExplicit(clean::ResolvedPath { did, .. }) => {
3260-
(false, Some(did) == cache().owned_box_did)
3261-
},
3262-
_ => (false, false),
3263-
};
3264-
3265-
(deref_mut_ || !by_mut_ref) && !by_box
3266-
} else {
3267-
false
3268-
}
3269-
},
3271+
RenderMode::ForDeref { mut_: deref_mut_ } => should_render_item(&item, deref_mut_),
32703272
};
32713273

32723274
match item.inner {
@@ -3513,12 +3515,16 @@ impl<'a> fmt::Display for Sidebar<'a> {
35133515
}
35143516
}
35153517

3516-
fn get_methods(i: &clean::Impl) -> Vec<String> {
3518+
fn get_methods(i: &clean::Impl, for_deref: bool) -> Vec<String> {
35173519
i.items.iter().filter_map(|item| {
35183520
match item.name {
35193521
// Maybe check with clean::Visibility::Public as well?
35203522
Some(ref name) if !name.is_empty() && item.visibility.is_some() && item.is_method() => {
3521-
Some(format!("<a href=\"#method.{name}\">{name}</a>", name = name))
3523+
if !for_deref || should_render_item(item, false) {
3524+
Some(format!("<a href=\"#method.{name}\">{name}</a>", name = name))
3525+
} else {
3526+
None
3527+
}
35223528
}
35233529
_ => None,
35243530
}
@@ -3546,7 +3552,7 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
35463552
if let Some(v) = c.impls.get(&it.def_id) {
35473553
let ret = v.iter()
35483554
.filter(|i| i.inner_impl().trait_.is_none())
3549-
.flat_map(|i| get_methods(i.inner_impl()))
3555+
.flat_map(|i| get_methods(i.inner_impl(), false))
35503556
.collect::<String>();
35513557
if !ret.is_empty() {
35523558
out.push_str(&format!("<a class=\"sidebar-title\" href=\"#methods\">Methods\
@@ -3574,17 +3580,23 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
35743580
out.push_str("</a>");
35753581
let ret = impls.iter()
35763582
.filter(|i| i.inner_impl().trait_.is_none())
3577-
.flat_map(|i| get_methods(i.inner_impl()))
3583+
.flat_map(|i| get_methods(i.inner_impl(), true))
35783584
.collect::<String>();
35793585
out.push_str(&format!("<div class=\"sidebar-links\">{}</div>", ret));
35803586
}
35813587
}
35823588
}
3589+
let mut links = HashSet::new();
35833590
let ret = v.iter()
35843591
.filter_map(|i| if let Some(ref i) = i.inner_impl().trait_ {
35853592
let out = format!("{:#}", i).replace("<", "&lt;").replace(">", "&gt;");
35863593
let encoded = small_url_encode(&format!("{:#}", i));
3587-
Some(format!("<a href=\"#impl-{:#}\">{}</a>", encoded, out))
3594+
let generated = format!("<a href=\"#impl-{}\">{}</a>", encoded, out);
3595+
if !links.contains(&generated) && links.insert(generated.clone()) {
3596+
Some(generated)
3597+
} else {
3598+
None
3599+
}
35883600
} else {
35893601
None
35903602
})

src/tools/linkchecker/main.rs

+17
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,32 @@ struct FileEntry {
6969

7070
type Cache = HashMap<PathBuf, FileEntry>;
7171

72+
fn small_url_encode(s: &str) -> String {
73+
s.replace("<", "%3C")
74+
.replace(">", "%3E")
75+
.replace(" ", "%20")
76+
.replace("?", "%3F")
77+
.replace("'", "%27")
78+
.replace("&", "%26")
79+
.replace(",", "%2C")
80+
.replace(":", "%3A")
81+
.replace(";", "%3B")
82+
.replace("[", "%5B")
83+
.replace("]", "%5D")
84+
}
85+
7286
impl FileEntry {
7387
fn parse_ids(&mut self, file: &Path, contents: &str, errors: &mut bool) {
7488
if self.ids.is_empty() {
7589
with_attrs_in_source(contents, " id", |fragment, i, _| {
7690
let frag = fragment.trim_left_matches("#").to_owned();
91+
let encoded = small_url_encode(&frag);
7792
if !self.ids.insert(frag) {
7893
*errors = true;
7994
println!("{}:{}: id is not unique: `{}`", file.display(), i, fragment);
8095
}
96+
// Just in case, we also add the encoded id.
97+
self.ids.insert(encoded);
8198
});
8299
}
83100
}

0 commit comments

Comments
 (0)