Skip to content

Commit af6cf85

Browse files
committedMar 18, 2015
[rustdoc] Fix source hyperlinks in docs
* rustdoc was doubly appending the file name to the path of where to generate the source files, meanwhile, the [src] hyperlinks were not * Added a flag to rustdoc::html::render::clean_srcpath to ignore the last path component, i.e. the file name itself to prevent the issue * This also avoids creating directories with the same name as source files, and it makes sure the link to `main.css` is correct as well. * Added regression tests to ensure the rustdoc heirarchy of rendered source files remains consistent Fixes #23192
1 parent 94a9506 commit af6cf85

File tree

4 files changed

+99
-5
lines changed

4 files changed

+99
-5
lines changed
 

‎src/librustdoc/html/render.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -692,16 +692,23 @@ fn shortty(item: &clean::Item) -> ItemType {
692692

693693
/// Takes a path to a source file and cleans the path to it. This canonicalizes
694694
/// things like ".." to components which preserve the "top down" hierarchy of a
695-
/// static HTML tree.
695+
/// static HTML tree. Each component in the cleaned path will be passed as an
696+
/// argument to `f`. The very last component of the path (ie the file name) will
697+
/// be passed to `f` if `keep_filename` is true, and ignored otherwise.
696698
// FIXME (#9639): The closure should deal with &[u8] instead of &str
697699
// FIXME (#9639): This is too conservative, rejecting non-UTF-8 paths
698-
fn clean_srcpath<F>(src_root: &Path, p: &Path, mut f: F) where
700+
fn clean_srcpath<F>(src_root: &Path, p: &Path, keep_filename: bool, mut f: F) where
699701
F: FnMut(&str),
700702
{
701703
// make it relative, if possible
702704
let p = p.relative_from(src_root).unwrap_or(p);
703705

704-
for c in p.iter().map(|x| x.to_str().unwrap()) {
706+
let mut iter = p.iter().map(|x| x.to_str().unwrap()).peekable();
707+
while let Some(c) = iter.next() {
708+
if !keep_filename && iter.peek().is_none() {
709+
break;
710+
}
711+
705712
if ".." == c {
706713
f("up");
707714
} else {
@@ -803,7 +810,7 @@ impl<'a> SourceCollector<'a> {
803810
// Create the intermediate directories
804811
let mut cur = self.dst.clone();
805812
let mut root_path = String::from_str("../../");
806-
clean_srcpath(&self.cx.src_root, &p, |component| {
813+
clean_srcpath(&self.cx.src_root, &p, false, |component| {
807814
cur.push(component);
808815
mkdir(&cur).unwrap();
809816
root_path.push_str("../");
@@ -1368,7 +1375,7 @@ impl<'a> Item<'a> {
13681375
if ast_util::is_local(self.item.def_id) {
13691376
let mut path = Vec::new();
13701377
clean_srcpath(&cx.src_root, Path::new(&self.item.source.filename),
1371-
|component| {
1378+
true, |component| {
13721379
path.push(component.to_string());
13731380
});
13741381
let href = if self.item.source.loline == self.item.source.hiline {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-include ../tools.mk
2+
all:
3+
$(HOST_RPATH_ENV) $(RUSTDOC) -w html -o $(TMPDIR)/doc foo.rs
4+
$(HTMLDOCCK) $(TMPDIR)/doc foo.rs
5+
$(HTMLDOCCK) $(TMPDIR)/doc qux/mod.rs
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright 2015 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+
//! Dox
14+
// @has src/foo/foo.rs.html
15+
// @has foo/index.html '//a/@href' '../src/foo/foo.rs.html'
16+
17+
pub mod qux;
18+
19+
// @has foo/bar/index.html '//a/@href' '../../src/foo/foo.rs.html'
20+
pub mod bar {
21+
22+
/// Dox
23+
// @has foo/bar/baz/index.html '//a/@href' '../../../src/foo/foo.rs.html'
24+
pub mod baz {
25+
/// Dox
26+
// @has foo/bar/baz/fn.baz.html '//a/@href' '../../../src/foo/foo.rs.html'
27+
pub fn baz() { }
28+
}
29+
30+
/// Dox
31+
// @has foo/bar/trait.Foobar.html '//a/@href' '../../src/foo/foo.rs.html'
32+
pub trait Foobar { fn dummy(&self) { } }
33+
34+
// @has foo/bar/struct.Foo.html '//a/@href' '../../src/foo/foo.rs.html'
35+
pub struct Foo { x: i32, y: u32 }
36+
37+
// @has foo/bar/fn.prawns.html '//a/@href' '../../src/foo/foo.rs.html'
38+
pub fn prawns((a, b): (i32, u32), Foo { x, y }: Foo) { }
39+
}
40+
41+
/// Dox
42+
// @has foo/fn.modfn.html '//a/@href' '../src/foo/foo.rs.html'
43+
pub fn modfn() { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2015 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+
//! Dox
12+
// @has src/foo/qux/mod.rs.html
13+
// @has foo/qux/index.html '//a/@href' '../../src/foo/qux/mod.rs.html'
14+
15+
// @has foo/qux/bar/index.html '//a/@href' '../../../src/foo/qux/mod.rs.html'
16+
pub mod bar {
17+
18+
/// Dox
19+
// @has foo/qux/bar/baz/index.html '//a/@href' '../../../../src/foo/qux/mod.rs.html'
20+
pub mod baz {
21+
/// Dox
22+
// @has foo/qux/bar/baz/fn.baz.html '//a/@href' '../../../../src/foo/qux/mod.rs.html'
23+
pub fn baz() { }
24+
}
25+
26+
/// Dox
27+
// @has foo/qux/bar/trait.Foobar.html '//a/@href' '../../../src/foo/qux/mod.rs.html'
28+
pub trait Foobar { fn dummy(&self) { } }
29+
30+
// @has foo/qux/bar/struct.Foo.html '//a/@href' '../../../src/foo/qux/mod.rs.html'
31+
pub struct Foo { x: i32, y: u32 }
32+
33+
// @has foo/qux/bar/fn.prawns.html '//a/@href' '../../../src/foo/qux/mod.rs.html'
34+
pub fn prawns((a, b): (i32, u32), Foo { x, y }: Foo) { }
35+
}
36+
37+
/// Dox
38+
// @has foo/qux/fn.modfn.html '//a/@href' '../../src/foo/qux/mod.rs.html'
39+
pub fn modfn() { }

0 commit comments

Comments
 (0)
Please sign in to comment.