diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index f97470dbaed75..81daac7b90f0d 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -692,16 +692,23 @@ fn shortty(item: &clean::Item) -> ItemType { /// Takes a path to a source file and cleans the path to it. This canonicalizes /// things like ".." to components which preserve the "top down" hierarchy of a -/// static HTML tree. +/// static HTML tree. Each component in the cleaned path will be passed as an +/// argument to `f`. The very last component of the path (ie the file name) will +/// be passed to `f` if `keep_filename` is true, and ignored otherwise. // FIXME (#9639): The closure should deal with &[u8] instead of &str // FIXME (#9639): This is too conservative, rejecting non-UTF-8 paths -fn clean_srcpath(src_root: &Path, p: &Path, mut f: F) where +fn clean_srcpath(src_root: &Path, p: &Path, keep_filename: bool, mut f: F) where F: FnMut(&str), { // make it relative, if possible let p = p.relative_from(src_root).unwrap_or(p); - for c in p.iter().map(|x| x.to_str().unwrap()) { + let mut iter = p.iter().map(|x| x.to_str().unwrap()).peekable(); + while let Some(c) = iter.next() { + if !keep_filename && iter.peek().is_none() { + break; + } + if ".." == c { f("up"); } else { @@ -803,7 +810,7 @@ impl<'a> SourceCollector<'a> { // Create the intermediate directories let mut cur = self.dst.clone(); let mut root_path = String::from_str("../../"); - clean_srcpath(&self.cx.src_root, &p, |component| { + clean_srcpath(&self.cx.src_root, &p, false, |component| { cur.push(component); mkdir(&cur).unwrap(); root_path.push_str("../"); @@ -1368,7 +1375,7 @@ impl<'a> Item<'a> { if ast_util::is_local(self.item.def_id) { let mut path = Vec::new(); clean_srcpath(&cx.src_root, Path::new(&self.item.source.filename), - |component| { + true, |component| { path.push(component.to_string()); }); let href = if self.item.source.loline == self.item.source.hiline { diff --git a/src/test/run-make/rustdoc-src-links/Makefile b/src/test/run-make/rustdoc-src-links/Makefile new file mode 100644 index 0000000000000..419603e82f715 --- /dev/null +++ b/src/test/run-make/rustdoc-src-links/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk +all: + $(HOST_RPATH_ENV) $(RUSTDOC) -w html -o $(TMPDIR)/doc foo.rs + $(HTMLDOCCK) $(TMPDIR)/doc foo.rs + $(HTMLDOCCK) $(TMPDIR)/doc qux/mod.rs diff --git a/src/test/run-make/rustdoc-src-links/foo.rs b/src/test/run-make/rustdoc-src-links/foo.rs new file mode 100644 index 0000000000000..9a964f1125252 --- /dev/null +++ b/src/test/run-make/rustdoc-src-links/foo.rs @@ -0,0 +1,43 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "foo"] + +//! Dox +// @has src/foo/foo.rs.html +// @has foo/index.html '//a/@href' '../src/foo/foo.rs.html' + +pub mod qux; + +// @has foo/bar/index.html '//a/@href' '../../src/foo/foo.rs.html' +pub mod bar { + + /// Dox + // @has foo/bar/baz/index.html '//a/@href' '../../../src/foo/foo.rs.html' + pub mod baz { + /// Dox + // @has foo/bar/baz/fn.baz.html '//a/@href' '../../../src/foo/foo.rs.html' + pub fn baz() { } + } + + /// Dox + // @has foo/bar/trait.Foobar.html '//a/@href' '../../src/foo/foo.rs.html' + pub trait Foobar { fn dummy(&self) { } } + + // @has foo/bar/struct.Foo.html '//a/@href' '../../src/foo/foo.rs.html' + pub struct Foo { x: i32, y: u32 } + + // @has foo/bar/fn.prawns.html '//a/@href' '../../src/foo/foo.rs.html' + pub fn prawns((a, b): (i32, u32), Foo { x, y }: Foo) { } +} + +/// Dox +// @has foo/fn.modfn.html '//a/@href' '../src/foo/foo.rs.html' +pub fn modfn() { } diff --git a/src/test/run-make/rustdoc-src-links/qux/mod.rs b/src/test/run-make/rustdoc-src-links/qux/mod.rs new file mode 100644 index 0000000000000..9b1563d32ac71 --- /dev/null +++ b/src/test/run-make/rustdoc-src-links/qux/mod.rs @@ -0,0 +1,39 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Dox +// @has src/foo/qux/mod.rs.html +// @has foo/qux/index.html '//a/@href' '../../src/foo/qux/mod.rs.html' + +// @has foo/qux/bar/index.html '//a/@href' '../../../src/foo/qux/mod.rs.html' +pub mod bar { + + /// Dox + // @has foo/qux/bar/baz/index.html '//a/@href' '../../../../src/foo/qux/mod.rs.html' + pub mod baz { + /// Dox + // @has foo/qux/bar/baz/fn.baz.html '//a/@href' '../../../../src/foo/qux/mod.rs.html' + pub fn baz() { } + } + + /// Dox + // @has foo/qux/bar/trait.Foobar.html '//a/@href' '../../../src/foo/qux/mod.rs.html' + pub trait Foobar { fn dummy(&self) { } } + + // @has foo/qux/bar/struct.Foo.html '//a/@href' '../../../src/foo/qux/mod.rs.html' + pub struct Foo { x: i32, y: u32 } + + // @has foo/qux/bar/fn.prawns.html '//a/@href' '../../../src/foo/qux/mod.rs.html' + pub fn prawns((a, b): (i32, u32), Foo { x, y }: Foo) { } +} + +/// Dox +// @has foo/qux/fn.modfn.html '//a/@href' '../../src/foo/qux/mod.rs.html' +pub fn modfn() { }