Skip to content

rustdoc: Hyperlink cross-crate reexports #14068

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 10, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions src/doc/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,13 @@ This document does not serve as a tutorial introduction to the
language. Background familiarity with the language is assumed. A separate
[tutorial] document is available to help acquire such background familiarity.

This document also does not serve as a reference to the [standard] or [extra]
libraries included in the language distribution. Those libraries are
This document also does not serve as a reference to the [standard]
library included in the language distribution. Those libraries are
documented separately by extracting documentation attributes from their
source code.

[tutorial]: tutorial.html
[standard]: std/index.html
[extra]: extra/index.html

## Disclaimer

Expand Down
2 changes: 1 addition & 1 deletion src/libcore/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
//!
//! Functions return `Result` whenever errors are expected and
//! recoverable. In the `std` crate `Result` is most prominently used
//! for [I/O](../io/index.html).
//! for [I/O](../../std/io/index.html).
//!
//! A simple function returning `Result` might be
//! defined and used like so:
Expand Down
84 changes: 37 additions & 47 deletions src/librustdoc/clean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -670,15 +670,7 @@ pub enum Type {
ResolvedPath {
pub path: Path,
pub typarams: Option<Vec<TyParamBound>>,
pub id: ast::NodeId,
},
/// Same as above, but only external variants
ExternalPath {
pub path: Path,
pub typarams: Option<Vec<TyParamBound>>,
pub fqn: Vec<~str>,
pub kind: TypeKind,
pub krate: ast::CrateNum,
pub did: ast::DefId,
},
// I have no idea how to usefully use this.
TyParamBinder(ast::NodeId),
Expand Down Expand Up @@ -715,19 +707,18 @@ pub enum Type {

#[deriving(Clone, Encodable, Decodable)]
pub enum TypeKind {
TypeStruct,
TypeEnum,
TypeTrait,
TypeFunction,
TypeModule,
TypeStatic,
TypeStruct,
TypeTrait,
TypeVariant,
}

impl Clean<Type> for ast::Ty {
fn clean(&self) -> Type {
use syntax::ast::*;
debug!("cleaning type `{:?}`", self);
let ctxt = super::ctxtkey.get().unwrap();
let codemap = ctxt.sess().codemap();
debug!("span corresponds to `{}`", codemap.span_to_str(self.span));
match self.node {
TyNil => Unit,
TyPtr(ref m) => RawPointer(m.mutbl.clean(), box m.ty.clean()),
Expand Down Expand Up @@ -1153,7 +1144,7 @@ pub enum ViewPath {
// use source::*;
GlobImport(ImportSource),
// use source::{a, b, c};
ImportList(ImportSource, Vec<ViewListIdent> ),
ImportList(ImportSource, Vec<ViewListIdent>),
}

#[deriving(Clone, Encodable, Decodable)]
Expand Down Expand Up @@ -1298,48 +1289,47 @@ fn resolve_type(path: Path, tpbs: Option<Vec<TyParamBound> >,
core::NotTyped(_) => return Bool
};
debug!("searching for {:?} in defmap", id);
let d = match tycx.def_map.borrow().find(&id) {
let def = match tycx.def_map.borrow().find(&id) {
Some(&k) => k,
None => {
debug!("could not find {:?} in defmap (`{}`)", id, tycx.map.node_to_str(id));
fail!("Unexpected failure: unresolved id not in defmap (this is a bug!)")
}
None => fail!("unresolved id not in defmap")
};

let (def_id, kind) = match d {
ast::DefFn(i, _) => (i, TypeFunction),
match def {
ast::DefSelfTy(i) => return Self(i),
ast::DefTy(i) => (i, TypeEnum),
ast::DefTrait(i) => {
debug!("saw DefTrait in def_to_id");
(i, TypeTrait)
},
ast::DefPrimTy(p) => match p {
ast::TyStr => return String,
ast::TyBool => return Bool,
_ => return Primitive(p)
},
ast::DefTyParam(i, _) => return Generic(i.node),
ast::DefTyParamBinder(i) => return TyParamBinder(i),
_ => {}
};
let did = register_def(&**cx, def);
ResolvedPath { path: path, typarams: tpbs, did: did }
}

fn register_def(cx: &core::DocContext, def: ast::Def) -> ast::DefId {
let (did, kind) = match def {
ast::DefFn(i, _) => (i, TypeFunction),
ast::DefTy(i) => (i, TypeEnum),
ast::DefTrait(i) => (i, TypeTrait),
ast::DefStruct(i) => (i, TypeStruct),
ast::DefTyParamBinder(i) => {
debug!("found a typaram_binder, what is it? {}", i);
return TyParamBinder(i);
},
x => fail!("resolved type maps to a weird def {:?}", x),
ast::DefMod(i) => (i, TypeModule),
ast::DefStatic(i, _) => (i, TypeStatic),
ast::DefVariant(i, _, _) => (i, TypeEnum),
_ => return ast_util::def_id_of_def(def),
};
if ast_util::is_local(def_id) {
ResolvedPath{ path: path, typarams: tpbs, id: def_id.node }
} else {
let fqn = csearch::get_item_path(tycx, def_id);
let fqn = fqn.move_iter().map(|i| i.to_str()).collect();
ExternalPath {
path: path,
typarams: tpbs,
fqn: fqn,
kind: kind,
krate: def_id.krate,
}
}
if ast_util::is_local(did) { return did }
let tcx = match cx.maybe_typed {
core::Typed(ref t) => t,
core::NotTyped(_) => return did
};
let fqn = csearch::get_item_path(tcx, did);
let fqn = fqn.move_iter().map(|i| i.to_str()).collect();
debug!("recording {} => {}", did, fqn);
cx.external_paths.borrow_mut().get_mut_ref().insert(did, (fqn, kind));
return did;
}

fn resolve_use_source(path: Path, id: ast::NodeId) -> ImportSource {
Expand All @@ -1353,7 +1343,7 @@ fn resolve_def(id: ast::NodeId) -> Option<ast::DefId> {
let cx = super::ctxtkey.get().unwrap();
match cx.maybe_typed {
core::Typed(ref tcx) => {
tcx.def_map.borrow().find(&id).map(|&d| ast_util::def_id_of_def(d))
tcx.def_map.borrow().find(&id).map(|&def| register_def(&**cx, def))
}
core::NotTyped(_) => None
}
Expand Down
11 changes: 10 additions & 1 deletion src/librustdoc/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use syntax;

use std::cell::RefCell;
use std::os;
use collections::HashSet;
use collections::{HashSet, HashMap};

use visit_ast::RustdocVisitor;
use clean;
Expand All @@ -31,10 +31,14 @@ pub enum MaybeTyped {
NotTyped(driver::session::Session)
}

pub type ExternalPaths = RefCell<Option<HashMap<ast::DefId,
(Vec<~str>, clean::TypeKind)>>>;

pub struct DocContext {
pub krate: ast::Crate,
pub maybe_typed: MaybeTyped,
pub src: Path,
pub external_paths: ExternalPaths,
}

impl DocContext {
Expand All @@ -49,6 +53,7 @@ impl DocContext {
pub struct CrateAnalysis {
pub exported_items: privacy::ExportedItems,
pub public_items: privacy::PublicItems,
pub external_paths: ExternalPaths,
}

/// Parses, resolves, and typechecks the given crate
Expand Down Expand Up @@ -98,9 +103,11 @@ fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<~str>)
krate: krate,
maybe_typed: Typed(ty_cx),
src: cpath.clone(),
external_paths: RefCell::new(Some(HashMap::new())),
}, CrateAnalysis {
exported_items: exported_items,
public_items: public_items,
external_paths: RefCell::new(None),
})
}

Expand All @@ -116,5 +123,7 @@ pub fn run_core(libs: HashSet<Path>, cfgs: Vec<~str>, path: &Path)
v.clean()
};

let external_paths = ctxt.external_paths.borrow_mut().take();
*analysis.external_paths.borrow_mut() = external_paths;
(krate, analysis)
}
61 changes: 19 additions & 42 deletions src/librustdoc/html/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,41 +146,28 @@ impl fmt::Show for clean::Path {

/// Used when rendering a `ResolvedPath` structure. This invokes the `path`
/// rendering function with the necessary arguments for linking to a local path.
fn resolved_path(w: &mut io::Writer, id: ast::NodeId, p: &clean::Path,
fn resolved_path(w: &mut io::Writer, did: ast::DefId, p: &clean::Path,
print_all: bool) -> fmt::Result {
path(w, p, print_all,
|_cache, loc| { Some("../".repeat(loc.len())) },
|cache, loc| {
if ast_util::is_local(did) {
Some("../".repeat(loc.len()))
} else {
match *cache.extern_locations.get(&did.krate) {
render::Remote(ref s) => Some(s.clone()),
render::Local => Some("../".repeat(loc.len())),
render::Unknown => None,
}
}
},
|cache| {
match cache.paths.find(&id) {
match cache.paths.find(&did) {
None => None,
Some(&(ref fqp, shortty)) => Some((fqp.clone(), shortty))
}
})
}

/// Used when rendering an `ExternalPath` structure. Like `resolved_path` this
/// will invoke `path` with proper linking-style arguments.
fn external_path(w: &mut io::Writer, p: &clean::Path, print_all: bool,
fqn: &[~str], kind: clean::TypeKind,
krate: ast::CrateNum) -> fmt::Result {
path(w, p, print_all,
|cache, loc| {
match *cache.extern_locations.get(&krate) {
render::Remote(ref s) => Some(s.clone()),
render::Local => Some("../".repeat(loc.len())),
render::Unknown => None,
}
},
|_cache| {
Some((Vec::from_slice(fqn), match kind {
clean::TypeStruct => item_type::Struct,
clean::TypeEnum => item_type::Enum,
clean::TypeFunction => item_type::Function,
clean::TypeTrait => item_type::Trait,
}))
})
}

fn path(w: &mut io::Writer, path: &clean::Path, print_all: bool,
root: |&render::Cache, &[~str]| -> Option<~str>,
info: |&render::Cache| -> Option<(Vec<~str> , ItemType)>)
Expand Down Expand Up @@ -298,15 +285,9 @@ impl fmt::Show for clean::Type {
let m = cache_key.get().unwrap();
f.buf.write(m.typarams.get(&id).as_bytes())
}
clean::ResolvedPath{id, typarams: ref tp, path: ref path} => {
try!(resolved_path(f.buf, id, path, false));
tybounds(f.buf, tp)
}
clean::ExternalPath{path: ref path, typarams: ref tp,
fqn: ref fqn, kind, krate} => {
try!(external_path(f.buf, path, false, fqn.as_slice(), kind,
krate))
tybounds(f.buf, tp)
clean::ResolvedPath{ did, ref typarams, ref path} => {
try!(resolved_path(f.buf, did, path, false));
tybounds(f.buf, typarams)
}
clean::Self(..) => f.buf.write("Self".as_bytes()),
clean::Primitive(prim) => {
Expand Down Expand Up @@ -543,10 +524,7 @@ impl fmt::Show for clean::ViewPath {
impl fmt::Show for clean::ImportSource {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.did {
// FIXME: shouldn't be restricted to just local imports
Some(did) if ast_util::is_local(did) => {
resolved_path(f.buf, did.node, &self.path, true)
}
Some(did) => resolved_path(f.buf, did, &self.path, true),
_ => {
for (i, seg) in self.path.segments.iter().enumerate() {
if i > 0 {
Expand All @@ -563,8 +541,7 @@ impl fmt::Show for clean::ImportSource {
impl fmt::Show for clean::ViewListIdent {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.source {
// FIXME: shouldn't be limited to just local imports
Some(did) if ast_util::is_local(did) => {
Some(did) => {
let path = clean::Path {
global: false,
segments: vec!(clean::PathSegment {
Expand All @@ -573,7 +550,7 @@ impl fmt::Show for clean::ViewListIdent {
types: Vec::new(),
})
};
resolved_path(f.buf, did.node, &path, false)
resolved_path(f.buf, did, &path, false)
}
_ => write!(f.buf, "{}", self.name),
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustdoc/html/item_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ impl ItemType {
match *self {
Module => "mod",
Struct => "struct",
Enum => "enum",
Enum => "type",
Function => "fn",
Typedef => "typedef",
Typedef => "type",
Static => "static",
Trait => "trait",
Impl => "impl",
Expand Down
Loading