Auto merge of #37954 - eddyb:rustdoc-2, r=alexcrichton
rustdoc: link to cross-crate sources directly. Fixes #37684 by implementing proper support for getting the `Span` of definitions across crates. In rustdoc this is used to generate direct links to the original source instead of fragile redirects. This functionality could be expanded further for making error reporting code more uniform and seamless across crates, although at the moment there is no actual source to print, only file/line/column information. Closes #37870 which is also "fixes" #37684 by throwing away the builtin macro docs from libcore. After this lands, #37727 could be reverted, although it doesn't matter much either way.
This commit is contained in:
commit
3abaf43f77
@ -760,47 +760,40 @@ impl<'ast> Map<'ast> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn opt_span(&self, id: NodeId) -> Option<Span> {
|
||||
let sp = match self.find(id) {
|
||||
Some(NodeItem(item)) => item.span,
|
||||
Some(NodeForeignItem(foreign_item)) => foreign_item.span,
|
||||
Some(NodeTraitItem(trait_method)) => trait_method.span,
|
||||
Some(NodeImplItem(ref impl_item)) => impl_item.span,
|
||||
Some(NodeVariant(variant)) => variant.span,
|
||||
Some(NodeField(field)) => field.span,
|
||||
Some(NodeExpr(expr)) => expr.span,
|
||||
Some(NodeStmt(stmt)) => stmt.span,
|
||||
Some(NodeTy(ty)) => ty.span,
|
||||
Some(NodeTraitRef(tr)) => tr.path.span,
|
||||
Some(NodeLocal(pat)) => pat.span,
|
||||
Some(NodePat(pat)) => pat.span,
|
||||
Some(NodeBlock(block)) => block.span,
|
||||
Some(NodeStructCtor(_)) => self.expect_item(self.get_parent(id)).span,
|
||||
Some(NodeTyParam(ty_param)) => ty_param.span,
|
||||
Some(NodeVisibility(&Visibility::Restricted { ref path, .. })) => path.span,
|
||||
_ => return None,
|
||||
};
|
||||
Some(sp)
|
||||
}
|
||||
|
||||
pub fn span(&self, id: NodeId) -> Span {
|
||||
self.read(id); // reveals span from node
|
||||
self.opt_span(id)
|
||||
.unwrap_or_else(|| bug!("AstMap.span: could not find span for id {:?}", id))
|
||||
match self.find_entry(id) {
|
||||
Some(EntryItem(_, item)) => item.span,
|
||||
Some(EntryForeignItem(_, foreign_item)) => foreign_item.span,
|
||||
Some(EntryTraitItem(_, trait_method)) => trait_method.span,
|
||||
Some(EntryImplItem(_, impl_item)) => impl_item.span,
|
||||
Some(EntryVariant(_, variant)) => variant.span,
|
||||
Some(EntryField(_, field)) => field.span,
|
||||
Some(EntryExpr(_, expr)) => expr.span,
|
||||
Some(EntryStmt(_, stmt)) => stmt.span,
|
||||
Some(EntryTy(_, ty)) => ty.span,
|
||||
Some(EntryTraitRef(_, tr)) => tr.path.span,
|
||||
Some(EntryLocal(_, pat)) => pat.span,
|
||||
Some(EntryPat(_, pat)) => pat.span,
|
||||
Some(EntryBlock(_, block)) => block.span,
|
||||
Some(EntryStructCtor(_, _)) => self.expect_item(self.get_parent(id)).span,
|
||||
Some(EntryLifetime(_, lifetime)) => lifetime.span,
|
||||
Some(EntryTyParam(_, ty_param)) => ty_param.span,
|
||||
Some(EntryVisibility(_, &Visibility::Restricted { ref path, .. })) => path.span,
|
||||
Some(EntryVisibility(_, v)) => bug!("unexpected Visibility {:?}", v),
|
||||
|
||||
Some(RootCrate) => self.krate().span,
|
||||
Some(RootInlinedParent(parent)) => parent.body.span,
|
||||
Some(NotPresent) | None => {
|
||||
bug!("hir::map::Map::span: id not in map: {:?}", id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn span_if_local(&self, id: DefId) -> Option<Span> {
|
||||
self.as_local_node_id(id).map(|id| self.span(id))
|
||||
}
|
||||
|
||||
pub fn def_id_span(&self, def_id: DefId, fallback: Span) -> Span {
|
||||
if let Some(node_id) = self.as_local_node_id(def_id) {
|
||||
self.opt_span(node_id).unwrap_or(fallback)
|
||||
} else {
|
||||
fallback
|
||||
}
|
||||
}
|
||||
|
||||
pub fn node_to_string(&self, id: NodeId) -> String {
|
||||
node_id_to_string(self, id, true)
|
||||
}
|
||||
|
@ -260,6 +260,7 @@ pub struct ExternCrate {
|
||||
pub trait CrateStore<'tcx> {
|
||||
// item info
|
||||
fn describe_def(&self, def: DefId) -> Option<Def>;
|
||||
fn def_span(&self, sess: &Session, def: DefId) -> Span;
|
||||
fn stability(&self, def: DefId) -> Option<attr::Stability>;
|
||||
fn deprecation(&self, def: DefId) -> Option<attr::Deprecation>;
|
||||
fn visibility(&self, def: DefId) -> ty::Visibility;
|
||||
@ -404,6 +405,7 @@ pub struct DummyCrateStore;
|
||||
impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
|
||||
// item info
|
||||
fn describe_def(&self, def: DefId) -> Option<Def> { bug!("describe_def") }
|
||||
fn def_span(&self, sess: &Session, def: DefId) -> Span { bug!("def_span") }
|
||||
fn stability(&self, def: DefId) -> Option<attr::Stability> { bug!("stability") }
|
||||
fn deprecation(&self, def: DefId) -> Option<attr::Deprecation> { bug!("deprecation") }
|
||||
fn visibility(&self, def: DefId) -> ty::Visibility { bug!("visibility") }
|
||||
|
@ -283,10 +283,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
expected.ty,
|
||||
found.ty));
|
||||
|
||||
match
|
||||
self.map.as_local_node_id(expected.def_id)
|
||||
.and_then(|node_id| self.map.opt_span(node_id))
|
||||
{
|
||||
match self.map.span_if_local(expected.def_id) {
|
||||
Some(span) => {
|
||||
db.span_note(span, "a default was defined here...");
|
||||
}
|
||||
@ -300,10 +297,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
expected.origin_span,
|
||||
"...that was applied to an unconstrained type variable here");
|
||||
|
||||
match
|
||||
self.map.as_local_node_id(found.def_id)
|
||||
.and_then(|node_id| self.map.opt_span(node_id))
|
||||
{
|
||||
match self.map.span_if_local(found.def_id) {
|
||||
Some(span) => {
|
||||
db.span_note(span, "a second default was defined here...");
|
||||
}
|
||||
|
@ -2360,6 +2360,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn def_span(self, def_id: DefId) -> Span {
|
||||
if let Some(id) = self.map.as_local_node_id(def_id) {
|
||||
self.map.span(id)
|
||||
} else {
|
||||
self.sess.cstore.def_span(&self.sess, def_id)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn item_name(self, id: DefId) -> ast::Name {
|
||||
if let Some(id) = self.map.as_local_node_id(id) {
|
||||
self.map.name(id)
|
||||
|
@ -496,8 +496,8 @@ fn add_fragment_siblings_for_extension<'a, 'tcx>(this: &MoveData<'tcx>,
|
||||
},
|
||||
|
||||
ref ty => {
|
||||
let opt_span = origin_id.and_then(|id|tcx.map.opt_span(id));
|
||||
span_bug!(opt_span.unwrap_or(DUMMY_SP),
|
||||
let span = origin_id.map_or(DUMMY_SP, |id| tcx.map.span(id));
|
||||
span_bug!(span,
|
||||
"type {:?} ({:?}) is not fragmentable",
|
||||
parent_ty, ty);
|
||||
}
|
||||
|
@ -1006,11 +1006,7 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
|
||||
got {:?}",
|
||||
node);
|
||||
|
||||
// Point to what was found, if there's an accessible span.
|
||||
match tcx.map.opt_span(nodeid) {
|
||||
Some(sp) => tcx.sess.span_fatal(sp, &message),
|
||||
None => tcx.sess.fatal(&message),
|
||||
}
|
||||
tcx.sess.span_fatal(tcx.map.span(nodeid), &message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ use syntax::ast;
|
||||
use syntax::attr;
|
||||
use syntax::parse::new_parser_from_source_str;
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax_pos::mk_sp;
|
||||
use syntax_pos::{mk_sp, Span};
|
||||
use rustc::hir::svh::Svh;
|
||||
use rustc_back::target::Target;
|
||||
use rustc::hir;
|
||||
@ -43,6 +43,11 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
|
||||
self.get_crate_data(def.krate).get_def(def.index)
|
||||
}
|
||||
|
||||
fn def_span(&self, sess: &Session, def: DefId) -> Span {
|
||||
self.dep_graph.read(DepNode::MetaData(def));
|
||||
self.get_crate_data(def.krate).get_span(def.index, sess)
|
||||
}
|
||||
|
||||
fn stability(&self, def: DefId) -> Option<attr::Stability> {
|
||||
self.dep_graph.read(DepNode::MetaData(def));
|
||||
self.get_crate_data(def.krate).get_stability(def.index)
|
||||
@ -383,20 +388,23 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
|
||||
let local_span = mk_sp(lo, parser.prev_span.hi);
|
||||
|
||||
// Mark the attrs as used
|
||||
for attr in &def.attrs {
|
||||
let attrs = data.get_item_attrs(id.index);
|
||||
for attr in &attrs {
|
||||
attr::mark_used(attr);
|
||||
}
|
||||
|
||||
let name = data.def_key(id.index).disambiguated_data.data
|
||||
.get_opt_name().expect("no name in load_macro");
|
||||
sess.imported_macro_spans.borrow_mut()
|
||||
.insert(local_span, (def.name.as_str().to_string(), def.span));
|
||||
.insert(local_span, (name.to_string(), data.get_span(id.index, sess)));
|
||||
|
||||
LoadedMacro::MacroRules(ast::MacroDef {
|
||||
ident: ast::Ident::with_empty_ctxt(def.name),
|
||||
ident: ast::Ident::with_empty_ctxt(name),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: local_span,
|
||||
imported_from: None, // FIXME
|
||||
allow_internal_unstable: attr::contains_name(&def.attrs, "allow_internal_unstable"),
|
||||
attrs: def.attrs,
|
||||
allow_internal_unstable: attr::contains_name(&attrs, "allow_internal_unstable"),
|
||||
attrs: attrs,
|
||||
body: body,
|
||||
})
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ use rustc::middle::cstore::{InlinedItem, LinkagePreference};
|
||||
use rustc::hir::def::{self, Def, CtorKind};
|
||||
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||
use rustc::middle::lang_items;
|
||||
use rustc::session::Session;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::subst::Substs;
|
||||
|
||||
@ -47,8 +48,9 @@ use syntax_pos::{self, Span, BytePos, Pos};
|
||||
|
||||
pub struct DecodeContext<'a, 'tcx: 'a> {
|
||||
opaque: opaque::Decoder<'a>,
|
||||
tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>,
|
||||
cdata: Option<&'a CrateMetadata>,
|
||||
sess: Option<&'a Session>,
|
||||
tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>,
|
||||
from_id_range: IdRange,
|
||||
to_id_range: IdRange,
|
||||
|
||||
@ -61,22 +63,21 @@ pub struct DecodeContext<'a, 'tcx: 'a> {
|
||||
/// Abstract over the various ways one can create metadata decoders.
|
||||
pub trait Metadata<'a, 'tcx>: Copy {
|
||||
fn raw_bytes(self) -> &'a [u8];
|
||||
fn cdata(self) -> Option<&'a CrateMetadata> {
|
||||
None
|
||||
}
|
||||
fn tcx(self) -> Option<TyCtxt<'a, 'tcx, 'tcx>> {
|
||||
None
|
||||
}
|
||||
fn cdata(self) -> Option<&'a CrateMetadata> { None }
|
||||
fn sess(self) -> Option<&'a Session> { None }
|
||||
fn tcx(self) -> Option<TyCtxt<'a, 'tcx, 'tcx>> { None }
|
||||
|
||||
fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> {
|
||||
let id_range = IdRange {
|
||||
min: NodeId::from_u32(u32::MIN),
|
||||
max: NodeId::from_u32(u32::MAX),
|
||||
};
|
||||
let tcx = self.tcx();
|
||||
DecodeContext {
|
||||
opaque: opaque::Decoder::new(self.raw_bytes(), pos),
|
||||
cdata: self.cdata(),
|
||||
tcx: self.tcx(),
|
||||
sess: self.sess().or(tcx.map(|tcx| tcx.sess)),
|
||||
tcx: tcx,
|
||||
from_id_range: id_range,
|
||||
to_id_range: id_range,
|
||||
last_filemap_index: 0,
|
||||
@ -104,6 +105,18 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadata {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, &'a Session) {
|
||||
fn raw_bytes(self) -> &'a [u8] {
|
||||
self.0.raw_bytes()
|
||||
}
|
||||
fn cdata(self) -> Option<&'a CrateMetadata> {
|
||||
Some(self.0)
|
||||
}
|
||||
fn sess(self) -> Option<&'a Session> {
|
||||
Some(&self.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'a, 'tcx, 'tcx>) {
|
||||
fn raw_bytes(self) -> &'a [u8] {
|
||||
self.0.raw_bytes()
|
||||
@ -280,8 +293,8 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
|
||||
let lo = BytePos::decode(self)?;
|
||||
let hi = BytePos::decode(self)?;
|
||||
|
||||
let tcx = if let Some(tcx) = self.tcx {
|
||||
tcx
|
||||
let sess = if let Some(sess) = self.sess {
|
||||
sess
|
||||
} else {
|
||||
return Ok(syntax_pos::mk_sp(lo, hi));
|
||||
};
|
||||
@ -299,7 +312,7 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
|
||||
(lo, hi)
|
||||
};
|
||||
|
||||
let imported_filemaps = self.cdata().imported_filemaps(&tcx.sess.codemap());
|
||||
let imported_filemaps = self.cdata().imported_filemaps(&sess.codemap());
|
||||
let filemap = {
|
||||
// Optimize for the case that most spans within a translated item
|
||||
// originate from the same filemap.
|
||||
@ -537,6 +550,10 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_span(&self, index: DefIndex, sess: &Session) -> Span {
|
||||
self.entry(index).span.decode((self, sess))
|
||||
}
|
||||
|
||||
pub fn get_trait_def(&self,
|
||||
item_id: DefIndex,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
||||
|
@ -275,6 +275,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
Entry {
|
||||
kind: EntryKind::Variant(self.lazy(&data)),
|
||||
visibility: enum_vis.simplify(),
|
||||
span: self.lazy(&tcx.def_span(def_id)),
|
||||
def_key: self.encode_def_key(def_id),
|
||||
attributes: self.encode_attributes(&tcx.get_attrs(def_id)),
|
||||
children: self.lazy_seq(variant.fields.iter().map(|f| {
|
||||
@ -313,6 +314,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
Entry {
|
||||
kind: EntryKind::Mod(self.lazy(&data)),
|
||||
visibility: vis.simplify(),
|
||||
span: self.lazy(&md.inner),
|
||||
def_key: self.encode_def_key(def_id),
|
||||
attributes: self.encode_attributes(attrs),
|
||||
children: self.lazy_seq(md.item_ids.iter().map(|item_id| {
|
||||
@ -393,6 +395,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
Entry {
|
||||
kind: EntryKind::Field,
|
||||
visibility: field.vis.simplify(),
|
||||
span: self.lazy(&tcx.def_span(def_id)),
|
||||
def_key: self.encode_def_key(def_id),
|
||||
attributes: self.encode_attributes(&variant_data.fields()[field_index].attrs),
|
||||
children: LazySeq::empty(),
|
||||
@ -426,6 +429,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
Entry {
|
||||
kind: EntryKind::Struct(self.lazy(&data)),
|
||||
visibility: struct_vis.simplify(),
|
||||
span: self.lazy(&tcx.def_span(def_id)),
|
||||
def_key: self.encode_def_key(def_id),
|
||||
attributes: LazySeq::empty(),
|
||||
children: LazySeq::empty(),
|
||||
@ -492,6 +496,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
Entry {
|
||||
kind: kind,
|
||||
visibility: trait_item.vis.simplify(),
|
||||
span: self.lazy(&ast_item.span),
|
||||
def_key: self.encode_def_key(def_id),
|
||||
attributes: self.encode_attributes(&ast_item.attrs),
|
||||
children: LazySeq::empty(),
|
||||
@ -580,6 +585,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
Entry {
|
||||
kind: kind,
|
||||
visibility: impl_item.vis.simplify(),
|
||||
span: self.lazy(&ast_item.span),
|
||||
def_key: self.encode_def_key(def_id),
|
||||
attributes: self.encode_attributes(&ast_item.attrs),
|
||||
children: LazySeq::empty(),
|
||||
@ -743,6 +749,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
Entry {
|
||||
kind: kind,
|
||||
visibility: item.vis.simplify(),
|
||||
span: self.lazy(&item.span),
|
||||
def_key: self.encode_def_key(def_id),
|
||||
attributes: self.encode_attributes(&item.attrs),
|
||||
children: match item.node {
|
||||
@ -850,18 +857,15 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
/// Serialize the text of exported macros
|
||||
fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) -> Entry<'tcx> {
|
||||
let def_id = self.tcx.map.local_def_id(macro_def.id);
|
||||
let macro_def = MacroDef {
|
||||
name: macro_def.name,
|
||||
attrs: macro_def.attrs.to_vec(),
|
||||
span: macro_def.span,
|
||||
body: ::syntax::print::pprust::tts_to_string(¯o_def.body)
|
||||
};
|
||||
Entry {
|
||||
kind: EntryKind::MacroDef(self.lazy(¯o_def)),
|
||||
kind: EntryKind::MacroDef(self.lazy(&MacroDef {
|
||||
body: ::syntax::print::pprust::tts_to_string(¯o_def.body)
|
||||
})),
|
||||
visibility: ty::Visibility::Public,
|
||||
span: self.lazy(¯o_def.span),
|
||||
def_key: self.encode_def_key(def_id),
|
||||
|
||||
attributes: LazySeq::empty(),
|
||||
attributes: self.encode_attributes(¯o_def.attrs),
|
||||
children: LazySeq::empty(),
|
||||
stability: None,
|
||||
deprecation: None,
|
||||
@ -960,6 +964,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
Entry {
|
||||
kind: kind,
|
||||
visibility: nitem.vis.simplify(),
|
||||
span: self.lazy(&nitem.span),
|
||||
def_key: self.encode_def_key(def_id),
|
||||
attributes: self.encode_attributes(&nitem.attrs),
|
||||
children: LazySeq::empty(),
|
||||
@ -1038,9 +1043,11 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
|
||||
|
||||
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
fn encode_info_for_anon_ty(&mut self, def_id: DefId) -> Entry<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
Entry {
|
||||
kind: EntryKind::Type,
|
||||
visibility: ty::Visibility::Public,
|
||||
span: self.lazy(&tcx.def_span(def_id)),
|
||||
def_key: self.encode_def_key(def_id),
|
||||
attributes: LazySeq::empty(),
|
||||
children: LazySeq::empty(),
|
||||
@ -1069,6 +1076,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
Entry {
|
||||
kind: EntryKind::Closure(self.lazy(&data)),
|
||||
visibility: ty::Visibility::Public,
|
||||
span: self.lazy(&tcx.def_span(def_id)),
|
||||
def_key: self.encode_def_key(def_id),
|
||||
attributes: self.encode_attributes(&tcx.get_attrs(def_id)),
|
||||
children: LazySeq::empty(),
|
||||
@ -1163,11 +1171,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
let all_filemaps = codemap.files.borrow();
|
||||
self.lazy_seq_ref(all_filemaps.iter()
|
||||
.filter(|filemap| {
|
||||
// No need to export empty filemaps, as they can't contain spans
|
||||
// that need translation.
|
||||
// Also no need to re-export imported filemaps, as any downstream
|
||||
// No need to re-export imported filemaps, as any downstream
|
||||
// crate will import them from their original source.
|
||||
!filemap.lines.borrow().is_empty() && !filemap.is_imported()
|
||||
!filemap.is_imported()
|
||||
})
|
||||
.map(|filemap| &**filemap))
|
||||
}
|
||||
|
@ -197,18 +197,11 @@ pub struct TraitImpls {
|
||||
pub impls: LazySeq<DefIndex>,
|
||||
}
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
pub struct MacroDef {
|
||||
pub name: ast::Name,
|
||||
pub attrs: Vec<ast::Attribute>,
|
||||
pub span: Span,
|
||||
pub body: String,
|
||||
}
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
pub struct Entry<'tcx> {
|
||||
pub kind: EntryKind<'tcx>,
|
||||
pub visibility: ty::Visibility,
|
||||
pub span: Lazy<Span>,
|
||||
pub def_key: Lazy<hir::map::DefKey>,
|
||||
pub attributes: LazySeq<ast::Attribute>,
|
||||
pub children: LazySeq<DefIndex>,
|
||||
@ -257,6 +250,11 @@ pub struct ModData {
|
||||
pub reexports: LazySeq<def::Export>,
|
||||
}
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
pub struct MacroDef {
|
||||
pub body: String,
|
||||
}
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
pub struct FnData {
|
||||
pub constness: hir::Constness,
|
||||
|
@ -69,7 +69,7 @@ pub fn item_namespace(ccx: &CrateContext, def_id: DefId) -> DIScope {
|
||||
};
|
||||
|
||||
let namespace_name = CString::new(namespace_name.as_bytes()).unwrap();
|
||||
let span = ccx.tcx().map.def_id_span(def_id, DUMMY_SP);
|
||||
let span = ccx.tcx().def_span(def_id);
|
||||
let (file, line) = if span != DUMMY_SP {
|
||||
let loc = span_start(ccx, span);
|
||||
(file_metadata(ccx, &loc.file.name, &loc.file.abs_path), loc.line as c_uint)
|
||||
|
@ -79,7 +79,7 @@ pub fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: DefId)
|
||||
});
|
||||
|
||||
// Try to get some span information, if we have an inlined item.
|
||||
let definition_span = cx.tcx().map.def_id_span(def_id, syntax_pos::DUMMY_SP);
|
||||
let definition_span = cx.tcx().def_span(def_id);
|
||||
|
||||
(containing_scope, definition_span)
|
||||
}
|
||||
|
@ -1227,8 +1227,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
self.tcx().associated_items(b.def_id()).find(|item| {
|
||||
item.kind == ty::AssociatedKind::Type && item.name == assoc_name
|
||||
})
|
||||
.and_then(|item| self.tcx().map.as_local_node_id(item.def_id))
|
||||
.and_then(|node_id| self.tcx().map.opt_span(node_id))
|
||||
.and_then(|item| self.tcx().map.span_if_local(item.def_id))
|
||||
});
|
||||
|
||||
let mut err = struct_span_err!(
|
||||
|
@ -21,7 +21,7 @@ use rustc::traits::{self, ObligationCause, Reveal};
|
||||
use util::nodemap::FxHashSet;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax_pos::{self, Span};
|
||||
use syntax_pos::Span;
|
||||
|
||||
/// check_drop_impl confirms that the Drop implementation identfied by
|
||||
/// `drop_impl_did` is not any more specialized than the type it is
|
||||
@ -59,7 +59,7 @@ pub fn check_drop_impl(ccx: &CrateCtxt, drop_impl_did: DefId) -> Result<(), ()>
|
||||
_ => {
|
||||
// Destructors only work on nominal types. This was
|
||||
// already checked by coherence, so we can panic here.
|
||||
let span = ccx.tcx.map.def_id_span(drop_impl_did, syntax_pos::DUMMY_SP);
|
||||
let span = ccx.tcx.def_span(drop_impl_did);
|
||||
span_bug!(span,
|
||||
"should have been rejected by coherence check: {}",
|
||||
dtor_self_type);
|
||||
@ -88,7 +88,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
|
||||
let named_type = tcx.item_type(self_type_did);
|
||||
let named_type = named_type.subst(tcx, &infcx.parameter_environment.free_substs);
|
||||
|
||||
let drop_impl_span = tcx.map.def_id_span(drop_impl_did, syntax_pos::DUMMY_SP);
|
||||
let drop_impl_span = tcx.def_span(drop_impl_did);
|
||||
let fresh_impl_substs =
|
||||
infcx.fresh_substs_for_item(drop_impl_span, drop_impl_did);
|
||||
let fresh_impl_self_ty = drop_impl_ty.subst(tcx, fresh_impl_substs);
|
||||
@ -173,7 +173,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>(
|
||||
|
||||
let self_type_node_id = tcx.map.as_local_node_id(self_type_did).unwrap();
|
||||
|
||||
let drop_impl_span = tcx.map.def_id_span(drop_impl_did, syntax_pos::DUMMY_SP);
|
||||
let drop_impl_span = tcx.def_span(drop_impl_did);
|
||||
|
||||
// We can assume the predicates attached to struct/enum definition
|
||||
// hold.
|
||||
|
@ -124,7 +124,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
CandidateSource::TraitSource(trait_did) => {
|
||||
let item = self.associated_item(trait_did, item_name).unwrap();
|
||||
let item_span = self.tcx.map.def_id_span(item.def_id, span);
|
||||
let item_span = self.tcx.def_span(item.def_id);
|
||||
span_note!(err,
|
||||
item_span,
|
||||
"candidate #{} is defined in the trait `{}`",
|
||||
|
@ -1755,7 +1755,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
let item_predicates = self.tcx.item_predicates(def_id);
|
||||
let bounds = item_predicates.instantiate(self.tcx, substs);
|
||||
|
||||
let span = self.tcx.map.def_id_span(def_id, codemap::DUMMY_SP);
|
||||
let span = self.tcx.def_span(def_id);
|
||||
for predicate in bounds.predicates {
|
||||
// Change the predicate to refer to the type variable,
|
||||
// which will be the concrete type, instead of the TyAnon.
|
||||
|
@ -183,7 +183,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
|
||||
fcx.register_wf_obligation(ty, span, code.clone());
|
||||
}
|
||||
ty::AssociatedKind::Method => {
|
||||
reject_shadowing_type_parameters(fcx.tcx, span, item.def_id);
|
||||
reject_shadowing_type_parameters(fcx.tcx, item.def_id);
|
||||
let method_ty = fcx.tcx.item_type(item.def_id);
|
||||
let method_ty = fcx.instantiate_type_scheme(span, free_substs, &method_ty);
|
||||
let predicates = fcx.instantiate_bounds(span, item.def_id, free_substs);
|
||||
@ -576,7 +576,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn reject_shadowing_type_parameters(tcx: TyCtxt, span: Span, def_id: DefId) {
|
||||
fn reject_shadowing_type_parameters(tcx: TyCtxt, def_id: DefId) {
|
||||
let generics = tcx.item_generics(def_id);
|
||||
let parent = tcx.item_generics(generics.parent.unwrap());
|
||||
let impl_params: FxHashMap<_, _> = parent.types
|
||||
@ -587,17 +587,12 @@ fn reject_shadowing_type_parameters(tcx: TyCtxt, span: Span, def_id: DefId) {
|
||||
for method_param in &generics.types {
|
||||
if impl_params.contains_key(&method_param.name) {
|
||||
// Tighten up the span to focus on only the shadowing type
|
||||
let shadow_node_id = tcx.map.as_local_node_id(method_param.def_id).unwrap();
|
||||
let type_span = match tcx.map.opt_span(shadow_node_id) {
|
||||
Some(osp) => osp,
|
||||
None => span
|
||||
};
|
||||
let type_span = tcx.def_span(method_param.def_id);
|
||||
|
||||
// The expectation here is that the original trait declaration is
|
||||
// local so it should be okay to just unwrap everything.
|
||||
let trait_def_id = impl_params.get(&method_param.name).unwrap();
|
||||
let trait_node_id = tcx.map.as_local_node_id(*trait_def_id).unwrap();
|
||||
let trait_decl_span = tcx.map.opt_span(trait_node_id).unwrap();
|
||||
let trait_def_id = impl_params[&method_param.name];
|
||||
let trait_decl_span = tcx.def_span(trait_def_id);
|
||||
error_194(tcx, type_span, trait_decl_span, method_param.name);
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ use rustc::util::nodemap::DefIdMap;
|
||||
use std::cell::Cell;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax_pos::{DUMMY_SP, Span};
|
||||
use syntax_pos::Span;
|
||||
|
||||
use rustc::hir::print::pat_to_string;
|
||||
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
@ -542,7 +542,7 @@ impl<'a, 'gcx, 'tcx> ResolveReason {
|
||||
}
|
||||
ResolvingClosure(did) |
|
||||
ResolvingAnonTy(did) => {
|
||||
tcx.map.def_id_span(did, DUMMY_SP)
|
||||
tcx.def_span(did)
|
||||
}
|
||||
ResolvingDeferredObligation(span) => span
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ fn try_inline_def(cx: &DocContext, def: Def) -> Option<Vec<clean::Item>> {
|
||||
let did = def.def_id();
|
||||
cx.renderinfo.borrow_mut().inlined.insert(did);
|
||||
ret.push(clean::Item {
|
||||
source: clean::Span::empty(),
|
||||
source: tcx.def_span(did).clean(cx),
|
||||
name: Some(tcx.item_name(did).to_string()),
|
||||
attrs: load_attrs(cx, did),
|
||||
inner: inner,
|
||||
@ -321,7 +321,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
|
||||
clean::RegionBound(..) => unreachable!(),
|
||||
},
|
||||
}),
|
||||
source: clean::Span::empty(),
|
||||
source: tcx.def_span(did).clean(cx),
|
||||
name: None,
|
||||
attrs: attrs,
|
||||
visibility: Some(clean::Inherited),
|
||||
@ -357,7 +357,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
|
||||
tcx.item_type(item.def_id).clean(cx),
|
||||
default,
|
||||
),
|
||||
source: clean::Span::empty(),
|
||||
source: tcx.def_span(item.def_id).clean(cx),
|
||||
attrs: clean::Attributes::default(),
|
||||
visibility: None,
|
||||
stability: tcx.lookup_stability(item.def_id).clean(cx),
|
||||
@ -404,7 +404,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
|
||||
Some(clean::Item {
|
||||
name: Some(item.name.clean(cx)),
|
||||
inner: clean::TypedefItem(typedef, true),
|
||||
source: clean::Span::empty(),
|
||||
source: tcx.def_span(item.def_id).clean(cx),
|
||||
attrs: clean::Attributes::default(),
|
||||
visibility: None,
|
||||
stability: tcx.lookup_stability(item.def_id).clean(cx),
|
||||
@ -442,7 +442,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
|
||||
items: trait_items,
|
||||
polarity: Some(polarity.clean(cx)),
|
||||
}),
|
||||
source: clean::Span::empty(),
|
||||
source: tcx.def_span(did).clean(cx),
|
||||
name: None,
|
||||
attrs: attrs,
|
||||
visibility: Some(clean::Inherited),
|
||||
|
@ -27,12 +27,11 @@ use syntax::ptr::P;
|
||||
use syntax::symbol::keywords;
|
||||
use syntax_pos::{self, DUMMY_SP, Pos};
|
||||
|
||||
use rustc_trans::back::link;
|
||||
use rustc::middle::privacy::AccessLevels;
|
||||
use rustc::middle::resolve_lifetime::DefRegion::*;
|
||||
use rustc::middle::lang_items;
|
||||
use rustc::hir::def::{Def, CtorKind};
|
||||
use rustc::hir::def_id::{self, DefId, DefIndex, CRATE_DEF_INDEX};
|
||||
use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||
use rustc::hir::print as pprust;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{self, AdtKind};
|
||||
@ -46,7 +45,6 @@ use std::rc::Rc;
|
||||
use std::slice;
|
||||
use std::sync::Arc;
|
||||
use std::u32;
|
||||
use std::env::current_dir;
|
||||
use std::mem;
|
||||
|
||||
use core::DocContext;
|
||||
@ -111,19 +109,16 @@ pub struct Crate {
|
||||
pub name: String,
|
||||
pub src: PathBuf,
|
||||
pub module: Option<Item>,
|
||||
pub externs: Vec<(def_id::CrateNum, ExternalCrate)>,
|
||||
pub primitives: Vec<PrimitiveType>,
|
||||
pub externs: Vec<(CrateNum, ExternalCrate)>,
|
||||
pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
|
||||
pub access_levels: Arc<AccessLevels<DefId>>,
|
||||
// These are later on moved into `CACHEKEY`, leaving the map empty.
|
||||
// Only here so that they can be filtered through the rustdoc passes.
|
||||
pub external_traits: FxHashMap<DefId, Trait>,
|
||||
}
|
||||
|
||||
struct CrateNum(def_id::CrateNum);
|
||||
|
||||
impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
|
||||
fn clean(&self, cx: &DocContext) -> Crate {
|
||||
use rustc::session::config::Input;
|
||||
use ::visit_lib::LibEmbargoVisitor;
|
||||
|
||||
{
|
||||
@ -134,20 +129,65 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
|
||||
|
||||
let mut externs = Vec::new();
|
||||
for cnum in cx.sess().cstore.crates() {
|
||||
externs.push((cnum, CrateNum(cnum).clean(cx)));
|
||||
externs.push((cnum, cnum.clean(cx)));
|
||||
// Analyze doc-reachability for extern items
|
||||
LibEmbargoVisitor::new(cx).visit_lib(cnum);
|
||||
}
|
||||
externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
|
||||
|
||||
// Figure out the name of this crate
|
||||
let input = &cx.input;
|
||||
let name = link::find_crate_name(None, &self.attrs, input);
|
||||
|
||||
// Clean the crate, translating the entire libsyntax AST to one that is
|
||||
// understood by rustdoc.
|
||||
let mut module = self.module.clean(cx);
|
||||
|
||||
let ExternalCrate { name, src, primitives, .. } = LOCAL_CRATE.clean(cx);
|
||||
{
|
||||
let m = match module.inner {
|
||||
ModuleItem(ref mut m) => m,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
m.items.extend(primitives.iter().map(|&(def_id, prim, ref attrs)| {
|
||||
Item {
|
||||
source: Span::empty(),
|
||||
name: Some(prim.to_url_str().to_string()),
|
||||
attrs: attrs.clone(),
|
||||
visibility: Some(Public),
|
||||
stability: None,
|
||||
deprecation: None,
|
||||
def_id: def_id,
|
||||
inner: PrimitiveItem(prim),
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
let mut access_levels = cx.access_levels.borrow_mut();
|
||||
let mut external_traits = cx.external_traits.borrow_mut();
|
||||
|
||||
Crate {
|
||||
name: name,
|
||||
src: src,
|
||||
module: Some(module),
|
||||
externs: externs,
|
||||
primitives: primitives,
|
||||
access_levels: Arc::new(mem::replace(&mut access_levels, Default::default())),
|
||||
external_traits: mem::replace(&mut external_traits, Default::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub struct ExternalCrate {
|
||||
pub name: String,
|
||||
pub src: PathBuf,
|
||||
pub attrs: Attributes,
|
||||
pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
|
||||
}
|
||||
|
||||
impl Clean<ExternalCrate> for CrateNum {
|
||||
fn clean(&self, cx: &DocContext) -> ExternalCrate {
|
||||
let root = DefId { krate: *self, index: CRATE_DEF_INDEX };
|
||||
let krate_span = cx.tcx.def_span(root);
|
||||
let krate_src = cx.sess().codemap().span_to_filename(krate_span);
|
||||
|
||||
// Collect all inner modules which are tagged as implementations of
|
||||
// primitives.
|
||||
//
|
||||
@ -165,80 +205,50 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
|
||||
// Also note that this does not attempt to deal with modules tagged
|
||||
// duplicately for the same primitive. This is handled later on when
|
||||
// rendering by delegating everything to a hash map.
|
||||
let mut primitives = Vec::new();
|
||||
{
|
||||
let m = match module.inner {
|
||||
ModuleItem(ref mut m) => m,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let mut tmp = Vec::new();
|
||||
for child in &mut m.items {
|
||||
if !child.is_mod() {
|
||||
continue;
|
||||
let as_primitive = |def: Def| {
|
||||
if let Def::Mod(def_id) = def {
|
||||
let attrs = cx.tcx.get_attrs(def_id).clean(cx);
|
||||
let mut prim = None;
|
||||
for attr in attrs.lists("doc") {
|
||||
if let Some(v) = attr.value_str() {
|
||||
if attr.check_name("primitive") {
|
||||
prim = PrimitiveType::from_str(&v.as_str());
|
||||
if prim.is_some() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let prim = match PrimitiveType::find(&child.attrs) {
|
||||
Some(prim) => prim,
|
||||
None => continue,
|
||||
};
|
||||
primitives.push(prim);
|
||||
tmp.push(Item {
|
||||
source: Span::empty(),
|
||||
name: Some(prim.to_url_str().to_string()),
|
||||
attrs: child.attrs.clone(),
|
||||
visibility: Some(Public),
|
||||
stability: None,
|
||||
deprecation: None,
|
||||
def_id: DefId::local(prim.to_def_index()),
|
||||
inner: PrimitiveItem(prim),
|
||||
});
|
||||
return prim.map(|p| (def_id, p, attrs));
|
||||
}
|
||||
m.items.extend(tmp);
|
||||
}
|
||||
|
||||
let src = match cx.input {
|
||||
Input::File(ref path) => {
|
||||
if path.is_absolute() {
|
||||
path.clone()
|
||||
} else {
|
||||
current_dir().unwrap().join(path)
|
||||
None
|
||||
};
|
||||
let primitives = if root.is_local() {
|
||||
cx.tcx.map.krate().module.item_ids.iter().filter_map(|&id| {
|
||||
let item = cx.tcx.map.expect_item(id.id);
|
||||
match item.node {
|
||||
hir::ItemMod(_) => {
|
||||
as_primitive(Def::Mod(cx.tcx.map.local_def_id(id.id)))
|
||||
}
|
||||
hir::ItemUse(ref path, hir::UseKind::Single)
|
||||
if item.vis == hir::Visibility::Public => {
|
||||
as_primitive(path.def).map(|(_, prim, attrs)| {
|
||||
// Pretend the primitive is local.
|
||||
(cx.tcx.map.local_def_id(id.id), prim, attrs)
|
||||
})
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
},
|
||||
Input::Str { ref name, .. } => PathBuf::from(name.clone()),
|
||||
}).collect()
|
||||
} else {
|
||||
cx.tcx.sess.cstore.item_children(root).iter().map(|item| item.def)
|
||||
.filter_map(as_primitive).collect()
|
||||
};
|
||||
|
||||
let mut access_levels = cx.access_levels.borrow_mut();
|
||||
let mut external_traits = cx.external_traits.borrow_mut();
|
||||
|
||||
Crate {
|
||||
name: name.to_string(),
|
||||
src: src,
|
||||
module: Some(module),
|
||||
externs: externs,
|
||||
primitives: primitives,
|
||||
access_levels: Arc::new(mem::replace(&mut access_levels, Default::default())),
|
||||
external_traits: mem::replace(&mut external_traits, Default::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub struct ExternalCrate {
|
||||
pub name: String,
|
||||
pub attrs: Attributes,
|
||||
pub primitives: Vec<PrimitiveType>,
|
||||
}
|
||||
|
||||
impl Clean<ExternalCrate> for CrateNum {
|
||||
fn clean(&self, cx: &DocContext) -> ExternalCrate {
|
||||
let mut primitives = Vec::new();
|
||||
let root = DefId { krate: self.0, index: CRATE_DEF_INDEX };
|
||||
for item in cx.tcx.sess.cstore.item_children(root) {
|
||||
let attrs = inline::load_attrs(cx, item.def.def_id());
|
||||
PrimitiveType::find(&attrs).map(|prim| primitives.push(prim));
|
||||
}
|
||||
ExternalCrate {
|
||||
name: cx.sess().cstore.crate_name(self.0).to_string(),
|
||||
attrs: cx.sess().cstore.item_attrs(root).clean(cx),
|
||||
name: cx.tcx.crate_name(*self).to_string(),
|
||||
src: PathBuf::from(krate_src),
|
||||
attrs: cx.tcx.get_attrs(root).clean(cx),
|
||||
primitives: primitives,
|
||||
}
|
||||
}
|
||||
@ -1438,7 +1448,7 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem {
|
||||
deprecation: get_deprecation(cx, self.def_id),
|
||||
def_id: self.def_id,
|
||||
attrs: inline::load_attrs(cx, self.def_id),
|
||||
source: Span::empty(),
|
||||
source: cx.tcx.def_span(self.def_id).clean(cx),
|
||||
inner: inner,
|
||||
}
|
||||
}
|
||||
@ -1596,19 +1606,6 @@ impl PrimitiveType {
|
||||
}
|
||||
}
|
||||
|
||||
fn find(attrs: &Attributes) -> Option<PrimitiveType> {
|
||||
for attr in attrs.lists("doc") {
|
||||
if let Some(v) = attr.value_str() {
|
||||
if attr.check_name("primitive") {
|
||||
if let ret@Some(..) = PrimitiveType::from_str(&v.as_str()) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
match *self {
|
||||
PrimitiveType::Isize => "isize",
|
||||
@ -1636,14 +1633,6 @@ impl PrimitiveType {
|
||||
pub fn to_url_str(&self) -> &'static str {
|
||||
self.as_str()
|
||||
}
|
||||
|
||||
/// Creates a rustdoc-specific node id for primitive types.
|
||||
///
|
||||
/// These node ids are generally never used by the AST itself.
|
||||
pub fn to_def_index(&self) -> DefIndex {
|
||||
let x = u32::MAX - 1 - (*self as u32);
|
||||
DefIndex::new(x as usize)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ast::IntTy> for PrimitiveType {
|
||||
@ -1943,7 +1932,7 @@ impl<'tcx> Clean<Item> for ty::FieldDefData<'tcx, 'static> {
|
||||
Item {
|
||||
name: Some(self.name).clean(cx),
|
||||
attrs: cx.tcx.get_attrs(self.did).clean(cx),
|
||||
source: Span::empty(),
|
||||
source: cx.tcx.def_span(self.did).clean(cx),
|
||||
visibility: self.vis.clean(cx),
|
||||
stability: get_stability(cx, self.did),
|
||||
deprecation: get_deprecation(cx, self.did),
|
||||
@ -2110,7 +2099,7 @@ impl<'tcx> Clean<Item> for ty::VariantDefData<'tcx, 'static> {
|
||||
fields_stripped: false,
|
||||
fields: self.fields.iter().map(|field| {
|
||||
Item {
|
||||
source: Span::empty(),
|
||||
source: cx.tcx.def_span(field.did).clean(cx),
|
||||
name: Some(field.name.clean(cx)),
|
||||
attrs: cx.tcx.get_attrs(field.did).clean(cx),
|
||||
visibility: field.vis.clean(cx),
|
||||
@ -2126,7 +2115,7 @@ impl<'tcx> Clean<Item> for ty::VariantDefData<'tcx, 'static> {
|
||||
Item {
|
||||
name: Some(self.name.clean(cx)),
|
||||
attrs: inline::load_attrs(cx, self.did),
|
||||
source: Span::empty(),
|
||||
source: cx.tcx.def_span(self.did).clean(cx),
|
||||
visibility: Some(Inherited),
|
||||
def_id: self.did,
|
||||
inner: VariantItem(Variant { kind: kind }),
|
||||
|
@ -45,7 +45,6 @@ pub type ExternalPaths = FxHashMap<DefId, (Vec<String>, clean::TypeKind)>;
|
||||
|
||||
pub struct DocContext<'a, 'tcx: 'a> {
|
||||
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
pub input: Input,
|
||||
pub populated_all_crate_impls: Cell<bool>,
|
||||
// Note that external items for which `doc(hidden)` applies to are shown as
|
||||
// non-reachable while local items aren't. This is because we're reusing
|
||||
@ -187,7 +186,6 @@ pub fn run_core(search_paths: SearchPaths,
|
||||
|
||||
let ctxt = DocContext {
|
||||
tcx: tcx,
|
||||
input: input,
|
||||
populated_all_crate_impls: Cell::new(false),
|
||||
access_levels: RefCell::new(access_levels),
|
||||
external_traits: Default::default(),
|
||||
|
@ -18,7 +18,7 @@
|
||||
use std::fmt;
|
||||
use std::iter::repeat;
|
||||
|
||||
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use syntax::abi::Abi;
|
||||
use rustc::hir;
|
||||
|
||||
@ -403,9 +403,9 @@ pub fn href(did: DefId) -> Option<(String, ItemType, Vec<String>)> {
|
||||
None => match cache.external_paths.get(&did) {
|
||||
Some(&(ref fqp, shortty)) => {
|
||||
(fqp, shortty, match cache.extern_locations[&did.krate] {
|
||||
(_, render::Remote(ref s)) => s.to_string(),
|
||||
(_, render::Local) => repeat("../").take(loc.len()).collect(),
|
||||
(_, render::Unknown) => return None,
|
||||
(.., render::Remote(ref s)) => s.to_string(),
|
||||
(.., render::Local) => repeat("../").take(loc.len()).collect(),
|
||||
(.., render::Unknown) => return None,
|
||||
})
|
||||
}
|
||||
None => return None,
|
||||
@ -479,7 +479,7 @@ fn primitive_link(f: &mut fmt::Formatter,
|
||||
let mut needs_termination = false;
|
||||
if !f.alternate() {
|
||||
match m.primitive_locations.get(&prim) {
|
||||
Some(&LOCAL_CRATE) => {
|
||||
Some(&def_id) if def_id.is_local() => {
|
||||
let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len());
|
||||
let len = if len == 0 {0} else {len - 1};
|
||||
write!(f, "<a class='primitive' href='{}primitive.{}.html'>",
|
||||
@ -487,14 +487,16 @@ fn primitive_link(f: &mut fmt::Formatter,
|
||||
prim.to_url_str())?;
|
||||
needs_termination = true;
|
||||
}
|
||||
Some(&cnum) => {
|
||||
let loc = match m.extern_locations[&cnum] {
|
||||
(ref cname, render::Remote(ref s)) => Some((cname, s.to_string())),
|
||||
(ref cname, render::Local) => {
|
||||
Some(&def_id) => {
|
||||
let loc = match m.extern_locations[&def_id.krate] {
|
||||
(ref cname, _, render::Remote(ref s)) => {
|
||||
Some((cname, s.to_string()))
|
||||
}
|
||||
(ref cname, _, render::Local) => {
|
||||
let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len());
|
||||
Some((cname, repeat("../").take(len).collect::<String>()))
|
||||
}
|
||||
(_, render::Unknown) => None,
|
||||
(.., render::Unknown) => None,
|
||||
};
|
||||
if let Some((cname, root)) = loc {
|
||||
write!(f, "<a class='primitive' href='{}{}/primitive.{}.html'>",
|
||||
|
@ -55,7 +55,7 @@ use externalfiles::ExternalHtml;
|
||||
use serialize::json::{ToJson, Json, as_json};
|
||||
use syntax::{abi, ast};
|
||||
use syntax::feature_gate::UnstableFeatures;
|
||||
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
|
||||
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
|
||||
use rustc::middle::privacy::AccessLevels;
|
||||
use rustc::middle::stability;
|
||||
use rustc::hir;
|
||||
@ -241,10 +241,10 @@ pub struct Cache {
|
||||
pub implementors: FxHashMap<DefId, Vec<Implementor>>,
|
||||
|
||||
/// Cache of where external crate documentation can be found.
|
||||
pub extern_locations: FxHashMap<CrateNum, (String, ExternalLocation)>,
|
||||
pub extern_locations: FxHashMap<CrateNum, (String, PathBuf, ExternalLocation)>,
|
||||
|
||||
/// Cache of where documentation for primitives can be found.
|
||||
pub primitive_locations: FxHashMap<clean::PrimitiveType, CrateNum>,
|
||||
pub primitive_locations: FxHashMap<clean::PrimitiveType, DefId>,
|
||||
|
||||
// Note that external items for which `doc(hidden)` applies to are shown as
|
||||
// non-reachable while local items aren't. This is because we're reusing
|
||||
@ -523,8 +523,13 @@ pub fn run(mut krate: clean::Crate,
|
||||
|
||||
// Cache where all our extern crates are located
|
||||
for &(n, ref e) in &krate.externs {
|
||||
cache.extern_locations.insert(n, (e.name.clone(),
|
||||
let src_root = match Path::new(&e.src).parent() {
|
||||
Some(p) => p.to_path_buf(),
|
||||
None => PathBuf::new(),
|
||||
};
|
||||
cache.extern_locations.insert(n, (e.name.clone(), src_root,
|
||||
extern_location(e, &cx.dst)));
|
||||
|
||||
let did = DefId { krate: n, index: CRATE_DEF_INDEX };
|
||||
cache.external_paths.insert(did, (vec![e.name.to_string()], ItemType::Module));
|
||||
}
|
||||
@ -533,13 +538,13 @@ pub fn run(mut krate: clean::Crate,
|
||||
//
|
||||
// Favor linking to as local extern as possible, so iterate all crates in
|
||||
// reverse topological order.
|
||||
for &(n, ref e) in krate.externs.iter().rev() {
|
||||
for &prim in &e.primitives {
|
||||
cache.primitive_locations.insert(prim, n);
|
||||
for &(_, ref e) in krate.externs.iter().rev() {
|
||||
for &(def_id, prim, _) in &e.primitives {
|
||||
cache.primitive_locations.insert(prim, def_id);
|
||||
}
|
||||
}
|
||||
for &prim in &krate.primitives {
|
||||
cache.primitive_locations.insert(prim, LOCAL_CRATE);
|
||||
for &(def_id, prim, _) in &krate.primitives {
|
||||
cache.primitive_locations.insert(prim, def_id);
|
||||
}
|
||||
|
||||
cache.stack.push(krate.name.clone());
|
||||
@ -875,6 +880,8 @@ impl<'a> DocFolder for SourceCollector<'a> {
|
||||
if self.scx.include_sources
|
||||
// skip all invalid spans
|
||||
&& item.source.filename != ""
|
||||
// skip non-local items
|
||||
&& item.def_id.is_local()
|
||||
// Macros from other libraries get special filenames which we can
|
||||
// safely ignore.
|
||||
&& !(item.source.filename.starts_with("<")
|
||||
@ -1127,13 +1134,15 @@ impl DocFolder for Cache {
|
||||
true
|
||||
}
|
||||
ref t => {
|
||||
match t.primitive_type() {
|
||||
Some(prim) => {
|
||||
let did = DefId::local(prim.to_def_index());
|
||||
let prim_did = t.primitive_type().and_then(|t| {
|
||||
self.primitive_locations.get(&t).cloned()
|
||||
});
|
||||
match prim_did {
|
||||
Some(did) => {
|
||||
self.parent_stack.push(did);
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1158,10 +1167,7 @@ impl DocFolder for Cache {
|
||||
}
|
||||
ref t => {
|
||||
t.primitive_type().and_then(|t| {
|
||||
self.primitive_locations.get(&t).map(|n| {
|
||||
let id = t.to_def_index();
|
||||
DefId { krate: *n, index: id }
|
||||
})
|
||||
self.primitive_locations.get(&t).cloned()
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1439,79 +1445,50 @@ impl<'a> Item<'a> {
|
||||
/// If `None` is returned, then a source link couldn't be generated. This
|
||||
/// may happen, for example, with externally inlined items where the source
|
||||
/// of their crate documentation isn't known.
|
||||
fn href(&self) -> Option<String> {
|
||||
let href = if self.item.source.loline == self.item.source.hiline {
|
||||
fn src_href(&self) -> Option<String> {
|
||||
let mut root = self.cx.root_path();
|
||||
|
||||
let cache = cache();
|
||||
let mut path = String::new();
|
||||
let (krate, path) = if self.item.def_id.is_local() {
|
||||
let path = PathBuf::from(&self.item.source.filename);
|
||||
if let Some(path) = self.cx.shared.local_sources.get(&path) {
|
||||
(&self.cx.shared.layout.krate, path)
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
} else {
|
||||
let (krate, src_root) = match cache.extern_locations.get(&self.item.def_id.krate) {
|
||||
Some(&(ref name, ref src, Local)) => (name, src),
|
||||
Some(&(ref name, ref src, Remote(ref s))) => {
|
||||
root = s.to_string();
|
||||
(name, src)
|
||||
}
|
||||
Some(&(_, _, Unknown)) | None => return None,
|
||||
};
|
||||
|
||||
let file = Path::new(&self.item.source.filename);
|
||||
clean_srcpath(&src_root, file, false, |component| {
|
||||
path.push_str(component);
|
||||
path.push('/');
|
||||
});
|
||||
let mut fname = file.file_name().expect("source has no filename")
|
||||
.to_os_string();
|
||||
fname.push(".html");
|
||||
path.push_str(&fname.to_string_lossy());
|
||||
(krate, &path)
|
||||
};
|
||||
|
||||
let lines = 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(),
|
||||
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
|
||||
// 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.
|
||||
} else if self.item.def_id.is_local() {
|
||||
let path = PathBuf::from(&self.item.source.filename);
|
||||
self.cx.shared.local_sources.get(&path).map(|path| {
|
||||
format!("{root}src/{krate}/{path}#{href}",
|
||||
root = self.cx.root_path(),
|
||||
krate = self.cx.shared.layout.krate,
|
||||
path = path,
|
||||
href = href)
|
||||
})
|
||||
// If this item is not part of the local crate, then things get a little
|
||||
// trickier. We don't actually know the span of the external item, but
|
||||
// we know that the documentation on the other end knows the span!
|
||||
//
|
||||
// In this case, we generate a link to the *documentation* for this type
|
||||
// in the original crate. There's an extra URL parameter which says that
|
||||
// we want to go somewhere else, and the JS on the destination page will
|
||||
// pick it up and instantly redirect the browser to the source code.
|
||||
//
|
||||
// If we don't know where the external documentation for this crate is
|
||||
// located, then we return `None`.
|
||||
} else {
|
||||
let cache = cache();
|
||||
let external_path = match cache.external_paths.get(&self.item.def_id) {
|
||||
Some(&(ref path, _)) => path,
|
||||
None => return None,
|
||||
};
|
||||
let mut path = match cache.extern_locations.get(&self.item.def_id.krate) {
|
||||
Some(&(_, Remote(ref s))) => s.to_string(),
|
||||
Some(&(_, Local)) => self.cx.root_path(),
|
||||
Some(&(_, Unknown)) => return None,
|
||||
None => return None,
|
||||
};
|
||||
for item in &external_path[..external_path.len() - 1] {
|
||||
path.push_str(item);
|
||||
path.push_str("/");
|
||||
}
|
||||
Some(format!("{path}{file}?gotosrc={goto}",
|
||||
path = path,
|
||||
file = item_path(self.item.type_(), external_path.last().unwrap()),
|
||||
goto = self.item.def_id.index.as_usize()))
|
||||
}
|
||||
Some(format!("{root}src/{krate}/{path}#{lines}",
|
||||
root = root,
|
||||
krate = krate,
|
||||
path = path,
|
||||
lines = lines))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1576,10 +1553,9 @@ impl<'a> fmt::Display for Item<'a> {
|
||||
// this page, and this link will be auto-clicked. The `id` attribute is
|
||||
// used to find the link to auto-click.
|
||||
if self.cx.shared.include_sources && !self.item.is_primitive() {
|
||||
if let Some(l) = self.href() {
|
||||
write!(fmt, "<a id='src-{}' class='srclink' \
|
||||
href='{}' title='{}'>[src]</a>",
|
||||
self.item.def_id.index.as_usize(), l, "goto source code")?;
|
||||
if let Some(l) = self.src_href() {
|
||||
write!(fmt, "<a class='srclink' href='{}' title='{}'>[src]</a>",
|
||||
l, "goto source code")?;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2781,8 +2757,7 @@ fn render_deref_methods(w: &mut fmt::Formatter, cx: &Context, impl_: &Impl,
|
||||
render_assoc_items(w, cx, container_item, did, what)
|
||||
} else {
|
||||
if let Some(prim) = target.primitive_type() {
|
||||
if let Some(c) = cache().primitive_locations.get(&prim) {
|
||||
let did = DefId { krate: *c, index: prim.to_def_index() };
|
||||
if let Some(&did) = cache().primitive_locations.get(&prim) {
|
||||
render_assoc_items(w, cx, container_item, did, what)?;
|
||||
}
|
||||
}
|
||||
@ -2796,12 +2771,11 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
|
||||
write!(w, "<h3 class='impl'><span class='in-band'><code>{}</code>", i.inner_impl())?;
|
||||
write!(w, "</span><span class='out-of-band'>")?;
|
||||
let since = i.impl_item.stability.as_ref().map(|s| &s.since[..]);
|
||||
if let Some(l) = (Item { item: &i.impl_item, cx: cx }).href() {
|
||||
if let Some(l) = (Item { item: &i.impl_item, cx: cx }).src_href() {
|
||||
write!(w, "<div class='ghost'></div>")?;
|
||||
render_stability_since_raw(w, since, outer_version)?;
|
||||
write!(w, "<a id='src-{}' class='srclink' \
|
||||
href='{}' title='{}'>[src]</a>",
|
||||
i.impl_item.def_id.index.as_usize(), l, "goto source code")?;
|
||||
write!(w, "<a class='srclink' href='{}' title='{}'>[src]</a>",
|
||||
l, "goto source code")?;
|
||||
} else {
|
||||
render_stability_since_raw(w, since, outer_version)?;
|
||||
}
|
||||
|
@ -923,15 +923,6 @@
|
||||
window.register_implementors(window.pending_implementors);
|
||||
}
|
||||
|
||||
// See documentation in html/render.rs for what this is doing.
|
||||
var query = getQueryStringParams();
|
||||
if (query['gotosrc']) {
|
||||
window.location = $('#src-' + query['gotosrc']).attr('href');
|
||||
}
|
||||
if (query['gotomacrosrc']) {
|
||||
window.location = $('.srclink').attr('href');
|
||||
}
|
||||
|
||||
function labelForToggleButton(sectionIsCollapsed) {
|
||||
if (sectionIsCollapsed) {
|
||||
// button will expand the section
|
||||
|
@ -16,5 +16,5 @@
|
||||
|
||||
extern crate issue_34274;
|
||||
|
||||
// @has foo/fn.extern_c_fn.html '//a/@href' '../issue_34274/fn.extern_c_fn.html?gotosrc='
|
||||
// @has foo/fn.extern_c_fn.html '//a/@href' '../src/issue_34274/issue-34274.rs.html#12'
|
||||
pub use issue_34274::extern_c_fn;
|
||||
|
@ -11,12 +11,13 @@
|
||||
// aux-build:src-links-external.rs
|
||||
// build-aux-docs
|
||||
// ignore-cross-compile
|
||||
// ignore-tidy-linelength
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
extern crate src_links_external;
|
||||
|
||||
// @has foo/bar/index.html '//a/@href' '../src_links_external/index.html?gotosrc='
|
||||
// @has foo/bar/index.html '//a/@href' '../../src/src_links_external/src-links-external.rs.html#11'
|
||||
pub use src_links_external as bar;
|
||||
|
||||
// @has foo/bar/struct.Foo.html '//a/@href' '../src_links_external/struct.Foo.html?gotosrc='
|
||||
// @has foo/bar/struct.Foo.html '//a/@href' '../../src/src_links_external/src-links-external.rs.html#11'
|
||||
|
Loading…
x
Reference in New Issue
Block a user