auto merge of #9691 : alexcrichton/rust/rustdoc, r=cmr
This slurps in the commits from #9684 as well as closing #9539.
This commit is contained in:
commit
8f40641e01
8 changed files with 288 additions and 128 deletions
|
|
@ -26,7 +26,8 @@ Rust extras are part of the standard Rust distribution.
|
|||
url = "https://github.com/mozilla/rust/tree/master/src/libextra")];
|
||||
|
||||
#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
|
||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico")];
|
||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
||||
html_root_url = "http://static.rust-lang.org/doc/master")];
|
||||
|
||||
#[comment = "Rust extras"];
|
||||
#[license = "MIT/ASL2"];
|
||||
|
|
|
|||
|
|
@ -15,11 +15,18 @@ use its = syntax::parse::token::ident_to_str;
|
|||
|
||||
use syntax;
|
||||
use syntax::ast;
|
||||
use syntax::ast_map;
|
||||
use syntax::ast_util;
|
||||
use syntax::attr;
|
||||
use syntax::attr::AttributeMethods;
|
||||
|
||||
use rustc::metadata::cstore;
|
||||
use rustc::metadata::csearch;
|
||||
use rustc::metadata::decoder;
|
||||
|
||||
use std;
|
||||
use std::hashmap::HashMap;
|
||||
|
||||
use doctree;
|
||||
use visit_ast;
|
||||
use std::local_data;
|
||||
|
|
@ -61,19 +68,44 @@ impl<T: Clean<U>, U> Clean<~[U]> for syntax::opt_vec::OptVec<T> {
|
|||
pub struct Crate {
|
||||
name: ~str,
|
||||
module: Option<Item>,
|
||||
externs: HashMap<ast::CrateNum, ExternalCrate>,
|
||||
}
|
||||
|
||||
impl Clean<Crate> for visit_ast::RustdocVisitor {
|
||||
fn clean(&self) -> Crate {
|
||||
use syntax::attr::{find_linkage_metas, last_meta_item_value_str_by_name};
|
||||
let maybe_meta = last_meta_item_value_str_by_name(find_linkage_metas(self.attrs), "name");
|
||||
let maybe_meta = last_meta_item_value_str_by_name(
|
||||
find_linkage_metas(self.attrs), "name");
|
||||
let cx = local_data::get(super::ctxtkey, |x| *x.unwrap());
|
||||
|
||||
let mut externs = HashMap::new();
|
||||
do cstore::iter_crate_data(cx.sess.cstore) |n, meta| {
|
||||
externs.insert(n, meta.clean());
|
||||
}
|
||||
|
||||
Crate {
|
||||
name: match maybe_meta {
|
||||
Some(x) => x.to_owned(),
|
||||
None => fail2!("rustdoc_ng requires a \\#[link(name=\"foo\")] crate attribute"),
|
||||
None => fail2!("rustdoc requires a \\#[link(name=\"foo\")] \
|
||||
crate attribute"),
|
||||
},
|
||||
module: Some(self.module.clean()),
|
||||
externs: externs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Clone, Encodable, Decodable)]
|
||||
pub struct ExternalCrate {
|
||||
name: ~str,
|
||||
attrs: ~[Attribute],
|
||||
}
|
||||
|
||||
impl Clean<ExternalCrate> for cstore::crate_metadata {
|
||||
fn clean(&self) -> ExternalCrate {
|
||||
ExternalCrate {
|
||||
name: self.name.to_owned(),
|
||||
attrs: decoder::get_crate_attributes(self.data).clean()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -542,7 +574,15 @@ pub enum Type {
|
|||
ResolvedPath {
|
||||
path: Path,
|
||||
typarams: Option<~[TyParamBound]>,
|
||||
did: ast::DefId
|
||||
id: ast::NodeId,
|
||||
},
|
||||
/// Same as above, but only external variants
|
||||
ExternalPath {
|
||||
path: Path,
|
||||
typarams: Option<~[TyParamBound]>,
|
||||
fqn: ~[~str],
|
||||
kind: TypeKind,
|
||||
crate: ast::CrateNum,
|
||||
},
|
||||
// I have no idea how to usefully use this.
|
||||
TyParamBinder(ast::NodeId),
|
||||
|
|
@ -572,6 +612,14 @@ pub enum Type {
|
|||
// region, raw, other boxes, mutable
|
||||
}
|
||||
|
||||
#[deriving(Clone, Encodable, Decodable)]
|
||||
pub enum TypeKind {
|
||||
TypeStruct,
|
||||
TypeEnum,
|
||||
TypeTrait,
|
||||
TypeFunction,
|
||||
}
|
||||
|
||||
impl Clean<Type> for ast::Ty {
|
||||
fn clean(&self) -> Type {
|
||||
use syntax::ast::*;
|
||||
|
|
@ -1099,26 +1147,12 @@ fn name_from_pat(p: &ast::Pat) -> ~str {
|
|||
}
|
||||
}
|
||||
|
||||
fn remove_comment_tags(s: &str) -> ~str {
|
||||
if s.starts_with("/") {
|
||||
match s.slice(0,3) {
|
||||
&"///" => return s.slice(3, s.len()).trim().to_owned(),
|
||||
&"/**" | &"/*!" => return s.slice(3, s.len() - 2).trim().to_owned(),
|
||||
_ => return s.trim().to_owned()
|
||||
}
|
||||
} else {
|
||||
return s.to_owned();
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a Type, resolve it using the def_map
|
||||
fn resolve_type(path: Path, tpbs: Option<~[TyParamBound]>,
|
||||
id: ast::NodeId) -> Type {
|
||||
use syntax::ast::*;
|
||||
|
||||
let dm = local_data::get(super::ctxtkey, |x| *x.unwrap()).tycx.def_map;
|
||||
let cx = local_data::get(super::ctxtkey, |x| *x.unwrap());
|
||||
debug2!("searching for {:?} in defmap", id);
|
||||
let d = match dm.find(&id) {
|
||||
let d = match cx.tycx.def_map.find(&id) {
|
||||
Some(k) => k,
|
||||
None => {
|
||||
let ctxt = local_data::get(super::ctxtkey, |x| *x.unwrap());
|
||||
|
|
@ -1128,28 +1162,41 @@ fn resolve_type(path: Path, tpbs: Option<~[TyParamBound]>,
|
|||
}
|
||||
};
|
||||
|
||||
let def_id = match *d {
|
||||
DefFn(i, _) => i,
|
||||
DefSelf(i) | DefSelfTy(i) => return Self(i),
|
||||
DefTy(i) => i,
|
||||
DefTrait(i) => {
|
||||
let (def_id, kind) = match *d {
|
||||
ast::DefFn(i, _) => (i, TypeFunction),
|
||||
ast::DefSelf(i) | ast::DefSelfTy(i) => return Self(i),
|
||||
ast::DefTy(i) => (i, TypeEnum),
|
||||
ast::DefTrait(i) => {
|
||||
debug2!("saw DefTrait in def_to_id");
|
||||
i
|
||||
(i, TypeTrait)
|
||||
},
|
||||
DefPrimTy(p) => match p {
|
||||
ty_str => return String,
|
||||
ty_bool => return Bool,
|
||||
ast::DefPrimTy(p) => match p {
|
||||
ast::ty_str => return String,
|
||||
ast::ty_bool => return Bool,
|
||||
_ => return Primitive(p)
|
||||
},
|
||||
DefTyParam(i, _) => return Generic(i.node),
|
||||
DefStruct(i) => i,
|
||||
DefTyParamBinder(i) => {
|
||||
ast::DefTyParam(i, _) => return Generic(i.node),
|
||||
ast::DefStruct(i) => (i, TypeStruct),
|
||||
ast::DefTyParamBinder(i) => {
|
||||
debug2!("found a typaram_binder, what is it? {}", i);
|
||||
return TyParamBinder(i);
|
||||
},
|
||||
x => fail2!("resolved type maps to a weird def {:?}", x),
|
||||
};
|
||||
ResolvedPath{ path: path, typarams: tpbs, did: def_id }
|
||||
if ast_util::is_local(def_id) {
|
||||
ResolvedPath{ path: path, typarams: tpbs, id: def_id.node }
|
||||
} else {
|
||||
let fqn = csearch::get_item_path(cx.tycx, def_id);
|
||||
let fqn = fqn.move_iter().map(|i| {
|
||||
match i {
|
||||
ast_map::path_mod(id) |
|
||||
ast_map::path_name(id) |
|
||||
ast_map::path_pretty_name(id, _) => id.clean()
|
||||
}
|
||||
}).to_owned_vec();
|
||||
ExternalPath{ path: path, typarams: tpbs, fqn: fqn, kind: kind,
|
||||
crate: def_id.crate }
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_use_source(path: Path, id: ast::NodeId) -> ImportSource {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ use syntax::ast;
|
|||
use syntax::ast_util;
|
||||
|
||||
use clean;
|
||||
use html::render;
|
||||
use html::render::{cache_key, current_location_key};
|
||||
|
||||
pub struct VisSpace(Option<ast::visibility>);
|
||||
|
|
@ -97,8 +98,46 @@ impl fmt::Default for clean::Path {
|
|||
}
|
||||
}
|
||||
|
||||
fn resolved_path(w: &mut io::Writer, did: ast::DefId,
|
||||
path: &clean::Path, print_all: bool) {
|
||||
fn resolved_path(w: &mut io::Writer, id: ast::NodeId, p: &clean::Path,
|
||||
print_all: bool) {
|
||||
path(w, p, print_all,
|
||||
|_cache, loc| {
|
||||
match p.segments[0].name.as_slice() {
|
||||
"super" => Some("../".repeat(loc.len() - 1)),
|
||||
_ => Some("../".repeat(loc.len())),
|
||||
}
|
||||
},
|
||||
|cache| {
|
||||
match cache.paths.find(&id) {
|
||||
None => None,
|
||||
Some(&(ref fqp, shortty)) => Some((fqp.clone(), shortty))
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn external_path(w: &mut io::Writer, p: &clean::Path, print_all: bool,
|
||||
fqn: &[~str], kind: clean::TypeKind, crate: ast::CrateNum) {
|
||||
path(w, p, print_all,
|
||||
|cache, loc| {
|
||||
match *cache.extern_locations.get(&crate) {
|
||||
render::Remote(ref s) => Some(s.clone()),
|
||||
render::Local => Some("../".repeat(loc.len())),
|
||||
render::Unknown => None,
|
||||
}
|
||||
},
|
||||
|_cache| {
|
||||
Some((fqn.to_owned(), match kind {
|
||||
clean::TypeStruct => "struct",
|
||||
clean::TypeEnum => "enum",
|
||||
clean::TypeFunction => "fn",
|
||||
clean::TypeTrait => "trait",
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
fn path(w: &mut io::Writer, path: &clean::Path, print_all: bool,
|
||||
root: &fn(&render::Cache, &[~str]) -> Option<~str>,
|
||||
info: &fn(&render::Cache) -> Option<(~[~str], &'static str)>) {
|
||||
// The generics will get written to both the title and link
|
||||
let mut generics = ~"";
|
||||
let last = path.segments.last();
|
||||
|
|
@ -121,51 +160,49 @@ fn resolved_path(w: &mut io::Writer, did: ast::DefId,
|
|||
do local_data::get(current_location_key) |loc| {
|
||||
let loc = loc.unwrap();
|
||||
|
||||
if print_all {
|
||||
let mut root = match path.segments[0].name.as_slice() {
|
||||
"super" => ~"../",
|
||||
"self" => ~"",
|
||||
_ => "../".repeat(loc.len() - 1),
|
||||
};
|
||||
let amt = path.segments.len() - 1;
|
||||
for seg in path.segments.slice_to(amt).iter() {
|
||||
if "super" == seg.name || "self" == seg.name {
|
||||
write!(w, "{}::", seg.name);
|
||||
} else {
|
||||
root.push_str(seg.name);
|
||||
root.push_str("/");
|
||||
write!(w, "<a class='mod'
|
||||
href='{}index.html'>{}</a>::",
|
||||
root,
|
||||
seg.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do local_data::get(cache_key) |cache| {
|
||||
do cache.unwrap().read |cache| {
|
||||
match cache.paths.find(&did.node) {
|
||||
// This is a documented path, link to it!
|
||||
// FIXME(#9539): this is_local check should not exist
|
||||
Some(&(ref fqp, shortty)) if ast_util::is_local(did) => {
|
||||
let fqn = fqp.connect("::");
|
||||
let same = loc.iter().zip(fqp.iter())
|
||||
.take_while(|&(a, b)| *a == *b).len();
|
||||
let abs_root = root(cache, loc.as_slice());
|
||||
let rel_root = match path.segments[0].name.as_slice() {
|
||||
"self" => Some(~"./"),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let mut url = ~"";
|
||||
if "super" == path.segments[0].name {
|
||||
url.push_str("../");
|
||||
} else if "self" != path.segments[0].name {
|
||||
url.push_str("../".repeat(loc.len() - same));
|
||||
}
|
||||
if same < fqp.len() {
|
||||
let remaining = fqp.slice_from(same);
|
||||
let to_link = remaining.slice_to(remaining.len() - 1);
|
||||
for component in to_link.iter() {
|
||||
url.push_str(*component);
|
||||
url.push_str("/");
|
||||
if print_all {
|
||||
let amt = path.segments.len() - 1;
|
||||
match rel_root {
|
||||
Some(root) => {
|
||||
let mut root = root;
|
||||
for seg in path.segments.slice_to(amt).iter() {
|
||||
if "super" == seg.name || "self" == seg.name {
|
||||
write!(w, "{}::", seg.name);
|
||||
} else {
|
||||
root.push_str(seg.name);
|
||||
root.push_str("/");
|
||||
write!(w, "<a class='mod'
|
||||
href='{}index.html'>{}</a>::",
|
||||
root,
|
||||
seg.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
for seg in path.segments.slice_to(amt).iter() {
|
||||
write!(w, "{}::", seg.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match info(cache) {
|
||||
// This is a documented path, link to it!
|
||||
Some((ref fqp, shortty)) if abs_root.is_some() => {
|
||||
let mut url = abs_root.unwrap();
|
||||
let to_link = fqp.slice_to(fqp.len() - 1);
|
||||
for component in to_link.iter() {
|
||||
url.push_str(*component);
|
||||
url.push_str("/");
|
||||
}
|
||||
match shortty {
|
||||
"mod" => {
|
||||
url.push_str(*fqp.last());
|
||||
|
|
@ -178,24 +215,35 @@ fn resolved_path(w: &mut io::Writer, did: ast::DefId,
|
|||
url.push_str(".html");
|
||||
}
|
||||
}
|
||||
write!(w, "<a class='{}' href='{}' title='{}'>{}</a>{}",
|
||||
shortty, url, fqn, last.name, generics);
|
||||
|
||||
write!(w, "<a class='{}' href='{}' title='{}'>{}</a>",
|
||||
shortty, url, fqp.connect("::"), last.name);
|
||||
}
|
||||
|
||||
_ => {
|
||||
if print_all {
|
||||
let amt = path.segments.len() - 1;
|
||||
for seg in path.segments.iter().take(amt) {
|
||||
write!(w, "{}::", seg.name);
|
||||
}
|
||||
}
|
||||
write!(w, "{}{}", last.name, generics);
|
||||
write!(w, "{}", last.name);
|
||||
}
|
||||
};
|
||||
}
|
||||
write!(w, "{}", generics);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn typarams(w: &mut io::Writer, typarams: &Option<~[clean::TyParamBound]>) {
|
||||
match *typarams {
|
||||
Some(ref params) => {
|
||||
write!(w, "<");
|
||||
for (i, param) in params.iter().enumerate() {
|
||||
if i > 0 { write!(w, ", "); }
|
||||
write!(w, "{}", *param);
|
||||
}
|
||||
write!(w, ">");
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Default for clean::Type {
|
||||
fn fmt(g: &clean::Type, f: &mut fmt::Formatter) {
|
||||
match *g {
|
||||
|
|
@ -206,19 +254,14 @@ impl fmt::Default for clean::Type {
|
|||
}
|
||||
}
|
||||
}
|
||||
clean::ResolvedPath{did, typarams: ref typarams, path: ref path} => {
|
||||
resolved_path(f.buf, did, path, false);
|
||||
match *typarams {
|
||||
Some(ref params) => {
|
||||
f.buf.write("<".as_bytes());
|
||||
for (i, param) in params.iter().enumerate() {
|
||||
if i > 0 { f.buf.write(", ".as_bytes()) }
|
||||
write!(f.buf, "{}", *param);
|
||||
}
|
||||
f.buf.write(">".as_bytes());
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
clean::ResolvedPath{id, typarams: ref tp, path: ref path} => {
|
||||
resolved_path(f.buf, id, path, false);
|
||||
typarams(f.buf, tp);
|
||||
}
|
||||
clean::ExternalPath{path: ref path, typarams: ref tp,
|
||||
fqn: ref fqn, kind, crate} => {
|
||||
external_path(f.buf, path, false, fqn.as_slice(), kind, crate);
|
||||
typarams(f.buf, tp);
|
||||
}
|
||||
clean::Self(*) => f.buf.write("Self".as_bytes()),
|
||||
clean::Primitive(prim) => {
|
||||
|
|
@ -417,8 +460,9 @@ impl fmt::Default for clean::ViewPath {
|
|||
impl fmt::Default for clean::ImportSource {
|
||||
fn fmt(v: &clean::ImportSource, f: &mut fmt::Formatter) {
|
||||
match v.did {
|
||||
Some(did) => {
|
||||
resolved_path(f.buf, did, &v.path, true);
|
||||
// XXX: shouldn't be restricted to just local imports
|
||||
Some(did) if ast_util::is_local(did) => {
|
||||
resolved_path(f.buf, did.node, &v.path, true);
|
||||
}
|
||||
_ => {
|
||||
for (i, seg) in v.path.segments.iter().enumerate() {
|
||||
|
|
@ -433,7 +477,8 @@ impl fmt::Default for clean::ImportSource {
|
|||
impl fmt::Default for clean::ViewListIdent {
|
||||
fn fmt(v: &clean::ViewListIdent, f: &mut fmt::Formatter) {
|
||||
match v.source {
|
||||
Some(did) => {
|
||||
// XXX: shouldn't be limited to just local imports
|
||||
Some(did) if ast_util::is_local(did) => {
|
||||
let path = clean::Path {
|
||||
global: false,
|
||||
segments: ~[clean::PathSegment {
|
||||
|
|
@ -442,7 +487,7 @@ impl fmt::Default for clean::ViewListIdent {
|
|||
types: ~[],
|
||||
}]
|
||||
};
|
||||
resolved_path(f.buf, did, &path, false);
|
||||
resolved_path(f.buf, did.node, &path, false);
|
||||
}
|
||||
_ => write!(f.buf, "{}", v.name),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,10 +28,8 @@ use std::vec;
|
|||
use extra::arc::RWArc;
|
||||
use extra::json::ToJson;
|
||||
use extra::sort;
|
||||
use extra::time;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::ast_util::is_local;
|
||||
use syntax::attr;
|
||||
|
||||
use clean;
|
||||
|
|
@ -52,6 +50,12 @@ pub struct Context {
|
|||
include_sources: bool,
|
||||
}
|
||||
|
||||
pub enum ExternalLocation {
|
||||
Remote(~str), // remote url root of the documentation
|
||||
Local, // inside local folder
|
||||
Unknown, // unknown where the documentation is
|
||||
}
|
||||
|
||||
enum Implementor {
|
||||
PathType(clean::Type),
|
||||
OtherType(clean::Generics, /* trait */ clean::Type, /* for */ clean::Type),
|
||||
|
|
@ -68,6 +72,8 @@ struct Cache {
|
|||
traits: HashMap<ast::NodeId, HashMap<~str, ~str>>,
|
||||
// trait id => implementors of the trait
|
||||
implementors: HashMap<ast::NodeId, ~[Implementor]>,
|
||||
// crate number => where is the crate's dox located at
|
||||
extern_locations: HashMap<ast::CrateNum, ExternalLocation>,
|
||||
|
||||
priv stack: ~[~str],
|
||||
priv parent_stack: ~[ast::NodeId],
|
||||
|
|
@ -142,6 +148,7 @@ pub fn run(mut crate: clean::Crate, dst: Path) {
|
|||
stack: ~[],
|
||||
parent_stack: ~[],
|
||||
search_index: ~[],
|
||||
extern_locations: HashMap::new(),
|
||||
};
|
||||
cache.stack.push(crate.name.clone());
|
||||
crate = cache.fold_crate(crate);
|
||||
|
|
@ -154,6 +161,7 @@ pub fn run(mut crate: clean::Crate, dst: Path) {
|
|||
write(dst.push("main.css"), include_str!("static/main.css"));
|
||||
write(dst.push("normalize.css"), include_str!("static/normalize.css"));
|
||||
|
||||
// Publish the search index
|
||||
{
|
||||
let dst = dst.push("search-index.js");
|
||||
let mut w = BufferedWriter::new(dst.open_writer(io::CreateOrTruncate));
|
||||
|
|
@ -180,9 +188,9 @@ pub fn run(mut crate: clean::Crate, dst: Path) {
|
|||
w.flush();
|
||||
}
|
||||
|
||||
info2!("emitting source files");
|
||||
let started = time::precise_time_ns();
|
||||
// Render all source files (this may turn into a giant no-op)
|
||||
{
|
||||
info2!("emitting source files");
|
||||
let dst = cx.dst.push("src");
|
||||
mkdir(&dst);
|
||||
let dst = dst.push(crate.name);
|
||||
|
|
@ -194,14 +202,13 @@ pub fn run(mut crate: clean::Crate, dst: Path) {
|
|||
};
|
||||
crate = folder.fold_crate(crate);
|
||||
}
|
||||
let ended = time::precise_time_ns();
|
||||
info2!("Took {:.03f}s", (ended as f64 - started as f64) / 1e9f64);
|
||||
|
||||
info2!("rendering the whole crate");
|
||||
let started = time::precise_time_ns();
|
||||
for (&n, e) in crate.externs.iter() {
|
||||
cache.extern_locations.insert(n, extern_location(e, &cx.dst));
|
||||
}
|
||||
|
||||
// And finally render the whole crate's documentation
|
||||
cx.crate(crate, cache);
|
||||
let ended = time::precise_time_ns();
|
||||
info2!("Took {:.03f}s", (ended as f64 - started as f64) / 1e9f64);
|
||||
}
|
||||
|
||||
fn write(dst: Path, contents: &str) {
|
||||
|
|
@ -235,6 +242,38 @@ fn clean_srcpath(src: &str, f: &fn(&str)) {
|
|||
}
|
||||
}
|
||||
|
||||
fn extern_location(e: &clean::ExternalCrate, dst: &Path) -> ExternalLocation {
|
||||
// See if there's documentation generated into the local directory
|
||||
let local_location = dst.push(e.name);
|
||||
if local_location.is_dir() {
|
||||
return Local;
|
||||
}
|
||||
|
||||
// Failing that, see if there's an attribute specifying where to find this
|
||||
// external crate
|
||||
for attr in e.attrs.iter() {
|
||||
match *attr {
|
||||
clean::List(~"doc", ref list) => {
|
||||
for attr in list.iter() {
|
||||
match *attr {
|
||||
clean::NameValue(~"html_root_url", ref s) => {
|
||||
if s.ends_with("/") {
|
||||
return Remote(s.to_owned());
|
||||
}
|
||||
return Remote(*s + "/");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// Well, at least we tried.
|
||||
return Unknown;
|
||||
}
|
||||
|
||||
impl<'self> DocFolder for SourceCollector<'self> {
|
||||
fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
|
||||
if self.cx.include_sources && !self.seen.contains(&item.source.filename) {
|
||||
|
|
@ -353,8 +392,7 @@ impl DocFolder for Cache {
|
|||
match item.inner {
|
||||
clean::ImplItem(ref i) => {
|
||||
match i.trait_ {
|
||||
Some(clean::ResolvedPath{ did, _ }) if is_local(did) => {
|
||||
let id = did.node;
|
||||
Some(clean::ResolvedPath{ id, _ }) => {
|
||||
let v = do self.implementors.find_or_insert_with(id) |_|{
|
||||
~[]
|
||||
};
|
||||
|
|
@ -441,8 +479,8 @@ impl DocFolder for Cache {
|
|||
}
|
||||
clean::ImplItem(ref i) => {
|
||||
match i.for_ {
|
||||
clean::ResolvedPath{ did, _ } if is_local(did) => {
|
||||
self.parent_stack.push(did.node); true
|
||||
clean::ResolvedPath{ id, _ } => {
|
||||
self.parent_stack.push(id); true
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
|
|
@ -457,8 +495,7 @@ impl DocFolder for Cache {
|
|||
match item {
|
||||
clean::Item{ attrs, inner: clean::ImplItem(i), _ } => {
|
||||
match i.for_ {
|
||||
clean::ResolvedPath { did, _ } if is_local(did) => {
|
||||
let id = did.node;
|
||||
clean::ResolvedPath { id, _ } => {
|
||||
let v = do self.impls.find_or_insert_with(id) |_| {
|
||||
~[]
|
||||
};
|
||||
|
|
@ -714,13 +751,18 @@ impl<'self> fmt::Default for Item<'self> {
|
|||
do clean_srcpath(it.item.source.filename) |component| {
|
||||
path.push(component.to_owned());
|
||||
}
|
||||
let href = if it.item.source.loline == it.item.source.hiline {
|
||||
format!("{}", it.item.source.loline)
|
||||
} else {
|
||||
format!("{}-{}", it.item.source.loline, it.item.source.hiline)
|
||||
};
|
||||
write!(fmt.buf,
|
||||
"<a class='source'
|
||||
href='{root}src/{crate}/{path}.html\\#{line}'>[src]</a>",
|
||||
href='{root}src/{crate}/{path}.html\\#{href}'>[src]</a>",
|
||||
root = it.cx.root_path,
|
||||
crate = it.cx.layout.crate,
|
||||
path = path.connect("/"),
|
||||
line = it.item.source.loline);
|
||||
href = href);
|
||||
}
|
||||
|
||||
// Write the breadcrumb trail header for the top
|
||||
|
|
@ -1253,7 +1295,7 @@ fn render_impl(w: &mut io::Writer, i: &clean::Impl, dox: &Option<~str>) {
|
|||
Some(ref ty) => {
|
||||
write!(w, "{} for ", *ty);
|
||||
match *ty {
|
||||
clean::ResolvedPath { did, _ } => Some(did),
|
||||
clean::ResolvedPath { id, _ } => Some(id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -1284,8 +1326,7 @@ fn render_impl(w: &mut io::Writer, i: &clean::Impl, dox: &Option<~str>) {
|
|||
// No documentation? Attempt to slurp in the trait's documentation
|
||||
let trait_id = match trait_id {
|
||||
None => continue,
|
||||
Some(id) if is_local(id) => continue,
|
||||
Some(id) => id.node,
|
||||
Some(id) => id,
|
||||
};
|
||||
do local_data::get(cache_key) |cache| {
|
||||
do cache.unwrap().read |cache| {
|
||||
|
|
|
|||
|
|
@ -118,9 +118,16 @@ body {
|
|||
.content h1 { margin-top: 0; }
|
||||
.content h1, .content h2 { margin-left: -20px; }
|
||||
.content pre { padding: 20px; }
|
||||
|
||||
.content.source pre.rust {
|
||||
white-space: pre;
|
||||
overflow: auto;
|
||||
padding-left: 0;
|
||||
}
|
||||
.content pre.line-numbers { float: left; border: none; }
|
||||
.line-numbers span { color: #c67e2d; }
|
||||
.line-numbers .line-highlighted {
|
||||
background-color: #fff871;
|
||||
}
|
||||
|
||||
.content .highlighted {
|
||||
cursor: pointer;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,25 @@
|
|||
resizeShortBlocks();
|
||||
$(window).on('resize', resizeShortBlocks);
|
||||
|
||||
function highlightSourceLines() {
|
||||
var i, from, to, match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/);
|
||||
if (match) {
|
||||
from = parseInt(match[1], 10);
|
||||
to = Math.min(50000, parseInt(match[2] || match[1], 10));
|
||||
from = Math.min(from, to);
|
||||
if ($('#' + from).length === 0) {
|
||||
return;
|
||||
}
|
||||
$('#' + from)[0].scrollIntoView();
|
||||
$('.line-numbers span').removeClass('line-highlighted');
|
||||
for (i = from; i <= to; i += 1) {
|
||||
$('#' + i).addClass('line-highlighted');
|
||||
}
|
||||
}
|
||||
}
|
||||
highlightSourceLines();
|
||||
$(window).on('hashchange', highlightSourceLines);
|
||||
|
||||
$(document).on('keyup', function (e) {
|
||||
if (document.activeElement.tagName === 'INPUT') {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ use std::uint;
|
|||
use std::hashmap::HashSet;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::ast_util::is_local;
|
||||
|
||||
use clean;
|
||||
use clean::Item;
|
||||
|
|
@ -131,8 +130,8 @@ pub fn strip_private(mut crate: clean::Crate) -> plugins::PluginResult {
|
|||
match i.inner {
|
||||
clean::ImplItem(ref imp) => {
|
||||
match imp.trait_ {
|
||||
Some(clean::ResolvedPath{ did, _ }) => {
|
||||
if is_local(did) && !self.contains(&did.node) {
|
||||
Some(clean::ResolvedPath{ id, _ }) => {
|
||||
if !self.contains(&id) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,8 @@ they contained the following prologue:
|
|||
#[crate_type = "lib"];
|
||||
|
||||
#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
|
||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico")];
|
||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
||||
html_root_url = "http://static.rust-lang.org/doc/master")];
|
||||
|
||||
// Don't link to std. We are std.
|
||||
#[no_std];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue