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 #21311
This commit is contained in:
parent
0a46933c4d
commit
8fb31f75c9
6 changed files with 51 additions and 20 deletions
|
@ -1270,6 +1270,7 @@ impl Clean<Item> for ast::ImplItem {
|
||||||
ast::MacImplItem(_) => {
|
ast::MacImplItem(_) => {
|
||||||
MacroItem(Macro {
|
MacroItem(Macro {
|
||||||
source: self.span.to_src(cx),
|
source: self.span.to_src(cx),
|
||||||
|
imported_from: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -2557,6 +2558,7 @@ fn resolve_def(cx: &DocContext, id: ast::NodeId) -> Option<ast::DefId> {
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||||
pub struct Macro {
|
pub struct Macro {
|
||||||
pub source: String,
|
pub source: String,
|
||||||
|
pub imported_from: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clean<Item> for doctree::Macro {
|
impl Clean<Item> for doctree::Macro {
|
||||||
|
@ -2570,6 +2572,7 @@ impl Clean<Item> for doctree::Macro {
|
||||||
def_id: ast_util::local_def(self.id),
|
def_id: ast_util::local_def(self.id),
|
||||||
inner: MacroItem(Macro {
|
inner: MacroItem(Macro {
|
||||||
source: self.whence.to_src(cx),
|
source: self.whence.to_src(cx),
|
||||||
|
imported_from: self.imported_from.clean(cx),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,6 +214,7 @@ pub struct Macro {
|
||||||
pub attrs: Vec<ast::Attribute>,
|
pub attrs: Vec<ast::Attribute>,
|
||||||
pub whence: Span,
|
pub whence: Span,
|
||||||
pub stab: Option<attr::Stability>,
|
pub stab: Option<attr::Stability>,
|
||||||
|
pub imported_from: Option<Ident>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ExternCrate {
|
pub struct ExternCrate {
|
||||||
|
|
|
@ -288,9 +288,9 @@ pub fn href(did: ast::DefId) -> Option<(String, ItemType, Vec<String>)> {
|
||||||
repeat("../").take(loc.len()).collect::<String>()
|
repeat("../").take(loc.len()).collect::<String>()
|
||||||
} else {
|
} else {
|
||||||
match cache.extern_locations[&did.krate] {
|
match cache.extern_locations[&did.krate] {
|
||||||
render::Remote(ref s) => s.to_string(),
|
(_, render::Remote(ref s)) => s.to_string(),
|
||||||
render::Local => repeat("../").take(loc.len()).collect::<String>(),
|
(_, render::Local) => repeat("../").take(loc.len()).collect(),
|
||||||
render::Unknown => return None,
|
(_, render::Unknown) => return None,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
for component in &fqp[..fqp.len() - 1] {
|
for component in &fqp[..fqp.len() - 1] {
|
||||||
|
@ -379,12 +379,12 @@ fn primitive_link(f: &mut fmt::Formatter,
|
||||||
node: ast::CRATE_NODE_ID,
|
node: ast::CRATE_NODE_ID,
|
||||||
}];
|
}];
|
||||||
let loc = match m.extern_locations[&cnum] {
|
let loc = match m.extern_locations[&cnum] {
|
||||||
render::Remote(ref s) => Some(s.to_string()),
|
(_, render::Remote(ref s)) => Some(s.to_string()),
|
||||||
render::Local => {
|
(_, render::Local) => {
|
||||||
let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len());
|
let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len());
|
||||||
Some(repeat("../").take(len).collect::<String>())
|
Some(repeat("../").take(len).collect::<String>())
|
||||||
}
|
}
|
||||||
render::Unknown => None,
|
(_, render::Unknown) => None,
|
||||||
};
|
};
|
||||||
match loc {
|
match loc {
|
||||||
Some(root) => {
|
Some(root) => {
|
||||||
|
|
|
@ -193,7 +193,7 @@ pub struct Cache {
|
||||||
pub implementors: HashMap<ast::DefId, Vec<Implementor>>,
|
pub implementors: HashMap<ast::DefId, Vec<Implementor>>,
|
||||||
|
|
||||||
/// Cache of where external crate documentation can be found.
|
/// Cache of where external crate documentation can be found.
|
||||||
pub extern_locations: HashMap<ast::CrateNum, ExternalLocation>,
|
pub extern_locations: HashMap<ast::CrateNum, (String, ExternalLocation)>,
|
||||||
|
|
||||||
/// Cache of where documentation for primitives can be found.
|
/// Cache of where documentation for primitives can be found.
|
||||||
pub primitive_locations: HashMap<clean::PrimitiveType, ast::CrateNum>,
|
pub primitive_locations: HashMap<clean::PrimitiveType, ast::CrateNum>,
|
||||||
|
@ -408,7 +408,8 @@ pub fn run(mut krate: clean::Crate,
|
||||||
|
|
||||||
// Cache where all our extern crates are located
|
// Cache where all our extern crates are located
|
||||||
for &(n, ref e) in &krate.externs {
|
for &(n, ref e) in &krate.externs {
|
||||||
cache.extern_locations.insert(n, extern_location(e, &cx.dst));
|
cache.extern_locations.insert(n, (e.name.clone(),
|
||||||
|
extern_location(e, &cx.dst)));
|
||||||
let did = ast::DefId { krate: n, node: ast::CRATE_NODE_ID };
|
let did = ast::DefId { krate: n, node: ast::CRATE_NODE_ID };
|
||||||
cache.paths.insert(did, (vec![e.name.to_string()], ItemType::Module));
|
cache.paths.insert(did, (vec![e.name.to_string()], ItemType::Module));
|
||||||
}
|
}
|
||||||
|
@ -1343,22 +1344,43 @@ impl<'a> Item<'a> {
|
||||||
/// may happen, for example, with externally inlined items where the source
|
/// may happen, for example, with externally inlined items where the source
|
||||||
/// of their crate documentation isn't known.
|
/// of their crate documentation isn't known.
|
||||||
fn href(&self, cx: &Context) -> Option<String> {
|
fn href(&self, cx: &Context) -> Option<String> {
|
||||||
|
let href = if self.item.source.loline == self.item.source.hiline {
|
||||||
|
format!("{}", self.item.source.loline)
|
||||||
|
} else {
|
||||||
|
format!("{}-{}", self.item.source.loline, self.item.source.hiline)
|
||||||
|
};
|
||||||
|
|
||||||
|
// First check to see if this is an imported macro source. In this case
|
||||||
|
// we need to handle it specially as cross-crate inlined macros have...
|
||||||
|
// odd locations!
|
||||||
|
let imported_macro_from = match self.item.inner {
|
||||||
|
clean::MacroItem(ref m) => m.imported_from.as_ref(),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
if let Some(krate) = imported_macro_from {
|
||||||
|
let cache = cache();
|
||||||
|
let root = cache.extern_locations.values().find(|&&(ref n, _)| {
|
||||||
|
*krate == *n
|
||||||
|
}).map(|l| &l.1);
|
||||||
|
let root = match root {
|
||||||
|
Some(&Remote(ref s)) => s.to_string(),
|
||||||
|
Some(&Local) => self.cx.root_path.clone(),
|
||||||
|
None | Some(&Unknown) => return None,
|
||||||
|
};
|
||||||
|
Some(format!("{root}/{krate}/macro.{name}.html?gotomacrosrc=1",
|
||||||
|
root = root,
|
||||||
|
krate = krate,
|
||||||
|
name = self.item.name.as_ref().unwrap()))
|
||||||
|
|
||||||
// If this item is part of the local crate, then we're guaranteed to
|
// If this item is part of the local crate, then we're guaranteed to
|
||||||
// know the span, so we plow forward and generate a proper url. The url
|
// know the span, so we plow forward and generate a proper url. The url
|
||||||
// has anchors for the line numbers that we're linking to.
|
// has anchors for the line numbers that we're linking to.
|
||||||
if ast_util::is_local(self.item.def_id) {
|
} else if ast_util::is_local(self.item.def_id) {
|
||||||
let mut path = Vec::new();
|
let mut path = Vec::new();
|
||||||
clean_srcpath(&cx.src_root, Path::new(&self.item.source.filename),
|
clean_srcpath(&cx.src_root, Path::new(&self.item.source.filename),
|
||||||
true, |component| {
|
true, |component| {
|
||||||
path.push(component.to_string());
|
path.push(component.to_string());
|
||||||
});
|
});
|
||||||
let href = if self.item.source.loline == self.item.source.hiline {
|
|
||||||
format!("{}", self.item.source.loline)
|
|
||||||
} else {
|
|
||||||
format!("{}-{}",
|
|
||||||
self.item.source.loline,
|
|
||||||
self.item.source.hiline)
|
|
||||||
};
|
|
||||||
Some(format!("{root}src/{krate}/{path}.html#{href}",
|
Some(format!("{root}src/{krate}/{path}.html#{href}",
|
||||||
root = self.cx.root_path,
|
root = self.cx.root_path,
|
||||||
krate = self.cx.layout.krate,
|
krate = self.cx.layout.krate,
|
||||||
|
@ -1380,9 +1402,9 @@ impl<'a> Item<'a> {
|
||||||
let cache = cache();
|
let cache = cache();
|
||||||
let path = &cache.external_paths[&self.item.def_id];
|
let path = &cache.external_paths[&self.item.def_id];
|
||||||
let root = match cache.extern_locations[&self.item.def_id.krate] {
|
let root = match cache.extern_locations[&self.item.def_id.krate] {
|
||||||
Remote(ref s) => s.to_string(),
|
(_, Remote(ref s)) => s.to_string(),
|
||||||
Local => self.cx.root_path.clone(),
|
(_, Local) => self.cx.root_path.clone(),
|
||||||
Unknown => return None,
|
(_, Unknown) => return None,
|
||||||
};
|
};
|
||||||
Some(format!("{root}{path}/{file}?gotosrc={goto}",
|
Some(format!("{root}{path}/{file}?gotosrc={goto}",
|
||||||
root = root,
|
root = root,
|
||||||
|
@ -1444,7 +1466,8 @@ impl<'a> fmt::Display for Item<'a> {
|
||||||
if self.cx.include_sources && !is_primitive {
|
if self.cx.include_sources && !is_primitive {
|
||||||
match self.href(self.cx) {
|
match self.href(self.cx) {
|
||||||
Some(l) => {
|
Some(l) => {
|
||||||
try!(write!(fmt, "<a id='src-{}' href='{}'>[src]</a>",
|
try!(write!(fmt, "<a id='src-{}' class='srclink' \
|
||||||
|
href='{}'>[src]</a>",
|
||||||
self.item.def_id.node, l));
|
self.item.def_id.node, l));
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
|
|
|
@ -802,6 +802,9 @@
|
||||||
if (query['gotosrc']) {
|
if (query['gotosrc']) {
|
||||||
window.location = $('#src-' + query['gotosrc']).attr('href');
|
window.location = $('#src-' + query['gotosrc']).attr('href');
|
||||||
}
|
}
|
||||||
|
if (query['gotomacrosrc']) {
|
||||||
|
window.location = $('.srclink').attr('href');
|
||||||
|
}
|
||||||
|
|
||||||
$("#expand-all").on("click", function() {
|
$("#expand-all").on("click", function() {
|
||||||
$(".docblock").show();
|
$(".docblock").show();
|
||||||
|
|
|
@ -398,6 +398,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
name: def.ident,
|
name: def.ident,
|
||||||
whence: def.span,
|
whence: def.span,
|
||||||
stab: self.stability(def.id),
|
stab: self.stability(def.id),
|
||||||
|
imported_from: def.imported_from,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue