Skip to content

Commit a27aa8e

Browse files
alexcrichtonquantheory
authored andcommitted
rustdoc: Fix cross-crate macro source links
The source filename for cross crate macros isn't quite right so the normal generated links are invalid. Closes rust-lang#21311
1 parent db2b5b9 commit a27aa8e

File tree

6 files changed

+51
-20
lines changed

6 files changed

+51
-20
lines changed

src/librustdoc/clean/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1270,6 +1270,7 @@ impl Clean<Item> for ast::ImplItem {
12701270
ast::MacImplItem(_) => {
12711271
MacroItem(Macro {
12721272
source: self.span.to_src(cx),
1273+
imported_from: None,
12731274
})
12741275
}
12751276
};
@@ -2557,6 +2558,7 @@ fn resolve_def(cx: &DocContext, id: ast::NodeId) -> Option<ast::DefId> {
25572558
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
25582559
pub struct Macro {
25592560
pub source: String,
2561+
pub imported_from: Option<String>,
25602562
}
25612563

25622564
impl Clean<Item> for doctree::Macro {
@@ -2570,6 +2572,7 @@ impl Clean<Item> for doctree::Macro {
25702572
def_id: ast_util::local_def(self.id),
25712573
inner: MacroItem(Macro {
25722574
source: self.whence.to_src(cx),
2575+
imported_from: self.imported_from.clean(cx),
25732576
}),
25742577
}
25752578
}

src/librustdoc/doctree.rs

+1
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ pub struct Macro {
214214
pub attrs: Vec<ast::Attribute>,
215215
pub whence: Span,
216216
pub stab: Option<attr::Stability>,
217+
pub imported_from: Option<Ident>,
217218
}
218219

219220
pub struct ExternCrate {

src/librustdoc/html/format.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -288,9 +288,9 @@ pub fn href(did: ast::DefId) -> Option<(String, ItemType, Vec<String>)> {
288288
repeat("../").take(loc.len()).collect::<String>()
289289
} else {
290290
match cache.extern_locations[&did.krate] {
291-
render::Remote(ref s) => s.to_string(),
292-
render::Local => repeat("../").take(loc.len()).collect::<String>(),
293-
render::Unknown => return None,
291+
(_, render::Remote(ref s)) => s.to_string(),
292+
(_, render::Local) => repeat("../").take(loc.len()).collect(),
293+
(_, render::Unknown) => return None,
294294
}
295295
};
296296
for component in &fqp[..fqp.len() - 1] {
@@ -379,12 +379,12 @@ fn primitive_link(f: &mut fmt::Formatter,
379379
node: ast::CRATE_NODE_ID,
380380
}];
381381
let loc = match m.extern_locations[&cnum] {
382-
render::Remote(ref s) => Some(s.to_string()),
383-
render::Local => {
382+
(_, render::Remote(ref s)) => Some(s.to_string()),
383+
(_, render::Local) => {
384384
let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len());
385385
Some(repeat("../").take(len).collect::<String>())
386386
}
387-
render::Unknown => None,
387+
(_, render::Unknown) => None,
388388
};
389389
match loc {
390390
Some(root) => {

src/librustdoc/html/render.rs

+37-14
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ pub struct Cache {
193193
pub implementors: HashMap<ast::DefId, Vec<Implementor>>,
194194

195195
/// Cache of where external crate documentation can be found.
196-
pub extern_locations: HashMap<ast::CrateNum, ExternalLocation>,
196+
pub extern_locations: HashMap<ast::CrateNum, (String, ExternalLocation)>,
197197

198198
/// Cache of where documentation for primitives can be found.
199199
pub primitive_locations: HashMap<clean::PrimitiveType, ast::CrateNum>,
@@ -408,7 +408,8 @@ pub fn run(mut krate: clean::Crate,
408408

409409
// Cache where all our extern crates are located
410410
for &(n, ref e) in &krate.externs {
411-
cache.extern_locations.insert(n, extern_location(e, &cx.dst));
411+
cache.extern_locations.insert(n, (e.name.clone(),
412+
extern_location(e, &cx.dst)));
412413
let did = ast::DefId { krate: n, node: ast::CRATE_NODE_ID };
413414
cache.paths.insert(did, (vec![e.name.to_string()], ItemType::Module));
414415
}
@@ -1343,22 +1344,43 @@ impl<'a> Item<'a> {
13431344
/// may happen, for example, with externally inlined items where the source
13441345
/// of their crate documentation isn't known.
13451346
fn href(&self, cx: &Context) -> Option<String> {
1347+
let href = if self.item.source.loline == self.item.source.hiline {
1348+
format!("{}", self.item.source.loline)
1349+
} else {
1350+
format!("{}-{}", self.item.source.loline, self.item.source.hiline)
1351+
};
1352+
1353+
// First check to see if this is an imported macro source. In this case
1354+
// we need to handle it specially as cross-crate inlined macros have...
1355+
// odd locations!
1356+
let imported_macro_from = match self.item.inner {
1357+
clean::MacroItem(ref m) => m.imported_from.as_ref(),
1358+
_ => None,
1359+
};
1360+
if let Some(krate) = imported_macro_from {
1361+
let cache = cache();
1362+
let root = cache.extern_locations.values().find(|&&(ref n, _)| {
1363+
*krate == *n
1364+
}).map(|l| &l.1);
1365+
let root = match root {
1366+
Some(&Remote(ref s)) => s.to_string(),
1367+
Some(&Local) => self.cx.root_path.clone(),
1368+
None | Some(&Unknown) => return None,
1369+
};
1370+
Some(format!("{root}/{krate}/macro.{name}.html?gotomacrosrc=1",
1371+
root = root,
1372+
krate = krate,
1373+
name = self.item.name.as_ref().unwrap()))
1374+
13461375
// If this item is part of the local crate, then we're guaranteed to
13471376
// know the span, so we plow forward and generate a proper url. The url
13481377
// has anchors for the line numbers that we're linking to.
1349-
if ast_util::is_local(self.item.def_id) {
1378+
} else if ast_util::is_local(self.item.def_id) {
13501379
let mut path = Vec::new();
13511380
clean_srcpath(&cx.src_root, Path::new(&self.item.source.filename),
13521381
true, |component| {
13531382
path.push(component.to_string());
13541383
});
1355-
let href = if self.item.source.loline == self.item.source.hiline {
1356-
format!("{}", self.item.source.loline)
1357-
} else {
1358-
format!("{}-{}",
1359-
self.item.source.loline,
1360-
self.item.source.hiline)
1361-
};
13621384
Some(format!("{root}src/{krate}/{path}.html#{href}",
13631385
root = self.cx.root_path,
13641386
krate = self.cx.layout.krate,
@@ -1380,9 +1402,9 @@ impl<'a> Item<'a> {
13801402
let cache = cache();
13811403
let path = &cache.external_paths[&self.item.def_id];
13821404
let root = match cache.extern_locations[&self.item.def_id.krate] {
1383-
Remote(ref s) => s.to_string(),
1384-
Local => self.cx.root_path.clone(),
1385-
Unknown => return None,
1405+
(_, Remote(ref s)) => s.to_string(),
1406+
(_, Local) => self.cx.root_path.clone(),
1407+
(_, Unknown) => return None,
13861408
};
13871409
Some(format!("{root}{path}/{file}?gotosrc={goto}",
13881410
root = root,
@@ -1444,7 +1466,8 @@ impl<'a> fmt::Display for Item<'a> {
14441466
if self.cx.include_sources && !is_primitive {
14451467
match self.href(self.cx) {
14461468
Some(l) => {
1447-
try!(write!(fmt, "<a id='src-{}' href='{}'>[src]</a>",
1469+
try!(write!(fmt, "<a id='src-{}' class='srclink' \
1470+
href='{}'>[src]</a>",
14481471
self.item.def_id.node, l));
14491472
}
14501473
None => {}

src/librustdoc/html/static/main.js

+3
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,9 @@
802802
if (query['gotosrc']) {
803803
window.location = $('#src-' + query['gotosrc']).attr('href');
804804
}
805+
if (query['gotomacrosrc']) {
806+
window.location = $('.srclink').attr('href');
807+
}
805808

806809
$("#expand-all").on("click", function() {
807810
$(".docblock").show();

src/librustdoc/visit_ast.rs

+1
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
398398
name: def.ident,
399399
whence: def.span,
400400
stab: self.stability(def.id),
401+
imported_from: def.imported_from,
401402
}
402403
}
403404
}

0 commit comments

Comments
 (0)