Skip to content

Commit 08fb9aa

Browse files
committed
rustdoc: Use relative paths in source renders.
Before: doc/src/collections/home/lifthrasiir/git/rust/src/libcollections/vec.rs.html After: doc/src/collections/vec.rs.html If the source code is in the parent dirs relative to the crate root, `..` is replaced with `up` as expected. Any other error like non-UTF-8 paths or drive-relative paths falls back to the absolute path. There might be a way to improve on false negatives, but this alone should be enough for fixing #18370.
1 parent 09f04bf commit 08fb9aa

File tree

2 files changed

+17
-5
lines changed

2 files changed

+17
-5
lines changed

src/librustdoc/clean/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ use std::rc::Rc;
5353
use std::u32;
5454
use std::str::Str as StrTrait; // Conflicts with Str variant
5555
use std::char::Char as CharTrait; // Conflicts with Char variant
56+
use std::path::Path as FsPath; // Conflicts with Path struct
5657

5758
use core::DocContext;
5859
use doctree;
@@ -115,6 +116,7 @@ impl<T: Clean<U>, U> Clean<Vec<U>> for syntax::owned_slice::OwnedSlice<T> {
115116
#[deriving(Clone, Encodable, Decodable)]
116117
pub struct Crate {
117118
pub name: String,
119+
pub src: FsPath,
118120
pub module: Option<Item>,
119121
pub externs: Vec<(ast::CrateNum, ExternalCrate)>,
120122
pub primitives: Vec<PrimitiveType>,
@@ -194,6 +196,7 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
194196

195197
Crate {
196198
name: name.to_string(),
199+
src: cx.src.clone(),
197200
module: Some(module),
198201
externs: externs,
199202
primitives: primitives,

src/librustdoc/html/render.rs

+14-5
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ pub struct Context {
8383
/// String representation of how to get back to the root path of the 'doc/'
8484
/// folder in terms of a relative URL.
8585
pub root_path: String,
86+
/// The path to the crate root source minus the file name.
87+
/// Used for simplifying paths to the highlighted source code files.
88+
pub src_root: Path,
8689
/// The current destination folder of where HTML artifacts should be placed.
8790
/// This changes as the context descends into the module hierarchy.
8891
pub dst: Path,
@@ -249,6 +252,7 @@ pub fn run(mut krate: clean::Crate,
249252
passes: HashSet<String>) -> io::IoResult<()> {
250253
let mut cx = Context {
251254
dst: dst,
255+
src_root: krate.src.dir_path(),
252256
passes: passes,
253257
current: Vec::new(),
254258
root_path: String::new(),
@@ -642,8 +646,13 @@ fn mkdir(path: &Path) -> io::IoResult<()> {
642646
/// things like ".." to components which preserve the "top down" hierarchy of a
643647
/// static HTML tree.
644648
// FIXME (#9639): The closure should deal with &[u8] instead of &str
645-
fn clean_srcpath(src: &[u8], f: |&str|) {
649+
// FIXME (#9639): This is too conservative, rejecting non-UTF-8 paths
650+
fn clean_srcpath(src_root: &Path, src: &[u8], f: |&str|) {
646651
let p = Path::new(src);
652+
653+
// make it relative, if possible
654+
let p = p.path_relative_from(src_root).unwrap_or(p);
655+
647656
if p.as_vec() != b"." {
648657
for c in p.str_components().map(|x|x.unwrap()) {
649658
if ".." == c {
@@ -749,7 +758,7 @@ impl<'a> SourceCollector<'a> {
749758
// Create the intermediate directories
750759
let mut cur = self.dst.clone();
751760
let mut root_path = String::from_str("../../");
752-
clean_srcpath(p.dirname(), |component| {
761+
clean_srcpath(&self.cx.src_root, p.dirname(), |component| {
753762
cur.push(component);
754763
mkdir(&cur).unwrap();
755764
root_path.push_str("../");
@@ -1299,13 +1308,13 @@ impl<'a> Item<'a> {
12991308
/// If `None` is returned, then a source link couldn't be generated. This
13001309
/// may happen, for example, with externally inlined items where the source
13011310
/// of their crate documentation isn't known.
1302-
fn href(&self) -> Option<String> {
1311+
fn href(&self, cx: &Context) -> Option<String> {
13031312
// If this item is part of the local crate, then we're guaranteed to
13041313
// know the span, so we plow forward and generate a proper url. The url
13051314
// has anchors for the line numbers that we're linking to.
13061315
if ast_util::is_local(self.item.def_id) {
13071316
let mut path = Vec::new();
1308-
clean_srcpath(self.item.source.filename.as_bytes(), |component| {
1317+
clean_srcpath(&cx.src_root, self.item.source.filename.as_bytes(), |component| {
13091318
path.push(component.to_string());
13101319
});
13111320
let href = if self.item.source.loline == self.item.source.hiline {
@@ -1412,7 +1421,7 @@ impl<'a> fmt::Show for Item<'a> {
14121421
// this page, and this link will be auto-clicked. The `id` attribute is
14131422
// used to find the link to auto-click.
14141423
if self.cx.include_sources && !is_primitive {
1415-
match self.href() {
1424+
match self.href(self.cx) {
14161425
Some(l) => {
14171426
try!(write!(fmt, "<a id='src-{}' href='{}'>[src]</a>",
14181427
self.item.def_id.node, l));

0 commit comments

Comments
 (0)