]> git.lizzy.rs Git - rust.git/commitdiff
rustdoc: Move inlining to its own module
authorAlex Crichton <alex@alexcrichton.com>
Sat, 24 May 2014 18:56:38 +0000 (11:56 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Sun, 25 May 2014 20:26:46 +0000 (13:26 -0700)
src/doc/rustdoc.md
src/librustc/metadata/csearch.rs
src/librustc/metadata/decoder.rs
src/librustdoc/clean.rs [deleted file]
src/librustdoc/clean/inline.rs [new file with mode: 0644]
src/librustdoc/clean/mod.rs [new file with mode: 0644]
src/librustdoc/html/render.rs
src/librustdoc/html/static/main.js
src/libstd/lib.rs
src/libstd/prelude.rs

index 625a7a6d802bee6475b7df193870581db01dd884..1034c776ea6dd59137c305e66e84bc79f9e064fa 100644 (file)
@@ -41,7 +41,9 @@ pub fn recalibrate() {
 # }
 ~~~
 
-Documentation can also be controlled via the `doc` attribute on items.
+Documentation can also be controlled via the `doc` attribute on items. This is
+implicitly done by the compiler when using the above form of doc comments
+(converting the slash-based comments to `#[doc]` attributes).
 
 ~~~
 #[doc = "
@@ -50,6 +52,7 @@ Calculates the factorial of a number.
 Given the input integer `n`, this function will calculate `n!` and return it.
 "]
 pub fn factorial(n: int) -> int { if n < 2 {1} else {n * factorial(n)} }
+# fn main() {}
 ~~~
 
 The `doc` attribute can also be used to control how rustdoc emits documentation
@@ -60,6 +63,7 @@ in some cases.
 // `pub use` reaches across crates, but this behavior can also be disabled.
 #[doc(no_inline)]
 pub use std::option::Option;
+# fn main() {}
 ```
 
 Doc comments are markdown, and are currently parsed with the
index d7f603d19092d496d3a963732471297fb34054df..d407cc046807b650973bf726bea468ee8f50b720 100644 (file)
@@ -308,7 +308,7 @@ pub fn get_missing_lang_items(cstore: &cstore::CStore, cnum: ast::CrateNum)
 }
 
 pub fn get_method_arg_names(cstore: &cstore::CStore, did: ast::DefId)
-    -> Vec<StrBuf>
+    -> Vec<String>
 {
     let cdata = cstore.get_crate_data(did.krate);
     decoder::get_method_arg_names(&*cdata, did.node)
index 26149785653fd87b8af358ba05f989875d0c849f..e8be05feae80630af665fd359c974c59d7543165 100644 (file)
@@ -1310,7 +1310,7 @@ pub fn get_missing_lang_items(cdata: Cmd)
     return result;
 }
 
-pub fn get_method_arg_names(cdata: Cmd, id: ast::NodeId) -> Vec<StrBuf> {
+pub fn get_method_arg_names(cdata: Cmd, id: ast::NodeId) -> Vec<String> {
     let mut ret = Vec::new();
     let method_doc = lookup_item(id, cdata.data());
     match reader::maybe_get_doc(method_doc, tag_method_argument_names) {
diff --git a/src/librustdoc/clean.rs b/src/librustdoc/clean.rs
deleted file mode 100644 (file)
index ab95341..0000000
+++ /dev/null
@@ -1,2083 +0,0 @@
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! This module contains the "cleaned" pieces of the AST, and the functions
-//! that clean them.
-
-use syntax;
-use syntax::ast;
-use syntax::ast_util;
-use syntax::attr;
-use syntax::attr::{AttributeMethods, AttrMetaMethods};
-use syntax::codemap::Pos;
-use syntax::parse::token::InternedString;
-use syntax::parse::token;
-
-use rustc::back::link;
-use rustc::driver::driver;
-use rustc::metadata::cstore;
-use rustc::metadata::csearch;
-use rustc::metadata::decoder;
-use rustc::middle::ty;
-
-use std::rc::Rc;
-
-use core;
-use doctree;
-use visit_ast;
-
-/// A stable identifier to the particular version of JSON output.
-/// Increment this when the `Crate` and related structures change.
-pub static SCHEMA_VERSION: &'static str = "0.8.2";
-
-pub trait Clean<T> {
-    fn clean(&self) -> T;
-}
-
-impl<T: Clean<U>, U> Clean<Vec<U>> for Vec<T> {
-    fn clean(&self) -> Vec<U> {
-        self.iter().map(|x| x.clean()).collect()
-    }
-}
-
-impl<T: Clean<U>, U> Clean<U> for @T {
-    fn clean(&self) -> U {
-        (**self).clean()
-    }
-}
-
-impl<T: Clean<U>, U> Clean<U> for Rc<T> {
-    fn clean(&self) -> U {
-        (**self).clean()
-    }
-}
-
-impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
-    fn clean(&self) -> Option<U> {
-        match self {
-            &None => None,
-            &Some(ref v) => Some(v.clean())
-        }
-    }
-}
-
-impl<T: Clean<U>, U> Clean<Vec<U>> for syntax::owned_slice::OwnedSlice<T> {
-    fn clean(&self) -> Vec<U> {
-        self.iter().map(|x| x.clean()).collect()
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct Crate {
-    pub name: String,
-    pub module: Option<Item>,
-    pub externs: Vec<(ast::CrateNum, ExternalCrate)>,
-}
-
-impl<'a> Clean<Crate> for visit_ast::RustdocVisitor<'a> {
-    fn clean(&self) -> Crate {
-        let cx = super::ctxtkey.get().unwrap();
-
-        let mut externs = Vec::new();
-        cx.sess().cstore.iter_crate_data(|n, meta| {
-            externs.push((n, meta.clean()));
-        });
-
-        let input = driver::FileInput(cx.src.clone());
-        let t_outputs = driver::build_output_filenames(&input,
-                                                       &None,
-                                                       &None,
-                                                       self.attrs.as_slice(),
-                                                       cx.sess());
-        let id = link::find_crate_id(self.attrs.as_slice(),
-                                     t_outputs.out_filestem.as_slice());
-        Crate {
-            name: id.name.to_strbuf(),
-            module: Some(self.module.clean()),
-            externs: externs,
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct ExternalCrate {
-    pub name: String,
-    pub attrs: Vec<Attribute>,
-}
-
-impl Clean<ExternalCrate> for cstore::crate_metadata {
-    fn clean(&self) -> ExternalCrate {
-        ExternalCrate {
-            name: self.name.to_strbuf(),
-            attrs: decoder::get_crate_attributes(self.data()).clean()
-                                                             .move_iter()
-                                                             .collect(),
-        }
-    }
-}
-
-/// Anything with a source location and set of attributes and, optionally, a
-/// name. That is, anything that can be documented. This doesn't correspond
-/// directly to the AST's concept of an item; it's a strict superset.
-#[deriving(Clone, Encodable, Decodable)]
-pub struct Item {
-    /// Stringified span
-    pub source: Span,
-    /// Not everything has a name. E.g., impls
-    pub name: Option<String>,
-    pub attrs: Vec<Attribute> ,
-    pub inner: ItemEnum,
-    pub visibility: Option<Visibility>,
-    pub def_id: ast::DefId,
-}
-
-impl Item {
-    /// Finds the `doc` attribute as a List and returns the list of attributes
-    /// nested inside.
-    pub fn doc_list<'a>(&'a self) -> Option<&'a [Attribute]> {
-        for attr in self.attrs.iter() {
-            match *attr {
-                List(ref x, ref list) if "doc" == x.as_slice() => {
-                    return Some(list.as_slice());
-                }
-                _ => {}
-            }
-        }
-        return None;
-    }
-
-    /// Finds the `doc` attribute as a NameValue and returns the corresponding
-    /// value found.
-    pub fn doc_value<'a>(&'a self) -> Option<&'a str> {
-        for attr in self.attrs.iter() {
-            match *attr {
-                NameValue(ref x, ref v) if "doc" == x.as_slice() => {
-                    return Some(v.as_slice());
-                }
-                _ => {}
-            }
-        }
-        return None;
-    }
-
-    pub fn is_hidden_from_doc(&self) -> bool {
-        match self.doc_list() {
-            Some(ref l) => {
-                for innerattr in l.iter() {
-                    match *innerattr {
-                        Word(ref s) if "hidden" == s.as_slice() => {
-                            return true
-                        }
-                        _ => (),
-                    }
-                }
-            },
-            None => ()
-        }
-        return false;
-    }
-
-    pub fn is_mod(&self) -> bool {
-        match self.inner { ModuleItem(..) => true, _ => false }
-    }
-    pub fn is_trait(&self) -> bool {
-        match self.inner { TraitItem(..) => true, _ => false }
-    }
-    pub fn is_struct(&self) -> bool {
-        match self.inner { StructItem(..) => true, _ => false }
-    }
-    pub fn is_enum(&self) -> bool {
-        match self.inner { EnumItem(..) => true, _ => false }
-    }
-    pub fn is_fn(&self) -> bool {
-        match self.inner { FunctionItem(..) => true, _ => false }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub enum ItemEnum {
-    StructItem(Struct),
-    EnumItem(Enum),
-    FunctionItem(Function),
-    ModuleItem(Module),
-    TypedefItem(Typedef),
-    StaticItem(Static),
-    TraitItem(Trait),
-    ImplItem(Impl),
-    /// `use` and `extern crate`
-    ViewItemItem(ViewItem),
-    /// A method signature only. Used for required methods in traits (ie,
-    /// non-default-methods).
-    TyMethodItem(TyMethod),
-    /// A method with a body.
-    MethodItem(Method),
-    StructFieldItem(StructField),
-    VariantItem(Variant),
-    /// `fn`s from an extern block
-    ForeignFunctionItem(Function),
-    /// `static`s from an extern block
-    ForeignStaticItem(Static),
-    MacroItem(Macro),
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct Module {
-    pub items: Vec<Item>,
-    pub is_crate: bool,
-}
-
-impl Clean<Item> for doctree::Module {
-    fn clean(&self) -> Item {
-        let name = if self.name.is_some() {
-            self.name.unwrap().clean()
-        } else {
-            "".to_strbuf()
-        };
-        let mut foreigns = Vec::new();
-        for subforeigns in self.foreigns.clean().move_iter() {
-            for foreign in subforeigns.move_iter() {
-                foreigns.push(foreign)
-            }
-        }
-        let items: Vec<Vec<Item> > = vec!(
-            self.structs.clean().move_iter().collect(),
-            self.enums.clean().move_iter().collect(),
-            self.fns.clean().move_iter().collect(),
-            foreigns,
-            self.mods.clean().move_iter().collect(),
-            self.typedefs.clean().move_iter().collect(),
-            self.statics.clean().move_iter().collect(),
-            self.traits.clean().move_iter().collect(),
-            self.impls.clean().move_iter().collect(),
-            self.view_items.clean().move_iter()
-                           .flat_map(|s| s.move_iter()).collect(),
-            self.macros.clean().move_iter().collect()
-        );
-
-        // determine if we should display the inner contents or
-        // the outer `mod` item for the source code.
-        let where = {
-            let ctxt = super::ctxtkey.get().unwrap();
-            let cm = ctxt.sess().codemap();
-            let outer = cm.lookup_char_pos(self.where_outer.lo);
-            let inner = cm.lookup_char_pos(self.where_inner.lo);
-            if outer.file.start_pos == inner.file.start_pos {
-                // mod foo { ... }
-                self.where_outer
-            } else {
-                // mod foo; (and a separate FileMap for the contents)
-                self.where_inner
-            }
-        };
-
-        Item {
-            name: Some(name),
-            attrs: self.attrs.clean(),
-            source: where.clean(),
-            visibility: self.vis.clean(),
-            def_id: ast_util::local_def(self.id),
-            inner: ModuleItem(Module {
-               is_crate: self.is_crate,
-               items: items.iter()
-                           .flat_map(|x| x.iter().map(|x| (*x).clone()))
-                           .collect(),
-            })
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub enum Attribute {
-    Word(String),
-    List(String, Vec<Attribute> ),
-    NameValue(String, String)
-}
-
-impl Clean<Attribute> for ast::MetaItem {
-    fn clean(&self) -> Attribute {
-        match self.node {
-            ast::MetaWord(ref s) => Word(s.get().to_strbuf()),
-            ast::MetaList(ref s, ref l) => {
-                List(s.get().to_strbuf(), l.clean().move_iter().collect())
-            }
-            ast::MetaNameValue(ref s, ref v) => {
-                NameValue(s.get().to_strbuf(), lit_to_str(v))
-            }
-        }
-    }
-}
-
-impl Clean<Attribute> for ast::Attribute {
-    fn clean(&self) -> Attribute {
-        self.desugar_doc().node.value.clean()
-    }
-}
-
-// This is a rough approximation that gets us what we want.
-impl attr::AttrMetaMethods for Attribute {
-    fn name(&self) -> InternedString {
-        match *self {
-            Word(ref n) | List(ref n, _) | NameValue(ref n, _) => {
-                token::intern_and_get_ident(n.as_slice())
-            }
-        }
-    }
-
-    fn value_str(&self) -> Option<InternedString> {
-        match *self {
-            NameValue(_, ref v) => {
-                Some(token::intern_and_get_ident(v.as_slice()))
-            }
-            _ => None,
-        }
-    }
-    fn meta_item_list<'a>(&'a self) -> Option<&'a [@ast::MetaItem]> { None }
-    fn name_str_pair(&self) -> Option<(InternedString, InternedString)> {
-        None
-    }
-}
-impl<'a> attr::AttrMetaMethods for &'a Attribute {
-    fn name(&self) -> InternedString { (**self).name() }
-    fn value_str(&self) -> Option<InternedString> { (**self).value_str() }
-    fn meta_item_list<'a>(&'a self) -> Option<&'a [@ast::MetaItem]> { None }
-    fn name_str_pair(&self) -> Option<(InternedString, InternedString)> {
-        None
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct TyParam {
-    pub name: String,
-    pub did: ast::DefId,
-    pub bounds: Vec<TyParamBound>,
-}
-
-impl Clean<TyParam> for ast::TyParam {
-    fn clean(&self) -> TyParam {
-        TyParam {
-            name: self.ident.clean(),
-            did: ast::DefId { krate: ast::LOCAL_CRATE, node: self.id },
-            bounds: self.bounds.clean().move_iter().collect(),
-        }
-    }
-}
-
-impl Clean<TyParam> for ty::TypeParameterDef {
-    fn clean(&self) -> TyParam {
-        let cx = super::ctxtkey.get().unwrap();
-        cx.external_typarams.borrow_mut().get_mut_ref().insert(self.def_id,
-                                                               self.ident.clean());
-        TyParam {
-            name: self.ident.clean(),
-            did: self.def_id,
-            bounds: self.bounds.clean(),
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub enum TyParamBound {
-    RegionBound,
-    TraitBound(Type)
-}
-
-impl Clean<TyParamBound> for ast::TyParamBound {
-    fn clean(&self) -> TyParamBound {
-        match *self {
-            ast::StaticRegionTyParamBound => RegionBound,
-            ast::OtherRegionTyParamBound(_) => RegionBound,
-            ast::TraitTyParamBound(ref t) => TraitBound(t.clean()),
-        }
-    }
-}
-
-fn external_path(name: &str) -> Path {
-    Path {
-        global: false,
-        segments: vec![PathSegment {
-            name: name.to_strbuf(),
-            lifetimes: Vec::new(),
-            types: Vec::new(),
-        }]
-    }
-}
-
-impl Clean<TyParamBound> for ty::BuiltinBound {
-    fn clean(&self) -> TyParamBound {
-        let cx = super::ctxtkey.get().unwrap();
-        let tcx = match cx.maybe_typed {
-            core::Typed(ref tcx) => tcx,
-            core::NotTyped(_) => return RegionBound,
-        };
-        let (did, path) = match *self {
-            ty::BoundStatic => return RegionBound,
-            ty::BoundSend =>
-                (tcx.lang_items.send_trait().unwrap(), external_path("Send")),
-            ty::BoundSized =>
-                (tcx.lang_items.sized_trait().unwrap(), external_path("Sized")),
-            ty::BoundCopy =>
-                (tcx.lang_items.copy_trait().unwrap(), external_path("Copy")),
-            ty::BoundShare =>
-                (tcx.lang_items.share_trait().unwrap(), external_path("Share")),
-        };
-        let fqn = csearch::get_item_path(tcx, did);
-        let fqn = fqn.move_iter().map(|i| i.to_str().to_strbuf()).collect();
-        cx.external_paths.borrow_mut().get_mut_ref().insert(did,
-                                                            (fqn, TypeTrait));
-        TraitBound(ResolvedPath {
-            path: path,
-            typarams: None,
-            did: did,
-        })
-    }
-}
-
-impl Clean<TyParamBound> for ty::TraitRef {
-    fn clean(&self) -> TyParamBound {
-        let cx = super::ctxtkey.get().unwrap();
-        let tcx = match cx.maybe_typed {
-            core::Typed(ref tcx) => tcx,
-            core::NotTyped(_) => return RegionBound,
-        };
-        let fqn = csearch::get_item_path(tcx, self.def_id);
-        let fqn = fqn.move_iter().map(|i| i.to_str().to_strbuf())
-                     .collect::<Vec<String>>();
-        let path = external_path(fqn.last().unwrap().as_slice());
-        cx.external_paths.borrow_mut().get_mut_ref().insert(self.def_id,
-                                                            (fqn, TypeTrait));
-        TraitBound(ResolvedPath {
-            path: path,
-            typarams: None,
-            did: self.def_id,
-        })
-    }
-}
-
-impl Clean<Vec<TyParamBound>> for ty::ParamBounds {
-    fn clean(&self) -> Vec<TyParamBound> {
-        let mut v = Vec::new();
-        for b in self.builtin_bounds.iter() {
-            if b != ty::BoundSized {
-                v.push(b.clean());
-            }
-        }
-        for t in self.trait_bounds.iter() {
-            v.push(t.clean());
-        }
-        return v;
-    }
-}
-
-impl Clean<Option<Vec<TyParamBound>>> for ty::substs {
-    fn clean(&self) -> Option<Vec<TyParamBound>> {
-        let mut v = Vec::new();
-        match self.regions {
-            ty::NonerasedRegions(..) => v.push(RegionBound),
-            ty::ErasedRegions => {}
-        }
-        v.extend(self.tps.iter().map(|t| TraitBound(t.clean())));
-
-        if v.len() > 0 {Some(v)} else {None}
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable, Eq)]
-pub struct Lifetime(String);
-
-impl Lifetime {
-    pub fn get_ref<'a>(&'a self) -> &'a str {
-        let Lifetime(ref s) = *self;
-        let s: &'a str = s.as_slice();
-        return s;
-    }
-}
-
-impl Clean<Lifetime> for ast::Lifetime {
-    fn clean(&self) -> Lifetime {
-        Lifetime(token::get_name(self.name).get().to_strbuf())
-    }
-}
-
-impl Clean<Lifetime> for ty::RegionParameterDef {
-    fn clean(&self) -> Lifetime {
-        Lifetime(token::get_name(self.name).get().to_strbuf())
-    }
-}
-
-impl Clean<Option<Lifetime>> for ty::Region {
-    fn clean(&self) -> Option<Lifetime> {
-        match *self {
-            ty::ReStatic => Some(Lifetime("static".to_strbuf())),
-            ty::ReLateBound(_, ty::BrNamed(_, name)) =>
-                Some(Lifetime(token::get_name(name).get().to_strbuf())),
-
-            ty::ReLateBound(..) |
-            ty::ReEarlyBound(..) |
-            ty::ReFree(..) |
-            ty::ReScope(..) |
-            ty::ReInfer(..) |
-            ty::ReEmpty(..) => None
-        }
-    }
-}
-
-// maybe use a Generic enum and use ~[Generic]?
-#[deriving(Clone, Encodable, Decodable)]
-pub struct Generics {
-    pub lifetimes: Vec<Lifetime>,
-    pub type_params: Vec<TyParam>,
-}
-
-impl Clean<Generics> for ast::Generics {
-    fn clean(&self) -> Generics {
-        Generics {
-            lifetimes: self.lifetimes.clean().move_iter().collect(),
-            type_params: self.ty_params.clean().move_iter().collect(),
-        }
-    }
-}
-
-impl Clean<Generics> for ty::Generics {
-    fn clean(&self) -> Generics {
-        Generics {
-            lifetimes: self.region_param_defs.clean(),
-            type_params: self.type_param_defs.clean(),
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct Method {
-    pub generics: Generics,
-    pub self_: SelfTy,
-    pub fn_style: ast::FnStyle,
-    pub decl: FnDecl,
-}
-
-impl Clean<Item> for ast::Method {
-    fn clean(&self) -> Item {
-        let inputs = match self.explicit_self.node {
-            ast::SelfStatic => self.decl.inputs.as_slice(),
-            _ => self.decl.inputs.slice_from(1)
-        };
-        let decl = FnDecl {
-            inputs: Arguments {
-                values: inputs.iter().map(|x| x.clean()).collect(),
-            },
-            output: (self.decl.output.clean()),
-            cf: self.decl.cf.clean(),
-            attrs: Vec::new()
-        };
-        Item {
-            name: Some(self.ident.clean()),
-            attrs: self.attrs.clean().move_iter().collect(),
-            source: self.span.clean(),
-            def_id: ast_util::local_def(self.id.clone()),
-            visibility: self.vis.clean(),
-            inner: MethodItem(Method {
-                generics: self.generics.clean(),
-                self_: self.explicit_self.node.clean(),
-                fn_style: self.fn_style.clone(),
-                decl: decl,
-            }),
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct TyMethod {
-    pub fn_style: ast::FnStyle,
-    pub decl: FnDecl,
-    pub generics: Generics,
-    pub self_: SelfTy,
-}
-
-impl Clean<Item> for ast::TypeMethod {
-    fn clean(&self) -> Item {
-        let inputs = match self.explicit_self.node {
-            ast::SelfStatic => self.decl.inputs.as_slice(),
-            _ => self.decl.inputs.slice_from(1)
-        };
-        let decl = FnDecl {
-            inputs: Arguments {
-                values: inputs.iter().map(|x| x.clean()).collect(),
-            },
-            output: (self.decl.output.clean()),
-            cf: self.decl.cf.clean(),
-            attrs: Vec::new()
-        };
-        Item {
-            name: Some(self.ident.clean()),
-            attrs: self.attrs.clean().move_iter().collect(),
-            source: self.span.clean(),
-            def_id: ast_util::local_def(self.id),
-            visibility: None,
-            inner: TyMethodItem(TyMethod {
-                fn_style: self.fn_style.clone(),
-                decl: decl,
-                self_: self.explicit_self.node.clean(),
-                generics: self.generics.clean(),
-            }),
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable, Eq)]
-pub enum SelfTy {
-    SelfStatic,
-    SelfValue,
-    SelfBorrowed(Option<Lifetime>, Mutability),
-    SelfOwned,
-}
-
-impl Clean<SelfTy> for ast::ExplicitSelf_ {
-    fn clean(&self) -> SelfTy {
-        match *self {
-            ast::SelfStatic => SelfStatic,
-            ast::SelfValue => SelfValue,
-            ast::SelfUniq => SelfOwned,
-            ast::SelfRegion(lt, mt) => SelfBorrowed(lt.clean(), mt.clean()),
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct Function {
-    pub decl: FnDecl,
-    pub generics: Generics,
-    pub fn_style: ast::FnStyle,
-}
-
-impl Clean<Item> for doctree::Function {
-    fn clean(&self) -> Item {
-        Item {
-            name: Some(self.name.clean()),
-            attrs: self.attrs.clean(),
-            source: self.where.clean(),
-            visibility: self.vis.clean(),
-            def_id: ast_util::local_def(self.id),
-            inner: FunctionItem(Function {
-                decl: self.decl.clean(),
-                generics: self.generics.clean(),
-                fn_style: self.fn_style,
-            }),
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct ClosureDecl {
-    pub lifetimes: Vec<Lifetime>,
-    pub decl: FnDecl,
-    pub onceness: ast::Onceness,
-    pub fn_style: ast::FnStyle,
-    pub bounds: Vec<TyParamBound>,
-}
-
-impl Clean<ClosureDecl> for ast::ClosureTy {
-    fn clean(&self) -> ClosureDecl {
-        ClosureDecl {
-            lifetimes: self.lifetimes.clean(),
-            decl: self.decl.clean(),
-            onceness: self.onceness,
-            fn_style: self.fn_style,
-            bounds: match self.bounds {
-                Some(ref x) => x.clean().move_iter().collect(),
-                None        => Vec::new()
-            },
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct FnDecl {
-    pub inputs: Arguments,
-    pub output: Type,
-    pub cf: RetStyle,
-    pub attrs: Vec<Attribute>,
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct Arguments {
-    pub values: Vec<Argument>,
-}
-
-impl Clean<FnDecl> for ast::FnDecl {
-    fn clean(&self) -> FnDecl {
-        FnDecl {
-            inputs: Arguments {
-                values: self.inputs.iter().map(|x| x.clean()).collect(),
-            },
-            output: (self.output.clean()),
-            cf: self.cf.clean(),
-            attrs: Vec::new()
-        }
-    }
-}
-
-impl<'a> Clean<FnDecl> for (ast::DefId, &'a ty::FnSig) {
-    fn clean(&self) -> FnDecl {
-        let cx = super::ctxtkey.get().unwrap();
-        let tcx = match cx.maybe_typed {
-            core::Typed(ref tcx) => tcx,
-            core::NotTyped(_) => fail!(),
-        };
-        let (did, sig) = *self;
-        let mut names = if did.node != 0 {
-            csearch::get_method_arg_names(&tcx.sess.cstore, did).move_iter()
-        } else {
-            Vec::new().move_iter()
-        }.peekable();
-        if names.peek().map(|s| s.as_slice()) == Some("self") {
-            let _ = names.next();
-        }
-        if did.node == 0 {
-            let _ = names.len();
-        }
-        FnDecl {
-            output: sig.output.clean(),
-            cf: Return,
-            attrs: Vec::new(),
-            inputs: Arguments {
-                values: sig.inputs.iter().map(|t| {
-                    Argument {
-                        type_: t.clean(),
-                        id: 0,
-                        name: names.next().unwrap_or("".to_strbuf()),
-                    }
-                }).collect(),
-            },
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct Argument {
-    pub type_: Type,
-    pub name: String,
-    pub id: ast::NodeId,
-}
-
-impl Clean<Argument> for ast::Arg {
-    fn clean(&self) -> Argument {
-        Argument {
-            name: name_from_pat(self.pat),
-            type_: (self.ty.clean()),
-            id: self.id
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub enum RetStyle {
-    NoReturn,
-    Return
-}
-
-impl Clean<RetStyle> for ast::RetStyle {
-    fn clean(&self) -> RetStyle {
-        match *self {
-            ast::Return => Return,
-            ast::NoReturn => NoReturn
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct Trait {
-    pub methods: Vec<TraitMethod>,
-    pub generics: Generics,
-    pub parents: Vec<Type>,
-}
-
-impl Clean<Item> for doctree::Trait {
-    fn clean(&self) -> Item {
-        Item {
-            name: Some(self.name.clean()),
-            attrs: self.attrs.clean(),
-            source: self.where.clean(),
-            def_id: ast_util::local_def(self.id),
-            visibility: self.vis.clean(),
-            inner: TraitItem(Trait {
-                methods: self.methods.clean(),
-                generics: self.generics.clean(),
-                parents: self.parents.clean(),
-            }),
-        }
-    }
-}
-
-impl Clean<Type> for ast::TraitRef {
-    fn clean(&self) -> Type {
-        resolve_type(self.path.clean(), None, self.ref_id)
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub enum TraitMethod {
-    Required(Item),
-    Provided(Item),
-}
-
-impl TraitMethod {
-    pub fn is_req(&self) -> bool {
-        match self {
-            &Required(..) => true,
-            _ => false,
-        }
-    }
-    pub fn is_def(&self) -> bool {
-        match self {
-            &Provided(..) => true,
-            _ => false,
-        }
-    }
-    pub fn item<'a>(&'a self) -> &'a Item {
-        match *self {
-            Required(ref item) => item,
-            Provided(ref item) => item,
-        }
-    }
-}
-
-impl Clean<TraitMethod> for ast::TraitMethod {
-    fn clean(&self) -> TraitMethod {
-        match self {
-            &ast::Required(ref t) => Required(t.clean()),
-            &ast::Provided(ref t) => Provided(t.clean()),
-        }
-    }
-}
-
-impl Clean<TraitMethod> for ty::Method {
-    fn clean(&self) -> TraitMethod {
-        let m = if self.provided_source.is_some() {Provided} else {Required};
-        let cx = super::ctxtkey.get().unwrap();
-        let tcx = match cx.maybe_typed {
-            core::Typed(ref tcx) => tcx,
-            core::NotTyped(_) => fail!(),
-        };
-        let (self_, sig) = match self.explicit_self {
-            ast::SelfStatic => (ast::SelfStatic.clean(), self.fty.sig.clone()),
-            s => {
-                let sig = ty::FnSig {
-                    inputs: Vec::from_slice(self.fty.sig.inputs.slice_from(1)),
-                    ..self.fty.sig.clone()
-                };
-                let s = match s {
-                    ast::SelfRegion(..) => {
-                        match ty::get(*self.fty.sig.inputs.get(0)).sty {
-                            ty::ty_rptr(r, mt) => {
-                                SelfBorrowed(r.clean(), mt.mutbl.clean())
-                            }
-                            _ => s.clean(),
-                        }
-                    }
-                    s => s.clean(),
-                };
-                (s, sig)
-            }
-        };
-
-        m(Item {
-            name: Some(self.ident.clean()),
-            visibility: Some(ast::Inherited),
-            def_id: self.def_id,
-            attrs: load_attrs(tcx, self.def_id),
-            source: Span::empty(),
-            inner: TyMethodItem(TyMethod {
-                fn_style: self.fty.fn_style,
-                generics: self.generics.clean(),
-                self_: self_,
-                decl: (self.def_id, &sig).clean(),
-            })
-        })
-    }
-}
-
-/// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
-/// type out of the AST/ty::ctxt given one of these, if more information is needed. Most importantly
-/// it does not preserve mutability or boxes.
-#[deriving(Clone, Encodable, Decodable)]
-pub enum Type {
-    /// structs/enums/traits (anything that'd be an ast::TyPath)
-    ResolvedPath {
-        pub path: Path,
-        pub typarams: Option<Vec<TyParamBound>>,
-        pub did: ast::DefId,
-    },
-    // I have no idea how to usefully use this.
-    TyParamBinder(ast::NodeId),
-    /// For parameterized types, so the consumer of the JSON don't go looking
-    /// for types which don't exist anywhere.
-    Generic(ast::DefId),
-    /// For references to self
-    Self(ast::DefId),
-    /// Primitives are just the fixed-size numeric types (plus int/uint/float), and char.
-    Primitive(ast::PrimTy),
-    Closure(Box<ClosureDecl>, Option<Lifetime>),
-    Proc(Box<ClosureDecl>),
-    /// extern "ABI" fn
-    BareFunction(Box<BareFunctionDecl>),
-    Tuple(Vec<Type>),
-    Vector(Box<Type>),
-    FixedVector(Box<Type>, String),
-    String,
-    Bool,
-    /// aka TyNil
-    Unit,
-    /// aka TyBot
-    Bottom,
-    Unique(Box<Type>),
-    Managed(Box<Type>),
-    RawPointer(Mutability, Box<Type>),
-    BorrowedRef {
-        pub lifetime: Option<Lifetime>,
-        pub mutability: Mutability,
-        pub type_: Box<Type>,
-    },
-    // region, raw, other boxes, mutable
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub enum TypeKind {
-    TypeEnum,
-    TypeFunction,
-    TypeModule,
-    TypeStatic,
-    TypeStruct,
-    TypeTrait,
-    TypeVariant,
-}
-
-impl Clean<Type> for ast::Ty {
-    fn clean(&self) -> Type {
-        use syntax::ast::*;
-        match self.node {
-            TyNil => Unit,
-            TyPtr(ref m) => RawPointer(m.mutbl.clean(), box m.ty.clean()),
-            TyRptr(ref l, ref m) =>
-                BorrowedRef {lifetime: l.clean(), mutability: m.mutbl.clean(),
-                             type_: box m.ty.clean()},
-            TyBox(ty) => Managed(box ty.clean()),
-            TyUniq(ty) => Unique(box ty.clean()),
-            TyVec(ty) => Vector(box ty.clean()),
-            TyFixedLengthVec(ty, ref e) => FixedVector(box ty.clean(),
-                                                       e.span.to_src()),
-            TyTup(ref tys) => Tuple(tys.iter().map(|x| x.clean()).collect()),
-            TyPath(ref p, ref tpbs, id) => {
-                resolve_type(p.clean(),
-                             tpbs.clean().map(|x| x.move_iter().collect()),
-                             id)
-            }
-            TyClosure(ref c, region) => Closure(box c.clean(), region.clean()),
-            TyProc(ref c) => Proc(box c.clean()),
-            TyBareFn(ref barefn) => BareFunction(box barefn.clean()),
-            TyBot => Bottom,
-            ref x => fail!("Unimplemented type {:?}", x),
-        }
-    }
-}
-
-impl Clean<Type> for ty::t {
-    fn clean(&self) -> Type {
-        match ty::get(*self).sty {
-            ty::ty_nil => Unit,
-            ty::ty_bot => Bottom,
-            ty::ty_bool => Bool,
-            ty::ty_char => Primitive(ast::TyChar),
-            ty::ty_int(t) => Primitive(ast::TyInt(t)),
-            ty::ty_uint(u) => Primitive(ast::TyUint(u)),
-            ty::ty_float(f) => Primitive(ast::TyFloat(f)),
-            ty::ty_box(t) => Managed(box t.clean()),
-            ty::ty_uniq(t) => Unique(box t.clean()),
-            ty::ty_str => String,
-            ty::ty_vec(mt, None) => Vector(box mt.ty.clean()),
-            ty::ty_vec(mt, Some(i)) => FixedVector(box mt.ty.clean(),
-                                                   format_strbuf!("{}", i)),
-            ty::ty_ptr(mt) => RawPointer(mt.mutbl.clean(), box mt.ty.clean()),
-            ty::ty_rptr(r, mt) => BorrowedRef {
-                lifetime: r.clean(),
-                mutability: mt.mutbl.clean(),
-                type_: box mt.ty.clean(),
-            },
-            ty::ty_bare_fn(ref fty) => BareFunction(box BareFunctionDecl {
-                fn_style: fty.fn_style,
-                generics: Generics {
-                    lifetimes: Vec::new(), type_params: Vec::new()
-                },
-                decl: (ast_util::local_def(0), &fty.sig).clean(),
-                abi: fty.abi.to_str().to_strbuf(),
-            }),
-            ty::ty_closure(ref fty) => {
-                let decl = box ClosureDecl {
-                    lifetimes: Vec::new(), // FIXME: this looks wrong...
-                    decl: (ast_util::local_def(0), &fty.sig).clean(),
-                    onceness: fty.onceness,
-                    fn_style: fty.fn_style,
-                    bounds: fty.bounds.iter().map(|i| i.clean()).collect(),
-                };
-                match fty.store {
-                    ty::UniqTraitStore => Proc(decl),
-                    ty::RegionTraitStore(ref r, _) => Closure(decl, r.clean()),
-                }
-            }
-            ty::ty_struct(did, ref substs) |
-            ty::ty_enum(did, ref substs) |
-            ty::ty_trait(box ty::TyTrait { def_id: did, ref substs, .. }) => {
-                let cx = super::ctxtkey.get().unwrap();
-                let tcx = match cx.maybe_typed {
-                    core::Typed(ref tycx) => tycx,
-                    core::NotTyped(_) => fail!(),
-                };
-                let fqn = csearch::get_item_path(tcx, did);
-                let fqn: Vec<String> = fqn.move_iter().map(|i| {
-                    i.to_str().to_strbuf()
-                }).collect();
-                let mut path = external_path(fqn.last()
-                                                .unwrap()
-                                                .to_str()
-                                                .as_slice());
-                let kind = match ty::get(*self).sty {
-                    ty::ty_struct(..) => TypeStruct,
-                    ty::ty_trait(..) => TypeTrait,
-                    _ => TypeEnum,
-                };
-                path.segments.get_mut(0).lifetimes = match substs.regions {
-                    ty::ErasedRegions => Vec::new(),
-                    ty::NonerasedRegions(ref v) => {
-                        v.iter().filter_map(|v| v.clean()).collect()
-                    }
-                };
-                path.segments.get_mut(0).types = substs.tps.clean();
-                cx.external_paths.borrow_mut().get_mut_ref().insert(did,
-                                                                    (fqn, kind));
-                ResolvedPath {
-                    path: path,
-                    typarams: None,
-                    did: did,
-                }
-            }
-            ty::ty_tup(ref t) => Tuple(t.iter().map(|t| t.clean()).collect()),
-
-            ty::ty_param(ref p) => Generic(p.def_id),
-            ty::ty_self(did) => Self(did),
-
-            ty::ty_infer(..) => fail!("ty_infer"),
-            ty::ty_err => fail!("ty_err"),
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub enum StructField {
-    HiddenStructField, // inserted later by strip passes
-    TypedStructField(Type),
-}
-
-impl Clean<Item> for ast::StructField {
-    fn clean(&self) -> Item {
-        let (name, vis) = match self.node.kind {
-            ast::NamedField(id, vis) => (Some(id), vis),
-            ast::UnnamedField(vis) => (None, vis)
-        };
-        Item {
-            name: name.clean(),
-            attrs: self.node.attrs.clean().move_iter().collect(),
-            source: self.span.clean(),
-            visibility: Some(vis),
-            def_id: ast_util::local_def(self.node.id),
-            inner: StructFieldItem(TypedStructField(self.node.ty.clean())),
-        }
-    }
-}
-
-impl Clean<Item> for ty::field_ty {
-    fn clean(&self) -> Item {
-        use syntax::parse::token::special_idents::unnamed_field;
-        let name = if self.name == unnamed_field.name {
-            None
-        } else {
-            Some(self.name)
-        };
-        let cx = super::ctxtkey.get().unwrap();
-        let tcx = match cx.maybe_typed {
-            core::Typed(ref tycx) => tycx,
-            core::NotTyped(_) => fail!(),
-        };
-        let ty = ty::lookup_item_type(tcx, self.id);
-        Item {
-            name: name.clean(),
-            attrs: load_attrs(tcx, self.id),
-            source: Span::empty(),
-            visibility: Some(self.vis),
-            def_id: self.id,
-            inner: StructFieldItem(TypedStructField(ty.ty.clean())),
-        }
-    }
-}
-
-pub type Visibility = ast::Visibility;
-
-impl Clean<Option<Visibility>> for ast::Visibility {
-    fn clean(&self) -> Option<Visibility> {
-        Some(*self)
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct Struct {
-    pub struct_type: doctree::StructType,
-    pub generics: Generics,
-    pub fields: Vec<Item>,
-    pub fields_stripped: bool,
-}
-
-impl Clean<Item> for doctree::Struct {
-    fn clean(&self) -> Item {
-        Item {
-            name: Some(self.name.clean()),
-            attrs: self.attrs.clean(),
-            source: self.where.clean(),
-            def_id: ast_util::local_def(self.id),
-            visibility: self.vis.clean(),
-            inner: StructItem(Struct {
-                struct_type: self.struct_type,
-                generics: self.generics.clean(),
-                fields: self.fields.clean(),
-                fields_stripped: false,
-            }),
-        }
-    }
-}
-
-/// This is a more limited form of the standard Struct, different in that
-/// it lacks the things most items have (name, id, parameterization). Found
-/// only as a variant in an enum.
-#[deriving(Clone, Encodable, Decodable)]
-pub struct VariantStruct {
-    pub struct_type: doctree::StructType,
-    pub fields: Vec<Item>,
-    pub fields_stripped: bool,
-}
-
-impl Clean<VariantStruct> for syntax::ast::StructDef {
-    fn clean(&self) -> VariantStruct {
-        VariantStruct {
-            struct_type: doctree::struct_type_from_def(self),
-            fields: self.fields.clean().move_iter().collect(),
-            fields_stripped: false,
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct Enum {
-    pub variants: Vec<Item>,
-    pub generics: Generics,
-    pub variants_stripped: bool,
-}
-
-impl Clean<Item> for doctree::Enum {
-    fn clean(&self) -> Item {
-        Item {
-            name: Some(self.name.clean()),
-            attrs: self.attrs.clean(),
-            source: self.where.clean(),
-            def_id: ast_util::local_def(self.id),
-            visibility: self.vis.clean(),
-            inner: EnumItem(Enum {
-                variants: self.variants.clean(),
-                generics: self.generics.clean(),
-                variants_stripped: false,
-            }),
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct Variant {
-    pub kind: VariantKind,
-}
-
-impl Clean<Item> for doctree::Variant {
-    fn clean(&self) -> Item {
-        Item {
-            name: Some(self.name.clean()),
-            attrs: self.attrs.clean(),
-            source: self.where.clean(),
-            visibility: self.vis.clean(),
-            def_id: ast_util::local_def(self.id),
-            inner: VariantItem(Variant {
-                kind: self.kind.clean(),
-            }),
-        }
-    }
-}
-
-impl Clean<Item> for ty::VariantInfo {
-    fn clean(&self) -> Item {
-        // use syntax::parse::token::special_idents::unnamed_field;
-        let cx = super::ctxtkey.get().unwrap();
-        let tcx = match cx.maybe_typed {
-            core::Typed(ref tycx) => tycx,
-            core::NotTyped(_) => fail!("tcx not present"),
-        };
-        let kind = match self.arg_names.as_ref().map(|s| s.as_slice()) {
-            None | Some([]) if self.args.len() == 0 => CLikeVariant,
-            None | Some([]) => {
-                TupleVariant(self.args.iter().map(|t| t.clean()).collect())
-            }
-            Some(s) => {
-                StructVariant(VariantStruct {
-                    struct_type: doctree::Plain,
-                    fields_stripped: false,
-                    fields: s.iter().zip(self.args.iter()).map(|(name, ty)| {
-                        Item {
-                            source: Span::empty(),
-                            name: Some(name.clean()),
-                            attrs: Vec::new(),
-                            visibility: Some(ast::Public),
-                            def_id: self.id, // FIXME: this is not accurate
-                            inner: StructFieldItem(
-                                TypedStructField(ty.clean())
-                            )
-                        }
-                    }).collect()
-                })
-            }
-        };
-        Item {
-            name: Some(self.name.clean()),
-            attrs: load_attrs(tcx, self.id),
-            source: Span::empty(),
-            visibility: Some(ast::Public),
-            def_id: self.id,
-            inner: VariantItem(Variant { kind: kind }),
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub enum VariantKind {
-    CLikeVariant,
-    TupleVariant(Vec<Type>),
-    StructVariant(VariantStruct),
-}
-
-impl Clean<VariantKind> for ast::VariantKind {
-    fn clean(&self) -> VariantKind {
-        match self {
-            &ast::TupleVariantKind(ref args) => {
-                if args.len() == 0 {
-                    CLikeVariant
-                } else {
-                    TupleVariant(args.iter().map(|x| x.ty.clean()).collect())
-                }
-            },
-            &ast::StructVariantKind(ref sd) => StructVariant(sd.clean()),
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct Span {
-    pub filename: String,
-    pub loline: uint,
-    pub locol: uint,
-    pub hiline: uint,
-    pub hicol: uint,
-}
-
-impl Span {
-    fn empty() -> Span {
-        Span {
-            filename: "".to_strbuf(),
-            loline: 0, locol: 0,
-            hiline: 0, hicol: 0,
-        }
-    }
-}
-
-impl Clean<Span> for syntax::codemap::Span {
-    fn clean(&self) -> Span {
-        let ctxt = super::ctxtkey.get().unwrap();
-        let cm = ctxt.sess().codemap();
-        let filename = cm.span_to_filename(*self);
-        let lo = cm.lookup_char_pos(self.lo);
-        let hi = cm.lookup_char_pos(self.hi);
-        Span {
-            filename: filename.to_strbuf(),
-            loline: lo.line,
-            locol: lo.col.to_uint(),
-            hiline: hi.line,
-            hicol: hi.col.to_uint(),
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct Path {
-    pub global: bool,
-    pub segments: Vec<PathSegment>,
-}
-
-impl Clean<Path> for ast::Path {
-    fn clean(&self) -> Path {
-        Path {
-            global: self.global,
-            segments: self.segments.clean().move_iter().collect(),
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct PathSegment {
-    pub name: String,
-    pub lifetimes: Vec<Lifetime>,
-    pub types: Vec<Type>,
-}
-
-impl Clean<PathSegment> for ast::PathSegment {
-    fn clean(&self) -> PathSegment {
-        PathSegment {
-            name: self.identifier.clean(),
-            lifetimes: self.lifetimes.clean().move_iter().collect(),
-            types: self.types.clean().move_iter().collect()
-        }
-    }
-}
-
-fn path_to_str(p: &ast::Path) -> String {
-    use syntax::parse::token;
-
-    let mut s = String::new();
-    let mut first = true;
-    for i in p.segments.iter().map(|x| token::get_ident(x.identifier)) {
-        if !first || p.global {
-            s.push_str("::");
-        } else {
-            first = false;
-        }
-        s.push_str(i.get());
-    }
-    s
-}
-
-impl Clean<String> for ast::Ident {
-    fn clean(&self) -> String {
-        token::get_ident(*self).get().to_strbuf()
-    }
-}
-
-impl Clean<StrBuf> for ast::Name {
-    fn clean(&self) -> StrBuf {
-        token::get_name(*self).get().to_strbuf()
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct Typedef {
-    pub type_: Type,
-    pub generics: Generics,
-}
-
-impl Clean<Item> for doctree::Typedef {
-    fn clean(&self) -> Item {
-        Item {
-            name: Some(self.name.clean()),
-            attrs: self.attrs.clean(),
-            source: self.where.clean(),
-            def_id: ast_util::local_def(self.id.clone()),
-            visibility: self.vis.clean(),
-            inner: TypedefItem(Typedef {
-                type_: self.ty.clean(),
-                generics: self.gen.clean(),
-            }),
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct BareFunctionDecl {
-    pub fn_style: ast::FnStyle,
-    pub generics: Generics,
-    pub decl: FnDecl,
-    pub abi: String,
-}
-
-impl Clean<BareFunctionDecl> for ast::BareFnTy {
-    fn clean(&self) -> BareFunctionDecl {
-        BareFunctionDecl {
-            fn_style: self.fn_style,
-            generics: Generics {
-                lifetimes: self.lifetimes.clean().move_iter().collect(),
-                type_params: Vec::new(),
-            },
-            decl: self.decl.clean(),
-            abi: self.abi.to_str().to_strbuf(),
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct Static {
-    pub type_: Type,
-    pub mutability: Mutability,
-    /// It's useful to have the value of a static documented, but I have no
-    /// desire to represent expressions (that'd basically be all of the AST,
-    /// which is huge!). So, have a string.
-    pub expr: String,
-}
-
-impl Clean<Item> for doctree::Static {
-    fn clean(&self) -> Item {
-        debug!("claning static {}: {:?}", self.name.clean(), self);
-        Item {
-            name: Some(self.name.clean()),
-            attrs: self.attrs.clean(),
-            source: self.where.clean(),
-            def_id: ast_util::local_def(self.id),
-            visibility: self.vis.clean(),
-            inner: StaticItem(Static {
-                type_: self.type_.clean(),
-                mutability: self.mutability.clean(),
-                expr: self.expr.span.to_src(),
-            }),
-        }
-    }
-}
-
-#[deriving(Show, Clone, Encodable, Decodable, Eq)]
-pub enum Mutability {
-    Mutable,
-    Immutable,
-}
-
-impl Clean<Mutability> for ast::Mutability {
-    fn clean(&self) -> Mutability {
-        match self {
-            &ast::MutMutable => Mutable,
-            &ast::MutImmutable => Immutable,
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct Impl {
-    pub generics: Generics,
-    pub trait_: Option<Type>,
-    pub for_: Type,
-    pub methods: Vec<Item>,
-    pub derived: bool,
-}
-
-fn detect_derived<M: AttrMetaMethods>(attrs: &[M]) -> bool {
-    attrs.iter().any(|attr| {
-        attr.name().get() == "automatically_derived"
-    })
-}
-
-impl Clean<Item> for doctree::Impl {
-    fn clean(&self) -> Item {
-        Item {
-            name: None,
-            attrs: self.attrs.clean(),
-            source: self.where.clean(),
-            def_id: ast_util::local_def(self.id),
-            visibility: self.vis.clean(),
-            inner: ImplItem(Impl {
-                generics: self.generics.clean(),
-                trait_: self.trait_.clean(),
-                for_: self.for_.clean(),
-                methods: self.methods.clean(),
-                derived: detect_derived(self.attrs.as_slice()),
-            }),
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct ViewItem {
-    pub inner: ViewItemInner,
-}
-
-impl Clean<Vec<Item>> for ast::ViewItem {
-    fn clean(&self) -> Vec<Item> {
-        let denied = self.vis != ast::Public || self.attrs.iter().any(|a| {
-            a.name().get() == "doc" && match a.meta_item_list() {
-                Some(l) => attr::contains_name(l, "noinline"),
-                None => false,
-            }
-        });
-        let convert = |node: &ast::ViewItem_| {
-            Item {
-                name: None,
-                attrs: self.attrs.clean().move_iter().collect(),
-                source: self.span.clean(),
-                def_id: ast_util::local_def(0),
-                visibility: self.vis.clean(),
-                inner: ViewItemItem(ViewItem { inner: node.clean() }),
-            }
-        };
-        let mut ret = Vec::new();
-        match self.node {
-            ast::ViewItemUse(ref path) if !denied => {
-                match path.node {
-                    ast::ViewPathGlob(..) => ret.push(convert(&self.node)),
-                    ast::ViewPathList(ref a, ref list, ref b) => {
-                        let remaining = list.iter().filter(|path| {
-                            match try_inline(path.node.id) {
-                                Some(items) => {
-                                    ret.extend(items.move_iter()); false
-                                }
-                                None => true,
-                            }
-                        }).map(|a| a.clone()).collect::<Vec<ast::PathListIdent>>();
-                        if remaining.len() > 0 {
-                            let path = ast::ViewPathList(a.clone(),
-                                                         remaining,
-                                                         b.clone());
-                            let path = syntax::codemap::dummy_spanned(path);
-                            ret.push(convert(&ast::ViewItemUse(@path)));
-                        }
-                    }
-                    ast::ViewPathSimple(_, _, id) => {
-                        match try_inline(id) {
-                            Some(items) => ret.extend(items.move_iter()),
-                            None => ret.push(convert(&self.node)),
-                        }
-                    }
-                }
-            }
-            ref n => ret.push(convert(n)),
-        }
-        return ret;
-    }
-}
-
-fn try_inline(id: ast::NodeId) -> Option<Vec<Item>> {
-    let cx = super::ctxtkey.get().unwrap();
-    let tcx = match cx.maybe_typed {
-        core::Typed(ref tycx) => tycx,
-        core::NotTyped(_) => return None,
-    };
-    let def = match tcx.def_map.borrow().find(&id) {
-        Some(def) => *def,
-        None => return None,
-    };
-    let did = ast_util::def_id_of_def(def);
-    if ast_util::is_local(did) { return None }
-    try_inline_def(&**cx, tcx, def)
-}
-
-fn try_inline_def(cx: &core::DocContext,
-                  tcx: &ty::ctxt,
-                  def: ast::Def) -> Option<Vec<Item>> {
-    let mut ret = Vec::new();
-    let did = ast_util::def_id_of_def(def);
-    let inner = match def {
-        ast::DefTrait(did) => {
-            record_extern_fqn(cx, did, TypeTrait);
-            TraitItem(build_external_trait(tcx, did))
-        }
-        ast::DefFn(did, style) => {
-            record_extern_fqn(cx, did, TypeFunction);
-            FunctionItem(build_external_function(tcx, did, style))
-        }
-        ast::DefStruct(did) => {
-            record_extern_fqn(cx, did, TypeStruct);
-            ret.extend(build_impls(tcx, did).move_iter());
-            StructItem(build_struct(tcx, did))
-        }
-        ast::DefTy(did) => {
-            record_extern_fqn(cx, did, TypeEnum);
-            ret.extend(build_impls(tcx, did).move_iter());
-            build_type(tcx, did)
-        }
-        // Assume that the enum type is reexported next to the variant, and
-        // variants don't show up in documentation specially.
-        ast::DefVariant(..) => return Some(Vec::new()),
-        ast::DefMod(did) => {
-            record_extern_fqn(cx, did, TypeModule);
-            ModuleItem(build_module(cx, tcx, did))
-        }
-        _ => return None,
-    };
-    let fqn = csearch::get_item_path(tcx, did);
-    ret.push(Item {
-        source: Span::empty(),
-        name: Some(fqn.last().unwrap().to_str().to_strbuf()),
-        attrs: load_attrs(tcx, did),
-        inner: inner,
-        visibility: Some(ast::Public),
-        def_id: did,
-    });
-    Some(ret)
-}
-
-fn load_attrs(tcx: &ty::ctxt, did: ast::DefId) -> Vec<Attribute> {
-    let mut attrs = Vec::new();
-    csearch::get_item_attrs(&tcx.sess.cstore, did, |v| {
-        attrs.extend(v.move_iter().map(|item| {
-            let mut a = attr::mk_attr_outer(item);
-            // FIXME this isn't quite always true, it's just true about 99% of
-            //       the time when dealing with documentation
-            if a.name().get() == "doc" && a.value_str().is_some() {
-                a.node.is_sugared_doc = true;
-            }
-            a.clean()
-        }));
-    });
-    attrs
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub enum ViewItemInner {
-    ExternCrate(String, Option<String>, ast::NodeId),
-    Import(ViewPath)
-}
-
-impl Clean<ViewItemInner> for ast::ViewItem_ {
-    fn clean(&self) -> ViewItemInner {
-        match self {
-            &ast::ViewItemExternCrate(ref i, ref p, ref id) => {
-                let string = match *p {
-                    None => None,
-                    Some((ref x, _)) => Some(x.get().to_strbuf()),
-                };
-                ExternCrate(i.clean(), string, *id)
-            }
-            &ast::ViewItemUse(ref vp) => {
-                Import(vp.clean())
-            }
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub enum ViewPath {
-    // use str = source;
-    SimpleImport(String, ImportSource),
-    // use source::*;
-    GlobImport(ImportSource),
-    // use source::{a, b, c};
-    ImportList(ImportSource, Vec<ViewListIdent>),
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct ImportSource {
-    pub path: Path,
-    pub did: Option<ast::DefId>,
-}
-
-impl Clean<ViewPath> for ast::ViewPath {
-    fn clean(&self) -> ViewPath {
-        match self.node {
-            ast::ViewPathSimple(ref i, ref p, id) =>
-                SimpleImport(i.clean(), resolve_use_source(p.clean(), id)),
-            ast::ViewPathGlob(ref p, id) =>
-                GlobImport(resolve_use_source(p.clean(), id)),
-            ast::ViewPathList(ref p, ref pl, id) => {
-                ImportList(resolve_use_source(p.clean(), id),
-                           pl.clean().move_iter().collect())
-            }
-        }
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct ViewListIdent {
-    pub name: String,
-    pub source: Option<ast::DefId>,
-}
-
-impl Clean<ViewListIdent> for ast::PathListIdent {
-    fn clean(&self) -> ViewListIdent {
-        ViewListIdent {
-            name: self.node.name.clean(),
-            source: resolve_def(self.node.id),
-        }
-    }
-}
-
-impl Clean<Vec<Item>> for ast::ForeignMod {
-    fn clean(&self) -> Vec<Item> {
-        self.items.clean()
-    }
-}
-
-impl Clean<Item> for ast::ForeignItem {
-    fn clean(&self) -> Item {
-        let inner = match self.node {
-            ast::ForeignItemFn(ref decl, ref generics) => {
-                ForeignFunctionItem(Function {
-                    decl: decl.clean(),
-                    generics: generics.clean(),
-                    fn_style: ast::UnsafeFn,
-                })
-            }
-            ast::ForeignItemStatic(ref ty, mutbl) => {
-                ForeignStaticItem(Static {
-                    type_: ty.clean(),
-                    mutability: if mutbl {Mutable} else {Immutable},
-                    expr: "".to_strbuf(),
-                })
-            }
-        };
-        Item {
-            name: Some(self.ident.clean()),
-            attrs: self.attrs.clean().move_iter().collect(),
-            source: self.span.clean(),
-            def_id: ast_util::local_def(self.id),
-            visibility: self.vis.clean(),
-            inner: inner,
-        }
-    }
-}
-
-// Utilities
-
-trait ToSource {
-    fn to_src(&self) -> String;
-}
-
-impl ToSource for syntax::codemap::Span {
-    fn to_src(&self) -> String {
-        debug!("converting span {:?} to snippet", self.clean());
-        let ctxt = super::ctxtkey.get().unwrap();
-        let cm = ctxt.sess().codemap().clone();
-        let sn = match cm.span_to_snippet(*self) {
-            Some(x) => x.to_strbuf(),
-            None    => "".to_strbuf()
-        };
-        debug!("got snippet {}", sn);
-        sn
-    }
-}
-
-fn lit_to_str(lit: &ast::Lit) -> String {
-    match lit.node {
-        ast::LitStr(ref st, _) => st.get().to_strbuf(),
-        ast::LitBinary(ref data) => format_strbuf!("{:?}", data.as_slice()),
-        ast::LitChar(c) => format_strbuf!("'{}'", c),
-        ast::LitInt(i, _t) => i.to_str().to_strbuf(),
-        ast::LitUint(u, _t) => u.to_str().to_strbuf(),
-        ast::LitIntUnsuffixed(i) => i.to_str().to_strbuf(),
-        ast::LitFloat(ref f, _t) => f.get().to_strbuf(),
-        ast::LitFloatUnsuffixed(ref f) => f.get().to_strbuf(),
-        ast::LitBool(b) => b.to_str().to_strbuf(),
-        ast::LitNil => "".to_strbuf(),
-    }
-}
-
-fn name_from_pat(p: &ast::Pat) -> String {
-    use syntax::ast::*;
-    debug!("Trying to get a name from pattern: {:?}", p);
-
-    match p.node {
-        PatWild => "_".to_strbuf(),
-        PatWildMulti => "..".to_strbuf(),
-        PatIdent(_, ref p, _) => path_to_str(p),
-        PatEnum(ref p, _) => path_to_str(p),
-        PatStruct(..) => fail!("tried to get argument name from pat_struct, \
-                                which is not allowed in function arguments"),
-        PatTup(..) => "(tuple arg NYI)".to_strbuf(),
-        PatUniq(p) => name_from_pat(p),
-        PatRegion(p) => name_from_pat(p),
-        PatLit(..) => {
-            warn!("tried to get argument name from PatLit, \
-                  which is silly in function arguments");
-            "()".to_strbuf()
-        },
-        PatRange(..) => fail!("tried to get argument name from PatRange, \
-                              which is not allowed in function arguments"),
-        PatVec(..) => fail!("tried to get argument name from pat_vec, \
-                             which is not allowed in function arguments")
-    }
-}
-
-/// Given a Type, resolve it using the def_map
-fn resolve_type(path: Path, tpbs: Option<Vec<TyParamBound>>,
-                id: ast::NodeId) -> Type {
-    let cx = super::ctxtkey.get().unwrap();
-    let tycx = match cx.maybe_typed {
-        core::Typed(ref tycx) => tycx,
-        // If we're extracting tests, this return value doesn't matter.
-        core::NotTyped(_) => return Bool
-    };
-    debug!("searching for {:?} in defmap", id);
-    let def = match tycx.def_map.borrow().find(&id) {
-        Some(&k) => k,
-        None => fail!("unresolved id not in defmap")
-    };
-
-    match def {
-        ast::DefSelfTy(i) => return Self(ast_util::local_def(i)),
-        ast::DefPrimTy(p) => match p {
-            ast::TyStr => return String,
-            ast::TyBool => return Bool,
-            _ => return Primitive(p)
-        },
-        ast::DefTyParam(i, _) => return Generic(i),
-        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::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(did) { return did }
-    let tcx = match cx.maybe_typed {
-        core::Typed(ref t) => t,
-        core::NotTyped(_) => return did
-    };
-    record_extern_fqn(cx, did, kind);
-    match kind {
-        TypeTrait => {
-            let t = build_external_trait(tcx, did);
-            cx.external_traits.borrow_mut().get_mut_ref().insert(did, t);
-        }
-        _ => {}
-    }
-    return did;
-}
-
-fn record_extern_fqn(cx: &core::DocContext,
-                     did: ast::DefId,
-                     kind: TypeKind) {
-    match cx.maybe_typed {
-        core::Typed(ref tcx) => {
-            let fqn = csearch::get_item_path(tcx, did);
-            let fqn = fqn.move_iter().map(|i| i.to_str().to_strbuf()).collect();
-            cx.external_paths.borrow_mut().get_mut_ref().insert(did, (fqn, kind));
-        }
-        core::NotTyped(..) => {}
-    }
-}
-
-fn build_external_trait(tcx: &ty::ctxt, did: ast::DefId) -> Trait {
-    let def = ty::lookup_trait_def(tcx, did);
-    let methods = ty::trait_methods(tcx, did);
-    Trait {
-        generics: def.generics.clean(),
-        methods: methods.iter().map(|i| i.clean()).collect(),
-        parents: Vec::new(), // FIXME: this is likely wrong
-    }
-}
-
-fn build_external_function(tcx: &ty::ctxt,
-                           did: ast::DefId,
-                           style: ast::FnStyle) -> Function {
-    let t = ty::lookup_item_type(tcx, did);
-    Function {
-        decl: match ty::get(t.ty).sty {
-            ty::ty_bare_fn(ref f) => (did, &f.sig).clean(),
-            _ => fail!("bad function"),
-        },
-        generics: t.generics.clean(),
-        fn_style: style,
-    }
-}
-
-fn build_struct(tcx: &ty::ctxt, did: ast::DefId) -> Struct {
-    use syntax::parse::token::special_idents::unnamed_field;
-
-    let t = ty::lookup_item_type(tcx, did);
-    let fields = ty::lookup_struct_fields(tcx, did);
-
-    Struct {
-        struct_type: match fields.as_slice() {
-            [] => doctree::Unit,
-            [ref f] if f.name == unnamed_field.name => doctree::Newtype,
-            [ref f, ..] if f.name == unnamed_field.name => doctree::Tuple,
-            _ => doctree::Plain,
-        },
-        generics: t.generics.clean(),
-        fields: fields.iter().map(|f| f.clean()).collect(),
-        fields_stripped: false,
-    }
-}
-
-fn build_type(tcx: &ty::ctxt, did: ast::DefId) -> ItemEnum {
-    let t = ty::lookup_item_type(tcx, did);
-    match ty::get(t.ty).sty {
-        ty::ty_enum(edid, _) => {
-            return EnumItem(Enum {
-                generics: t.generics.clean(),
-                variants_stripped: false,
-                variants: ty::enum_variants(tcx, edid).clean(),
-            })
-        }
-        _ => {}
-    }
-
-    TypedefItem(Typedef {
-        type_: t.ty.clean(),
-        generics: t.generics.clean(),
-    })
-}
-
-fn build_impls(tcx: &ty::ctxt,
-               did: ast::DefId) -> Vec<Item> {
-    ty::populate_implementations_for_type_if_necessary(tcx, did);
-    let mut impls = Vec::new();
-
-    match tcx.inherent_impls.borrow().find(&did) {
-        None => {}
-        Some(i) => {
-            impls.extend(i.borrow().iter().map(|&did| { build_impl(tcx, did) }));
-        }
-    }
-
-    // csearch::each_impl(&tcx.sess.cstore, did.krate, |imp| {
-    //     // if imp.krate
-    //     let t = ty::lookup_item_type(tcx, imp);
-    //     println!("{}", ::rustc::util::ppaux::ty_to_str(tcx, t.ty));
-    //     match ty::get(t.ty).sty {
-    //         ty::ty_struct(tdid, _) |
-    //         ty::ty_enum(tdid, _) if tdid == did => {
-    //             impls.push(build_impl(tcx, imp));
-    //         }
-    //         _ => {}
-    //     }
-    // });
-    // for (k, v) in tcx.trait_impls.borrow().iter() {
-    //     if k.krate != did.krate { continue }
-    //     for imp in v.borrow().iter() {
-    //         if imp.krate != did.krate { continue }
-    //         let t = ty::lookup_item_type(tcx, *imp);
-    //         println!("{}", ::rustc::util::ppaux::ty_to_str(tcx, t.ty));
-    //         match ty::get(t.ty).sty {
-    //             ty::ty_struct(tdid, _) |
-    //             ty::ty_enum(tdid, _) if tdid == did => {
-    //                 impls.push(build_impl(tcx, *imp));
-    //             }
-    //             _ => {}
-    //         }
-    //     }
-    // }
-
-    impls
-}
-
-fn build_impl(tcx: &ty::ctxt, did: ast::DefId) -> Item {
-    let associated_trait = csearch::get_impl_trait(tcx, did);
-    let attrs = load_attrs(tcx, did);
-    let ty = ty::lookup_item_type(tcx, did);
-    let methods = csearch::get_impl_methods(&tcx.sess.cstore, did).iter().map(|did| {
-        let mut item = match ty::method(tcx, *did).clean() {
-            Provided(item) => item,
-            Required(item) => item,
-        };
-        item.inner = match item.inner.clone() {
-            TyMethodItem(TyMethod { fn_style, decl, self_, generics }) => {
-                MethodItem(Method {
-                    fn_style: fn_style,
-                    decl: decl,
-                    self_: self_,
-                    generics: generics,
-                })
-            }
-            _ => fail!("not a tymethod"),
-        };
-        item
-    }).collect();
-    Item {
-        inner: ImplItem(Impl {
-            derived: detect_derived(attrs.as_slice()),
-            trait_: associated_trait.clean().map(|bound| {
-                match bound {
-                    TraitBound(ty) => ty,
-                    RegionBound => fail!(),
-                }
-            }),
-            for_: ty.ty.clean(),
-            generics: ty.generics.clean(),
-            methods: methods,
-        }),
-        source: Span::empty(),
-        name: None,
-        attrs: attrs,
-        visibility: Some(ast::Inherited),
-        def_id: did,
-    }
-}
-
-fn build_module(cx: &core::DocContext, tcx: &ty::ctxt,
-                did: ast::DefId) -> Module {
-    let mut items = Vec::new();
-
-    csearch::each_child_of_item(&tcx.sess.cstore, did, |def, _, _| {
-        match def {
-            decoder::DlDef(def) => {
-                match try_inline_def(cx, tcx, def) {
-                    Some(i) => items.extend(i.move_iter()),
-                    None => {}
-                }
-            }
-            decoder::DlImpl(did) => items.push(build_impl(tcx, did)),
-            decoder::DlField => fail!("unimplemented field"),
-        }
-    });
-
-    Module {
-        items: items,
-        is_crate: false,
-    }
-}
-
-fn resolve_use_source(path: Path, id: ast::NodeId) -> ImportSource {
-    ImportSource {
-        path: path,
-        did: resolve_def(id),
-    }
-}
-
-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(|&def| register_def(&**cx, def))
-        }
-        core::NotTyped(_) => None
-    }
-}
-
-#[deriving(Clone, Encodable, Decodable)]
-pub struct Macro {
-    pub source: String,
-}
-
-impl Clean<Item> for doctree::Macro {
-    fn clean(&self) -> Item {
-        Item {
-            name: Some(format_strbuf!("{}!", self.name.clean())),
-            attrs: self.attrs.clean(),
-            source: self.where.clean(),
-            visibility: ast::Public.clean(),
-            def_id: ast_util::local_def(self.id),
-            inner: MacroItem(Macro {
-                source: self.where.to_src(),
-            }),
-        }
-    }
-}
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
new file mode 100644 (file)
index 0000000..dd5fddc
--- /dev/null
@@ -0,0 +1,278 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Support for inlining external documentation into the current AST.
+
+use syntax::ast;
+use syntax::ast_util;
+use syntax::attr::AttrMetaMethods;
+
+use rustc::metadata::csearch;
+use rustc::metadata::decoder;
+use rustc::middle::ty;
+
+use core;
+use doctree;
+use clean;
+
+use super::Clean;
+
+/// Attempt to inline the definition of a local node id into this AST.
+///
+/// This function will fetch the definition of the id specified, and if it is
+/// from another crate it will attempt to inline the documentation from the
+/// other crate into this crate.
+///
+/// This is primarily used for `pub use` statements which are, in general,
+/// implementation details. Inlining the documentation should help provide a
+/// better experience when reading the documentation in this use case.
+///
+/// The returned value is `None` if the `id` could not be inlined, and `Some`
+/// of a vector of items if it was successfully expanded.
+pub fn try_inline(id: ast::NodeId) -> Option<Vec<clean::Item>> {
+    let cx = ::ctxtkey.get().unwrap();
+    let tcx = match cx.maybe_typed {
+        core::Typed(ref tycx) => tycx,
+        core::NotTyped(_) => return None,
+    };
+    let def = match tcx.def_map.borrow().find(&id) {
+        Some(def) => *def,
+        None => return None,
+    };
+    let did = ast_util::def_id_of_def(def);
+    if ast_util::is_local(did) { return None }
+    try_inline_def(&**cx, tcx, def)
+}
+
+fn try_inline_def(cx: &core::DocContext,
+                  tcx: &ty::ctxt,
+                  def: ast::Def) -> Option<Vec<clean::Item>> {
+    let mut ret = Vec::new();
+    let did = ast_util::def_id_of_def(def);
+    let inner = match def {
+        ast::DefTrait(did) => {
+            record_extern_fqn(cx, did, clean::TypeTrait);
+            clean::TraitItem(build_external_trait(tcx, did))
+        }
+        ast::DefFn(did, style) => {
+            record_extern_fqn(cx, did, clean::TypeFunction);
+            clean::FunctionItem(build_external_function(tcx, did, style))
+        }
+        ast::DefStruct(did) => {
+            record_extern_fqn(cx, did, clean::TypeStruct);
+            ret.extend(build_impls(tcx, did).move_iter());
+            clean::StructItem(build_struct(tcx, did))
+        }
+        ast::DefTy(did) => {
+            record_extern_fqn(cx, did, clean::TypeEnum);
+            ret.extend(build_impls(tcx, did).move_iter());
+            build_type(tcx, did)
+        }
+        // Assume that the enum type is reexported next to the variant, and
+        // variants don't show up in documentation specially.
+        ast::DefVariant(..) => return Some(Vec::new()),
+        ast::DefMod(did) => {
+            record_extern_fqn(cx, did, clean::TypeModule);
+            clean::ModuleItem(build_module(cx, tcx, did))
+        }
+        _ => return None,
+    };
+    let fqn = csearch::get_item_path(tcx, did);
+    ret.push(clean::Item {
+        source: clean::Span::empty(),
+        name: Some(fqn.last().unwrap().to_str().to_strbuf()),
+        attrs: load_attrs(tcx, did),
+        inner: inner,
+        visibility: Some(ast::Public),
+        def_id: did,
+    });
+    Some(ret)
+}
+
+pub fn load_attrs(tcx: &ty::ctxt, did: ast::DefId) -> Vec<clean::Attribute> {
+    let mut attrs = Vec::new();
+    csearch::get_item_attrs(&tcx.sess.cstore, did, |v| {
+        attrs.extend(v.move_iter().map(|mut a| {
+            // FIXME this isn't quite always true, it's just true about 99% of
+            //       the time when dealing with documentation. For example,
+            //       this would treat doc comments of the form `#[doc = "foo"]`
+            //       incorrectly.
+            if a.name().get() == "doc" && a.value_str().is_some() {
+                a.node.is_sugared_doc = true;
+            }
+            a.clean()
+        }));
+    });
+    attrs
+}
+
+/// Record an external fully qualified name in the external_paths cache.
+///
+/// These names are used later on by HTML rendering to generate things like
+/// source links back to the original item.
+pub fn record_extern_fqn(cx: &core::DocContext,
+                         did: ast::DefId,
+                         kind: clean::TypeKind) {
+    match cx.maybe_typed {
+        core::Typed(ref tcx) => {
+            let fqn = csearch::get_item_path(tcx, did);
+            let fqn = fqn.move_iter().map(|i| i.to_str().to_strbuf()).collect();
+            cx.external_paths.borrow_mut().get_mut_ref().insert(did, (fqn, kind));
+        }
+        core::NotTyped(..) => {}
+    }
+}
+
+pub fn build_external_trait(tcx: &ty::ctxt, did: ast::DefId) -> clean::Trait {
+    let def = ty::lookup_trait_def(tcx, did);
+    let methods = ty::trait_methods(tcx, did);
+    clean::Trait {
+        generics: def.generics.clean(),
+        methods: methods.iter().map(|i| i.clean()).collect(),
+        parents: Vec::new(), // FIXME: this is likely wrong
+    }
+}
+
+fn build_external_function(tcx: &ty::ctxt,
+                           did: ast::DefId,
+                           style: ast::FnStyle) -> clean::Function {
+    let t = ty::lookup_item_type(tcx, did);
+    clean::Function {
+        decl: match ty::get(t.ty).sty {
+            ty::ty_bare_fn(ref f) => (did, &f.sig).clean(),
+            _ => fail!("bad function"),
+        },
+        generics: t.generics.clean(),
+        fn_style: style,
+    }
+}
+
+fn build_struct(tcx: &ty::ctxt, did: ast::DefId) -> clean::Struct {
+    use syntax::parse::token::special_idents::unnamed_field;
+
+    let t = ty::lookup_item_type(tcx, did);
+    let fields = ty::lookup_struct_fields(tcx, did);
+
+    clean::Struct {
+        struct_type: match fields.as_slice() {
+            [] => doctree::Unit,
+            [ref f] if f.name == unnamed_field.name => doctree::Newtype,
+            [ref f, ..] if f.name == unnamed_field.name => doctree::Tuple,
+            _ => doctree::Plain,
+        },
+        generics: t.generics.clean(),
+        fields: fields.iter().map(|f| f.clean()).collect(),
+        fields_stripped: false,
+    }
+}
+
+fn build_type(tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEnum {
+    let t = ty::lookup_item_type(tcx, did);
+    match ty::get(t.ty).sty {
+        ty::ty_enum(edid, _) => {
+            return clean::EnumItem(clean::Enum {
+                generics: t.generics.clean(),
+                variants_stripped: false,
+                variants: ty::enum_variants(tcx, edid).clean(),
+            })
+        }
+        _ => {}
+    }
+
+    clean::TypedefItem(clean::Typedef {
+        type_: t.ty.clean(),
+        generics: t.generics.clean(),
+    })
+}
+
+fn build_impls(tcx: &ty::ctxt,
+               did: ast::DefId) -> Vec<clean::Item> {
+    ty::populate_implementations_for_type_if_necessary(tcx, did);
+    let mut impls = Vec::new();
+
+    match tcx.inherent_impls.borrow().find(&did) {
+        None => {}
+        Some(i) => {
+            impls.extend(i.borrow().iter().map(|&did| { build_impl(tcx, did) }));
+        }
+    }
+
+    impls
+}
+
+fn build_impl(tcx: &ty::ctxt, did: ast::DefId) -> clean::Item {
+    let associated_trait = csearch::get_impl_trait(tcx, did);
+    let attrs = load_attrs(tcx, did);
+    let ty = ty::lookup_item_type(tcx, did);
+    let methods = csearch::get_impl_methods(&tcx.sess.cstore, did).iter().map(|did| {
+        let mut item = match ty::method(tcx, *did).clean() {
+            clean::Provided(item) => item,
+            clean::Required(item) => item,
+        };
+        item.inner = match item.inner.clone() {
+            clean::TyMethodItem(clean::TyMethod {
+                fn_style, decl, self_, generics
+            }) => {
+                clean::MethodItem(clean::Method {
+                    fn_style: fn_style,
+                    decl: decl,
+                    self_: self_,
+                    generics: generics,
+                })
+            }
+            _ => fail!("not a tymethod"),
+        };
+        item
+    }).collect();
+    clean::Item {
+        inner: clean::ImplItem(clean::Impl {
+            derived: clean::detect_derived(attrs.as_slice()),
+            trait_: associated_trait.clean().map(|bound| {
+                match bound {
+                    clean::TraitBound(ty) => ty,
+                    clean::RegionBound => unreachable!(),
+                }
+            }),
+            for_: ty.ty.clean(),
+            generics: ty.generics.clean(),
+            methods: methods,
+        }),
+        source: clean::Span::empty(),
+        name: None,
+        attrs: attrs,
+        visibility: Some(ast::Inherited),
+        def_id: did,
+    }
+}
+
+fn build_module(cx: &core::DocContext, tcx: &ty::ctxt,
+                did: ast::DefId) -> clean::Module {
+    let mut items = Vec::new();
+
+    // FIXME: this doesn't handle reexports inside the module itself.
+    //        Should they be handled?
+    csearch::each_child_of_item(&tcx.sess.cstore, did, |def, _, _| {
+        match def {
+            decoder::DlDef(def) => {
+                match try_inline_def(cx, tcx, def) {
+                    Some(i) => items.extend(i.move_iter()),
+                    None => {}
+                }
+            }
+            decoder::DlImpl(did) => items.push(build_impl(tcx, did)),
+            decoder::DlField => fail!("unimplemented field"),
+        }
+    });
+
+    clean::Module {
+        items: items,
+        is_crate: false,
+    }
+}
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
new file mode 100644 (file)
index 0000000..f0f6842
--- /dev/null
@@ -0,0 +1,1830 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! This module contains the "cleaned" pieces of the AST, and the functions
+//! that clean them.
+
+use syntax;
+use syntax::ast;
+use syntax::ast_util;
+use syntax::attr;
+use syntax::attr::{AttributeMethods, AttrMetaMethods};
+use syntax::codemap::Pos;
+use syntax::parse::token::InternedString;
+use syntax::parse::token;
+
+use rustc::back::link;
+use rustc::driver::driver;
+use rustc::metadata::cstore;
+use rustc::metadata::csearch;
+use rustc::metadata::decoder;
+use rustc::middle::ty;
+
+use std::rc::Rc;
+
+use core;
+use doctree;
+use visit_ast;
+
+/// A stable identifier to the particular version of JSON output.
+/// Increment this when the `Crate` and related structures change.
+pub static SCHEMA_VERSION: &'static str = "0.8.2";
+
+mod inline;
+
+pub trait Clean<T> {
+    fn clean(&self) -> T;
+}
+
+impl<T: Clean<U>, U> Clean<Vec<U>> for Vec<T> {
+    fn clean(&self) -> Vec<U> {
+        self.iter().map(|x| x.clean()).collect()
+    }
+}
+
+impl<T: Clean<U>, U> Clean<U> for @T {
+    fn clean(&self) -> U {
+        (**self).clean()
+    }
+}
+
+impl<T: Clean<U>, U> Clean<U> for Rc<T> {
+    fn clean(&self) -> U {
+        (**self).clean()
+    }
+}
+
+impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
+    fn clean(&self) -> Option<U> {
+        match self {
+            &None => None,
+            &Some(ref v) => Some(v.clean())
+        }
+    }
+}
+
+impl<T: Clean<U>, U> Clean<Vec<U>> for syntax::owned_slice::OwnedSlice<T> {
+    fn clean(&self) -> Vec<U> {
+        self.iter().map(|x| x.clean()).collect()
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct Crate {
+    pub name: String,
+    pub module: Option<Item>,
+    pub externs: Vec<(ast::CrateNum, ExternalCrate)>,
+}
+
+impl<'a> Clean<Crate> for visit_ast::RustdocVisitor<'a> {
+    fn clean(&self) -> Crate {
+        let cx = super::ctxtkey.get().unwrap();
+
+        let mut externs = Vec::new();
+        cx.sess().cstore.iter_crate_data(|n, meta| {
+            externs.push((n, meta.clean()));
+        });
+
+        let input = driver::FileInput(cx.src.clone());
+        let t_outputs = driver::build_output_filenames(&input,
+                                                       &None,
+                                                       &None,
+                                                       self.attrs.as_slice(),
+                                                       cx.sess());
+        let id = link::find_crate_id(self.attrs.as_slice(),
+                                     t_outputs.out_filestem.as_slice());
+        Crate {
+            name: id.name.to_strbuf(),
+            module: Some(self.module.clean()),
+            externs: externs,
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct ExternalCrate {
+    pub name: String,
+    pub attrs: Vec<Attribute>,
+}
+
+impl Clean<ExternalCrate> for cstore::crate_metadata {
+    fn clean(&self) -> ExternalCrate {
+        ExternalCrate {
+            name: self.name.to_strbuf(),
+            attrs: decoder::get_crate_attributes(self.data()).clean()
+                                                             .move_iter()
+                                                             .collect(),
+        }
+    }
+}
+
+/// Anything with a source location and set of attributes and, optionally, a
+/// name. That is, anything that can be documented. This doesn't correspond
+/// directly to the AST's concept of an item; it's a strict superset.
+#[deriving(Clone, Encodable, Decodable)]
+pub struct Item {
+    /// Stringified span
+    pub source: Span,
+    /// Not everything has a name. E.g., impls
+    pub name: Option<String>,
+    pub attrs: Vec<Attribute> ,
+    pub inner: ItemEnum,
+    pub visibility: Option<Visibility>,
+    pub def_id: ast::DefId,
+}
+
+impl Item {
+    /// Finds the `doc` attribute as a List and returns the list of attributes
+    /// nested inside.
+    pub fn doc_list<'a>(&'a self) -> Option<&'a [Attribute]> {
+        for attr in self.attrs.iter() {
+            match *attr {
+                List(ref x, ref list) if "doc" == x.as_slice() => {
+                    return Some(list.as_slice());
+                }
+                _ => {}
+            }
+        }
+        return None;
+    }
+
+    /// Finds the `doc` attribute as a NameValue and returns the corresponding
+    /// value found.
+    pub fn doc_value<'a>(&'a self) -> Option<&'a str> {
+        for attr in self.attrs.iter() {
+            match *attr {
+                NameValue(ref x, ref v) if "doc" == x.as_slice() => {
+                    return Some(v.as_slice());
+                }
+                _ => {}
+            }
+        }
+        return None;
+    }
+
+    pub fn is_hidden_from_doc(&self) -> bool {
+        match self.doc_list() {
+            Some(ref l) => {
+                for innerattr in l.iter() {
+                    match *innerattr {
+                        Word(ref s) if "hidden" == s.as_slice() => {
+                            return true
+                        }
+                        _ => (),
+                    }
+                }
+            },
+            None => ()
+        }
+        return false;
+    }
+
+    pub fn is_mod(&self) -> bool {
+        match self.inner { ModuleItem(..) => true, _ => false }
+    }
+    pub fn is_trait(&self) -> bool {
+        match self.inner { TraitItem(..) => true, _ => false }
+    }
+    pub fn is_struct(&self) -> bool {
+        match self.inner { StructItem(..) => true, _ => false }
+    }
+    pub fn is_enum(&self) -> bool {
+        match self.inner { EnumItem(..) => true, _ => false }
+    }
+    pub fn is_fn(&self) -> bool {
+        match self.inner { FunctionItem(..) => true, _ => false }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub enum ItemEnum {
+    StructItem(Struct),
+    EnumItem(Enum),
+    FunctionItem(Function),
+    ModuleItem(Module),
+    TypedefItem(Typedef),
+    StaticItem(Static),
+    TraitItem(Trait),
+    ImplItem(Impl),
+    /// `use` and `extern crate`
+    ViewItemItem(ViewItem),
+    /// A method signature only. Used for required methods in traits (ie,
+    /// non-default-methods).
+    TyMethodItem(TyMethod),
+    /// A method with a body.
+    MethodItem(Method),
+    StructFieldItem(StructField),
+    VariantItem(Variant),
+    /// `fn`s from an extern block
+    ForeignFunctionItem(Function),
+    /// `static`s from an extern block
+    ForeignStaticItem(Static),
+    MacroItem(Macro),
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct Module {
+    pub items: Vec<Item>,
+    pub is_crate: bool,
+}
+
+impl Clean<Item> for doctree::Module {
+    fn clean(&self) -> Item {
+        let name = if self.name.is_some() {
+            self.name.unwrap().clean()
+        } else {
+            "".to_strbuf()
+        };
+        let mut foreigns = Vec::new();
+        for subforeigns in self.foreigns.clean().move_iter() {
+            for foreign in subforeigns.move_iter() {
+                foreigns.push(foreign)
+            }
+        }
+        let items: Vec<Vec<Item> > = vec!(
+            self.structs.clean().move_iter().collect(),
+            self.enums.clean().move_iter().collect(),
+            self.fns.clean().move_iter().collect(),
+            foreigns,
+            self.mods.clean().move_iter().collect(),
+            self.typedefs.clean().move_iter().collect(),
+            self.statics.clean().move_iter().collect(),
+            self.traits.clean().move_iter().collect(),
+            self.impls.clean().move_iter().collect(),
+            self.view_items.clean().move_iter()
+                           .flat_map(|s| s.move_iter()).collect(),
+            self.macros.clean().move_iter().collect()
+        );
+
+        // determine if we should display the inner contents or
+        // the outer `mod` item for the source code.
+        let where = {
+            let ctxt = super::ctxtkey.get().unwrap();
+            let cm = ctxt.sess().codemap();
+            let outer = cm.lookup_char_pos(self.where_outer.lo);
+            let inner = cm.lookup_char_pos(self.where_inner.lo);
+            if outer.file.start_pos == inner.file.start_pos {
+                // mod foo { ... }
+                self.where_outer
+            } else {
+                // mod foo; (and a separate FileMap for the contents)
+                self.where_inner
+            }
+        };
+
+        Item {
+            name: Some(name),
+            attrs: self.attrs.clean(),
+            source: where.clean(),
+            visibility: self.vis.clean(),
+            def_id: ast_util::local_def(self.id),
+            inner: ModuleItem(Module {
+               is_crate: self.is_crate,
+               items: items.iter()
+                           .flat_map(|x| x.iter().map(|x| (*x).clone()))
+                           .collect(),
+            })
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub enum Attribute {
+    Word(String),
+    List(String, Vec<Attribute> ),
+    NameValue(String, String)
+}
+
+impl Clean<Attribute> for ast::MetaItem {
+    fn clean(&self) -> Attribute {
+        match self.node {
+            ast::MetaWord(ref s) => Word(s.get().to_strbuf()),
+            ast::MetaList(ref s, ref l) => {
+                List(s.get().to_strbuf(), l.clean().move_iter().collect())
+            }
+            ast::MetaNameValue(ref s, ref v) => {
+                NameValue(s.get().to_strbuf(), lit_to_str(v))
+            }
+        }
+    }
+}
+
+impl Clean<Attribute> for ast::Attribute {
+    fn clean(&self) -> Attribute {
+        self.desugar_doc().node.value.clean()
+    }
+}
+
+// This is a rough approximation that gets us what we want.
+impl attr::AttrMetaMethods for Attribute {
+    fn name(&self) -> InternedString {
+        match *self {
+            Word(ref n) | List(ref n, _) | NameValue(ref n, _) => {
+                token::intern_and_get_ident(n.as_slice())
+            }
+        }
+    }
+
+    fn value_str(&self) -> Option<InternedString> {
+        match *self {
+            NameValue(_, ref v) => {
+                Some(token::intern_and_get_ident(v.as_slice()))
+            }
+            _ => None,
+        }
+    }
+    fn meta_item_list<'a>(&'a self) -> Option<&'a [@ast::MetaItem]> { None }
+    fn name_str_pair(&self) -> Option<(InternedString, InternedString)> {
+        None
+    }
+}
+impl<'a> attr::AttrMetaMethods for &'a Attribute {
+    fn name(&self) -> InternedString { (**self).name() }
+    fn value_str(&self) -> Option<InternedString> { (**self).value_str() }
+    fn meta_item_list<'a>(&'a self) -> Option<&'a [@ast::MetaItem]> { None }
+    fn name_str_pair(&self) -> Option<(InternedString, InternedString)> {
+        None
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct TyParam {
+    pub name: String,
+    pub did: ast::DefId,
+    pub bounds: Vec<TyParamBound>,
+}
+
+impl Clean<TyParam> for ast::TyParam {
+    fn clean(&self) -> TyParam {
+        TyParam {
+            name: self.ident.clean(),
+            did: ast::DefId { krate: ast::LOCAL_CRATE, node: self.id },
+            bounds: self.bounds.clean().move_iter().collect(),
+        }
+    }
+}
+
+impl Clean<TyParam> for ty::TypeParameterDef {
+    fn clean(&self) -> TyParam {
+        let cx = super::ctxtkey.get().unwrap();
+        cx.external_typarams.borrow_mut().get_mut_ref().insert(self.def_id,
+                                                               self.ident.clean());
+        TyParam {
+            name: self.ident.clean(),
+            did: self.def_id,
+            bounds: self.bounds.clean(),
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub enum TyParamBound {
+    RegionBound,
+    TraitBound(Type)
+}
+
+impl Clean<TyParamBound> for ast::TyParamBound {
+    fn clean(&self) -> TyParamBound {
+        match *self {
+            ast::StaticRegionTyParamBound => RegionBound,
+            ast::OtherRegionTyParamBound(_) => RegionBound,
+            ast::TraitTyParamBound(ref t) => TraitBound(t.clean()),
+        }
+    }
+}
+
+fn external_path(name: &str) -> Path {
+    Path {
+        global: false,
+        segments: vec![PathSegment {
+            name: name.to_strbuf(),
+            lifetimes: Vec::new(),
+            types: Vec::new(),
+        }]
+    }
+}
+
+impl Clean<TyParamBound> for ty::BuiltinBound {
+    fn clean(&self) -> TyParamBound {
+        let cx = super::ctxtkey.get().unwrap();
+        let tcx = match cx.maybe_typed {
+            core::Typed(ref tcx) => tcx,
+            core::NotTyped(_) => return RegionBound,
+        };
+        let (did, path) = match *self {
+            ty::BoundStatic => return RegionBound,
+            ty::BoundSend =>
+                (tcx.lang_items.send_trait().unwrap(), external_path("Send")),
+            ty::BoundSized =>
+                (tcx.lang_items.sized_trait().unwrap(), external_path("Sized")),
+            ty::BoundCopy =>
+                (tcx.lang_items.copy_trait().unwrap(), external_path("Copy")),
+            ty::BoundShare =>
+                (tcx.lang_items.share_trait().unwrap(), external_path("Share")),
+        };
+        let fqn = csearch::get_item_path(tcx, did);
+        let fqn = fqn.move_iter().map(|i| i.to_str().to_strbuf()).collect();
+        cx.external_paths.borrow_mut().get_mut_ref().insert(did,
+                                                            (fqn, TypeTrait));
+        TraitBound(ResolvedPath {
+            path: path,
+            typarams: None,
+            did: did,
+        })
+    }
+}
+
+impl Clean<TyParamBound> for ty::TraitRef {
+    fn clean(&self) -> TyParamBound {
+        let cx = super::ctxtkey.get().unwrap();
+        let tcx = match cx.maybe_typed {
+            core::Typed(ref tcx) => tcx,
+            core::NotTyped(_) => return RegionBound,
+        };
+        let fqn = csearch::get_item_path(tcx, self.def_id);
+        let fqn = fqn.move_iter().map(|i| i.to_str().to_strbuf())
+                     .collect::<Vec<String>>();
+        let path = external_path(fqn.last().unwrap().as_slice());
+        cx.external_paths.borrow_mut().get_mut_ref().insert(self.def_id,
+                                                            (fqn, TypeTrait));
+        TraitBound(ResolvedPath {
+            path: path,
+            typarams: None,
+            did: self.def_id,
+        })
+    }
+}
+
+impl Clean<Vec<TyParamBound>> for ty::ParamBounds {
+    fn clean(&self) -> Vec<TyParamBound> {
+        let mut v = Vec::new();
+        for b in self.builtin_bounds.iter() {
+            if b != ty::BoundSized {
+                v.push(b.clean());
+            }
+        }
+        for t in self.trait_bounds.iter() {
+            v.push(t.clean());
+        }
+        return v;
+    }
+}
+
+impl Clean<Option<Vec<TyParamBound>>> for ty::substs {
+    fn clean(&self) -> Option<Vec<TyParamBound>> {
+        let mut v = Vec::new();
+        match self.regions {
+            ty::NonerasedRegions(..) => v.push(RegionBound),
+            ty::ErasedRegions => {}
+        }
+        v.extend(self.tps.iter().map(|t| TraitBound(t.clean())));
+
+        if v.len() > 0 {Some(v)} else {None}
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable, Eq)]
+pub struct Lifetime(String);
+
+impl Lifetime {
+    pub fn get_ref<'a>(&'a self) -> &'a str {
+        let Lifetime(ref s) = *self;
+        let s: &'a str = s.as_slice();
+        return s;
+    }
+}
+
+impl Clean<Lifetime> for ast::Lifetime {
+    fn clean(&self) -> Lifetime {
+        Lifetime(token::get_name(self.name).get().to_strbuf())
+    }
+}
+
+impl Clean<Lifetime> for ty::RegionParameterDef {
+    fn clean(&self) -> Lifetime {
+        Lifetime(token::get_name(self.name).get().to_strbuf())
+    }
+}
+
+impl Clean<Option<Lifetime>> for ty::Region {
+    fn clean(&self) -> Option<Lifetime> {
+        match *self {
+            ty::ReStatic => Some(Lifetime("static".to_strbuf())),
+            ty::ReLateBound(_, ty::BrNamed(_, name)) =>
+                Some(Lifetime(token::get_name(name).get().to_strbuf())),
+
+            ty::ReLateBound(..) |
+            ty::ReEarlyBound(..) |
+            ty::ReFree(..) |
+            ty::ReScope(..) |
+            ty::ReInfer(..) |
+            ty::ReEmpty(..) => None
+        }
+    }
+}
+
+// maybe use a Generic enum and use ~[Generic]?
+#[deriving(Clone, Encodable, Decodable)]
+pub struct Generics {
+    pub lifetimes: Vec<Lifetime>,
+    pub type_params: Vec<TyParam>,
+}
+
+impl Clean<Generics> for ast::Generics {
+    fn clean(&self) -> Generics {
+        Generics {
+            lifetimes: self.lifetimes.clean().move_iter().collect(),
+            type_params: self.ty_params.clean().move_iter().collect(),
+        }
+    }
+}
+
+impl Clean<Generics> for ty::Generics {
+    fn clean(&self) -> Generics {
+        Generics {
+            lifetimes: self.region_param_defs.clean(),
+            type_params: self.type_param_defs.clean(),
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct Method {
+    pub generics: Generics,
+    pub self_: SelfTy,
+    pub fn_style: ast::FnStyle,
+    pub decl: FnDecl,
+}
+
+impl Clean<Item> for ast::Method {
+    fn clean(&self) -> Item {
+        let inputs = match self.explicit_self.node {
+            ast::SelfStatic => self.decl.inputs.as_slice(),
+            _ => self.decl.inputs.slice_from(1)
+        };
+        let decl = FnDecl {
+            inputs: Arguments {
+                values: inputs.iter().map(|x| x.clean()).collect(),
+            },
+            output: (self.decl.output.clean()),
+            cf: self.decl.cf.clean(),
+            attrs: Vec::new()
+        };
+        Item {
+            name: Some(self.ident.clean()),
+            attrs: self.attrs.clean().move_iter().collect(),
+            source: self.span.clean(),
+            def_id: ast_util::local_def(self.id.clone()),
+            visibility: self.vis.clean(),
+            inner: MethodItem(Method {
+                generics: self.generics.clean(),
+                self_: self.explicit_self.node.clean(),
+                fn_style: self.fn_style.clone(),
+                decl: decl,
+            }),
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct TyMethod {
+    pub fn_style: ast::FnStyle,
+    pub decl: FnDecl,
+    pub generics: Generics,
+    pub self_: SelfTy,
+}
+
+impl Clean<Item> for ast::TypeMethod {
+    fn clean(&self) -> Item {
+        let inputs = match self.explicit_self.node {
+            ast::SelfStatic => self.decl.inputs.as_slice(),
+            _ => self.decl.inputs.slice_from(1)
+        };
+        let decl = FnDecl {
+            inputs: Arguments {
+                values: inputs.iter().map(|x| x.clean()).collect(),
+            },
+            output: (self.decl.output.clean()),
+            cf: self.decl.cf.clean(),
+            attrs: Vec::new()
+        };
+        Item {
+            name: Some(self.ident.clean()),
+            attrs: self.attrs.clean().move_iter().collect(),
+            source: self.span.clean(),
+            def_id: ast_util::local_def(self.id),
+            visibility: None,
+            inner: TyMethodItem(TyMethod {
+                fn_style: self.fn_style.clone(),
+                decl: decl,
+                self_: self.explicit_self.node.clean(),
+                generics: self.generics.clean(),
+            }),
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable, Eq)]
+pub enum SelfTy {
+    SelfStatic,
+    SelfValue,
+    SelfBorrowed(Option<Lifetime>, Mutability),
+    SelfOwned,
+}
+
+impl Clean<SelfTy> for ast::ExplicitSelf_ {
+    fn clean(&self) -> SelfTy {
+        match *self {
+            ast::SelfStatic => SelfStatic,
+            ast::SelfValue => SelfValue,
+            ast::SelfUniq => SelfOwned,
+            ast::SelfRegion(lt, mt) => SelfBorrowed(lt.clean(), mt.clean()),
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct Function {
+    pub decl: FnDecl,
+    pub generics: Generics,
+    pub fn_style: ast::FnStyle,
+}
+
+impl Clean<Item> for doctree::Function {
+    fn clean(&self) -> Item {
+        Item {
+            name: Some(self.name.clean()),
+            attrs: self.attrs.clean(),
+            source: self.where.clean(),
+            visibility: self.vis.clean(),
+            def_id: ast_util::local_def(self.id),
+            inner: FunctionItem(Function {
+                decl: self.decl.clean(),
+                generics: self.generics.clean(),
+                fn_style: self.fn_style,
+            }),
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct ClosureDecl {
+    pub lifetimes: Vec<Lifetime>,
+    pub decl: FnDecl,
+    pub onceness: ast::Onceness,
+    pub fn_style: ast::FnStyle,
+    pub bounds: Vec<TyParamBound>,
+}
+
+impl Clean<ClosureDecl> for ast::ClosureTy {
+    fn clean(&self) -> ClosureDecl {
+        ClosureDecl {
+            lifetimes: self.lifetimes.clean(),
+            decl: self.decl.clean(),
+            onceness: self.onceness,
+            fn_style: self.fn_style,
+            bounds: match self.bounds {
+                Some(ref x) => x.clean().move_iter().collect(),
+                None        => Vec::new()
+            },
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct FnDecl {
+    pub inputs: Arguments,
+    pub output: Type,
+    pub cf: RetStyle,
+    pub attrs: Vec<Attribute>,
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct Arguments {
+    pub values: Vec<Argument>,
+}
+
+impl Clean<FnDecl> for ast::FnDecl {
+    fn clean(&self) -> FnDecl {
+        FnDecl {
+            inputs: Arguments {
+                values: self.inputs.iter().map(|x| x.clean()).collect(),
+            },
+            output: (self.output.clean()),
+            cf: self.cf.clean(),
+            attrs: Vec::new()
+        }
+    }
+}
+
+impl<'a> Clean<FnDecl> for (ast::DefId, &'a ty::FnSig) {
+    fn clean(&self) -> FnDecl {
+        let cx = super::ctxtkey.get().unwrap();
+        let tcx = match cx.maybe_typed {
+            core::Typed(ref tcx) => tcx,
+            core::NotTyped(_) => unreachable!(),
+        };
+        let (did, sig) = *self;
+        let mut names = if did.node != 0 {
+            csearch::get_method_arg_names(&tcx.sess.cstore, did).move_iter()
+        } else {
+            Vec::new().move_iter()
+        }.peekable();
+        if names.peek().map(|s| s.as_slice()) == Some("self") {
+            let _ = names.next();
+        }
+        FnDecl {
+            output: sig.output.clean(),
+            cf: Return,
+            attrs: Vec::new(),
+            inputs: Arguments {
+                values: sig.inputs.iter().map(|t| {
+                    Argument {
+                        type_: t.clean(),
+                        id: 0,
+                        name: names.next().unwrap_or("".to_strbuf()),
+                    }
+                }).collect(),
+            },
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct Argument {
+    pub type_: Type,
+    pub name: String,
+    pub id: ast::NodeId,
+}
+
+impl Clean<Argument> for ast::Arg {
+    fn clean(&self) -> Argument {
+        Argument {
+            name: name_from_pat(self.pat),
+            type_: (self.ty.clean()),
+            id: self.id
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub enum RetStyle {
+    NoReturn,
+    Return
+}
+
+impl Clean<RetStyle> for ast::RetStyle {
+    fn clean(&self) -> RetStyle {
+        match *self {
+            ast::Return => Return,
+            ast::NoReturn => NoReturn
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct Trait {
+    pub methods: Vec<TraitMethod>,
+    pub generics: Generics,
+    pub parents: Vec<Type>,
+}
+
+impl Clean<Item> for doctree::Trait {
+    fn clean(&self) -> Item {
+        Item {
+            name: Some(self.name.clean()),
+            attrs: self.attrs.clean(),
+            source: self.where.clean(),
+            def_id: ast_util::local_def(self.id),
+            visibility: self.vis.clean(),
+            inner: TraitItem(Trait {
+                methods: self.methods.clean(),
+                generics: self.generics.clean(),
+                parents: self.parents.clean(),
+            }),
+        }
+    }
+}
+
+impl Clean<Type> for ast::TraitRef {
+    fn clean(&self) -> Type {
+        resolve_type(self.path.clean(), None, self.ref_id)
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub enum TraitMethod {
+    Required(Item),
+    Provided(Item),
+}
+
+impl TraitMethod {
+    pub fn is_req(&self) -> bool {
+        match self {
+            &Required(..) => true,
+            _ => false,
+        }
+    }
+    pub fn is_def(&self) -> bool {
+        match self {
+            &Provided(..) => true,
+            _ => false,
+        }
+    }
+    pub fn item<'a>(&'a self) -> &'a Item {
+        match *self {
+            Required(ref item) => item,
+            Provided(ref item) => item,
+        }
+    }
+}
+
+impl Clean<TraitMethod> for ast::TraitMethod {
+    fn clean(&self) -> TraitMethod {
+        match self {
+            &ast::Required(ref t) => Required(t.clean()),
+            &ast::Provided(ref t) => Provided(t.clean()),
+        }
+    }
+}
+
+impl Clean<TraitMethod> for ty::Method {
+    fn clean(&self) -> TraitMethod {
+        let m = if self.provided_source.is_some() {Provided} else {Required};
+        let cx = super::ctxtkey.get().unwrap();
+        let tcx = match cx.maybe_typed {
+            core::Typed(ref tcx) => tcx,
+            core::NotTyped(_) => unreachable!(),
+        };
+        let (self_, sig) = match self.explicit_self {
+            ast::SelfStatic => (ast::SelfStatic.clean(), self.fty.sig.clone()),
+            s => {
+                let sig = ty::FnSig {
+                    inputs: Vec::from_slice(self.fty.sig.inputs.slice_from(1)),
+                    ..self.fty.sig.clone()
+                };
+                let s = match s {
+                    ast::SelfRegion(..) => {
+                        match ty::get(*self.fty.sig.inputs.get(0)).sty {
+                            ty::ty_rptr(r, mt) => {
+                                SelfBorrowed(r.clean(), mt.mutbl.clean())
+                            }
+                            _ => s.clean(),
+                        }
+                    }
+                    s => s.clean(),
+                };
+                (s, sig)
+            }
+        };
+
+        m(Item {
+            name: Some(self.ident.clean()),
+            visibility: Some(ast::Inherited),
+            def_id: self.def_id,
+            attrs: inline::load_attrs(tcx, self.def_id),
+            source: Span::empty(),
+            inner: TyMethodItem(TyMethod {
+                fn_style: self.fty.fn_style,
+                generics: self.generics.clean(),
+                self_: self_,
+                decl: (self.def_id, &sig).clean(),
+            })
+        })
+    }
+}
+
+/// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
+/// type out of the AST/ty::ctxt given one of these, if more information is needed. Most importantly
+/// it does not preserve mutability or boxes.
+#[deriving(Clone, Encodable, Decodable)]
+pub enum Type {
+    /// structs/enums/traits (anything that'd be an ast::TyPath)
+    ResolvedPath {
+        pub path: Path,
+        pub typarams: Option<Vec<TyParamBound>>,
+        pub did: ast::DefId,
+    },
+    // I have no idea how to usefully use this.
+    TyParamBinder(ast::NodeId),
+    /// For parameterized types, so the consumer of the JSON don't go looking
+    /// for types which don't exist anywhere.
+    Generic(ast::DefId),
+    /// For references to self
+    Self(ast::DefId),
+    /// Primitives are just the fixed-size numeric types (plus int/uint/float), and char.
+    Primitive(ast::PrimTy),
+    Closure(Box<ClosureDecl>, Option<Lifetime>),
+    Proc(Box<ClosureDecl>),
+    /// extern "ABI" fn
+    BareFunction(Box<BareFunctionDecl>),
+    Tuple(Vec<Type>),
+    Vector(Box<Type>),
+    FixedVector(Box<Type>, String),
+    String,
+    Bool,
+    /// aka TyNil
+    Unit,
+    /// aka TyBot
+    Bottom,
+    Unique(Box<Type>),
+    Managed(Box<Type>),
+    RawPointer(Mutability, Box<Type>),
+    BorrowedRef {
+        pub lifetime: Option<Lifetime>,
+        pub mutability: Mutability,
+        pub type_: Box<Type>,
+    },
+    // region, raw, other boxes, mutable
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub enum TypeKind {
+    TypeEnum,
+    TypeFunction,
+    TypeModule,
+    TypeStatic,
+    TypeStruct,
+    TypeTrait,
+    TypeVariant,
+}
+
+impl Clean<Type> for ast::Ty {
+    fn clean(&self) -> Type {
+        use syntax::ast::*;
+        match self.node {
+            TyNil => Unit,
+            TyPtr(ref m) => RawPointer(m.mutbl.clean(), box m.ty.clean()),
+            TyRptr(ref l, ref m) =>
+                BorrowedRef {lifetime: l.clean(), mutability: m.mutbl.clean(),
+                             type_: box m.ty.clean()},
+            TyBox(ty) => Managed(box ty.clean()),
+            TyUniq(ty) => Unique(box ty.clean()),
+            TyVec(ty) => Vector(box ty.clean()),
+            TyFixedLengthVec(ty, ref e) => FixedVector(box ty.clean(),
+                                                       e.span.to_src()),
+            TyTup(ref tys) => Tuple(tys.iter().map(|x| x.clean()).collect()),
+            TyPath(ref p, ref tpbs, id) => {
+                resolve_type(p.clean(),
+                             tpbs.clean().map(|x| x.move_iter().collect()),
+                             id)
+            }
+            TyClosure(ref c, region) => Closure(box c.clean(), region.clean()),
+            TyProc(ref c) => Proc(box c.clean()),
+            TyBareFn(ref barefn) => BareFunction(box barefn.clean()),
+            TyBot => Bottom,
+            ref x => fail!("Unimplemented type {:?}", x),
+        }
+    }
+}
+
+impl Clean<Type> for ty::t {
+    fn clean(&self) -> Type {
+        match ty::get(*self).sty {
+            ty::ty_nil => Unit,
+            ty::ty_bot => Bottom,
+            ty::ty_bool => Bool,
+            ty::ty_char => Primitive(ast::TyChar),
+            ty::ty_int(t) => Primitive(ast::TyInt(t)),
+            ty::ty_uint(u) => Primitive(ast::TyUint(u)),
+            ty::ty_float(f) => Primitive(ast::TyFloat(f)),
+            ty::ty_box(t) => Managed(box t.clean()),
+            ty::ty_uniq(t) => Unique(box t.clean()),
+            ty::ty_str => String,
+            ty::ty_vec(mt, None) => Vector(box mt.ty.clean()),
+            ty::ty_vec(mt, Some(i)) => FixedVector(box mt.ty.clean(),
+                                                   format_strbuf!("{}", i)),
+            ty::ty_ptr(mt) => RawPointer(mt.mutbl.clean(), box mt.ty.clean()),
+            ty::ty_rptr(r, mt) => BorrowedRef {
+                lifetime: r.clean(),
+                mutability: mt.mutbl.clean(),
+                type_: box mt.ty.clean(),
+            },
+            ty::ty_bare_fn(ref fty) => BareFunction(box BareFunctionDecl {
+                fn_style: fty.fn_style,
+                generics: Generics {
+                    lifetimes: Vec::new(), type_params: Vec::new()
+                },
+                decl: (ast_util::local_def(0), &fty.sig).clean(),
+                abi: fty.abi.to_str().to_strbuf(),
+            }),
+            ty::ty_closure(ref fty) => {
+                let decl = box ClosureDecl {
+                    lifetimes: Vec::new(), // FIXME: this looks wrong...
+                    decl: (ast_util::local_def(0), &fty.sig).clean(),
+                    onceness: fty.onceness,
+                    fn_style: fty.fn_style,
+                    bounds: fty.bounds.iter().map(|i| i.clean()).collect(),
+                };
+                match fty.store {
+                    ty::UniqTraitStore => Proc(decl),
+                    ty::RegionTraitStore(ref r, _) => Closure(decl, r.clean()),
+                }
+            }
+            ty::ty_struct(did, ref substs) |
+            ty::ty_enum(did, ref substs) |
+            ty::ty_trait(box ty::TyTrait { def_id: did, ref substs, .. }) => {
+                let cx = super::ctxtkey.get().unwrap();
+                let tcx = match cx.maybe_typed {
+                    core::Typed(ref tycx) => tycx,
+                    core::NotTyped(_) => unreachable!(),
+                };
+                let fqn = csearch::get_item_path(tcx, did);
+                let fqn: Vec<String> = fqn.move_iter().map(|i| {
+                    i.to_str().to_strbuf()
+                }).collect();
+                let mut path = external_path(fqn.last()
+                                                .unwrap()
+                                                .to_str()
+                                                .as_slice());
+                let kind = match ty::get(*self).sty {
+                    ty::ty_struct(..) => TypeStruct,
+                    ty::ty_trait(..) => TypeTrait,
+                    _ => TypeEnum,
+                };
+                path.segments.get_mut(0).lifetimes = match substs.regions {
+                    ty::ErasedRegions => Vec::new(),
+                    ty::NonerasedRegions(ref v) => {
+                        v.iter().filter_map(|v| v.clean()).collect()
+                    }
+                };
+                path.segments.get_mut(0).types = substs.tps.clean();
+                cx.external_paths.borrow_mut().get_mut_ref().insert(did,
+                                                                    (fqn, kind));
+                ResolvedPath {
+                    path: path,
+                    typarams: None,
+                    did: did,
+                }
+            }
+            ty::ty_tup(ref t) => Tuple(t.iter().map(|t| t.clean()).collect()),
+
+            ty::ty_param(ref p) => Generic(p.def_id),
+            ty::ty_self(did) => Self(did),
+
+            ty::ty_infer(..) => fail!("ty_infer"),
+            ty::ty_err => fail!("ty_err"),
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub enum StructField {
+    HiddenStructField, // inserted later by strip passes
+    TypedStructField(Type),
+}
+
+impl Clean<Item> for ast::StructField {
+    fn clean(&self) -> Item {
+        let (name, vis) = match self.node.kind {
+            ast::NamedField(id, vis) => (Some(id), vis),
+            ast::UnnamedField(vis) => (None, vis)
+        };
+        Item {
+            name: name.clean(),
+            attrs: self.node.attrs.clean().move_iter().collect(),
+            source: self.span.clean(),
+            visibility: Some(vis),
+            def_id: ast_util::local_def(self.node.id),
+            inner: StructFieldItem(TypedStructField(self.node.ty.clean())),
+        }
+    }
+}
+
+impl Clean<Item> for ty::field_ty {
+    fn clean(&self) -> Item {
+        use syntax::parse::token::special_idents::unnamed_field;
+        let name = if self.name == unnamed_field.name {
+            None
+        } else {
+            Some(self.name)
+        };
+        let cx = super::ctxtkey.get().unwrap();
+        let tcx = match cx.maybe_typed {
+            core::Typed(ref tycx) => tycx,
+            core::NotTyped(_) => unreachable!(),
+        };
+        let ty = ty::lookup_item_type(tcx, self.id);
+        Item {
+            name: name.clean(),
+            attrs: inline::load_attrs(tcx, self.id),
+            source: Span::empty(),
+            visibility: Some(self.vis),
+            def_id: self.id,
+            inner: StructFieldItem(TypedStructField(ty.ty.clean())),
+        }
+    }
+}
+
+pub type Visibility = ast::Visibility;
+
+impl Clean<Option<Visibility>> for ast::Visibility {
+    fn clean(&self) -> Option<Visibility> {
+        Some(*self)
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct Struct {
+    pub struct_type: doctree::StructType,
+    pub generics: Generics,
+    pub fields: Vec<Item>,
+    pub fields_stripped: bool,
+}
+
+impl Clean<Item> for doctree::Struct {
+    fn clean(&self) -> Item {
+        Item {
+            name: Some(self.name.clean()),
+            attrs: self.attrs.clean(),
+            source: self.where.clean(),
+            def_id: ast_util::local_def(self.id),
+            visibility: self.vis.clean(),
+            inner: StructItem(Struct {
+                struct_type: self.struct_type,
+                generics: self.generics.clean(),
+                fields: self.fields.clean(),
+                fields_stripped: false,
+            }),
+        }
+    }
+}
+
+/// This is a more limited form of the standard Struct, different in that
+/// it lacks the things most items have (name, id, parameterization). Found
+/// only as a variant in an enum.
+#[deriving(Clone, Encodable, Decodable)]
+pub struct VariantStruct {
+    pub struct_type: doctree::StructType,
+    pub fields: Vec<Item>,
+    pub fields_stripped: bool,
+}
+
+impl Clean<VariantStruct> for syntax::ast::StructDef {
+    fn clean(&self) -> VariantStruct {
+        VariantStruct {
+            struct_type: doctree::struct_type_from_def(self),
+            fields: self.fields.clean().move_iter().collect(),
+            fields_stripped: false,
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct Enum {
+    pub variants: Vec<Item>,
+    pub generics: Generics,
+    pub variants_stripped: bool,
+}
+
+impl Clean<Item> for doctree::Enum {
+    fn clean(&self) -> Item {
+        Item {
+            name: Some(self.name.clean()),
+            attrs: self.attrs.clean(),
+            source: self.where.clean(),
+            def_id: ast_util::local_def(self.id),
+            visibility: self.vis.clean(),
+            inner: EnumItem(Enum {
+                variants: self.variants.clean(),
+                generics: self.generics.clean(),
+                variants_stripped: false,
+            }),
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct Variant {
+    pub kind: VariantKind,
+}
+
+impl Clean<Item> for doctree::Variant {
+    fn clean(&self) -> Item {
+        Item {
+            name: Some(self.name.clean()),
+            attrs: self.attrs.clean(),
+            source: self.where.clean(),
+            visibility: self.vis.clean(),
+            def_id: ast_util::local_def(self.id),
+            inner: VariantItem(Variant {
+                kind: self.kind.clean(),
+            }),
+        }
+    }
+}
+
+impl Clean<Item> for ty::VariantInfo {
+    fn clean(&self) -> Item {
+        // use syntax::parse::token::special_idents::unnamed_field;
+        let cx = super::ctxtkey.get().unwrap();
+        let tcx = match cx.maybe_typed {
+            core::Typed(ref tycx) => tycx,
+            core::NotTyped(_) => fail!("tcx not present"),
+        };
+        let kind = match self.arg_names.as_ref().map(|s| s.as_slice()) {
+            None | Some([]) if self.args.len() == 0 => CLikeVariant,
+            None | Some([]) => {
+                TupleVariant(self.args.iter().map(|t| t.clean()).collect())
+            }
+            Some(s) => {
+                StructVariant(VariantStruct {
+                    struct_type: doctree::Plain,
+                    fields_stripped: false,
+                    fields: s.iter().zip(self.args.iter()).map(|(name, ty)| {
+                        Item {
+                            source: Span::empty(),
+                            name: Some(name.clean()),
+                            attrs: Vec::new(),
+                            visibility: Some(ast::Public),
+                            // FIXME: this is not accurate, we need an id for
+                            //        the specific field but we're using the id
+                            //        for the whole variant. Nothing currently
+                            //        uses this so we should be good for now.
+                            def_id: self.id,
+                            inner: StructFieldItem(
+                                TypedStructField(ty.clean())
+                            )
+                        }
+                    }).collect()
+                })
+            }
+        };
+        Item {
+            name: Some(self.name.clean()),
+            attrs: inline::load_attrs(tcx, self.id),
+            source: Span::empty(),
+            visibility: Some(ast::Public),
+            def_id: self.id,
+            inner: VariantItem(Variant { kind: kind }),
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub enum VariantKind {
+    CLikeVariant,
+    TupleVariant(Vec<Type>),
+    StructVariant(VariantStruct),
+}
+
+impl Clean<VariantKind> for ast::VariantKind {
+    fn clean(&self) -> VariantKind {
+        match self {
+            &ast::TupleVariantKind(ref args) => {
+                if args.len() == 0 {
+                    CLikeVariant
+                } else {
+                    TupleVariant(args.iter().map(|x| x.ty.clean()).collect())
+                }
+            },
+            &ast::StructVariantKind(ref sd) => StructVariant(sd.clean()),
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct Span {
+    pub filename: String,
+    pub loline: uint,
+    pub locol: uint,
+    pub hiline: uint,
+    pub hicol: uint,
+}
+
+impl Span {
+    fn empty() -> Span {
+        Span {
+            filename: "".to_strbuf(),
+            loline: 0, locol: 0,
+            hiline: 0, hicol: 0,
+        }
+    }
+}
+
+impl Clean<Span> for syntax::codemap::Span {
+    fn clean(&self) -> Span {
+        let ctxt = super::ctxtkey.get().unwrap();
+        let cm = ctxt.sess().codemap();
+        let filename = cm.span_to_filename(*self);
+        let lo = cm.lookup_char_pos(self.lo);
+        let hi = cm.lookup_char_pos(self.hi);
+        Span {
+            filename: filename.to_strbuf(),
+            loline: lo.line,
+            locol: lo.col.to_uint(),
+            hiline: hi.line,
+            hicol: hi.col.to_uint(),
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct Path {
+    pub global: bool,
+    pub segments: Vec<PathSegment>,
+}
+
+impl Clean<Path> for ast::Path {
+    fn clean(&self) -> Path {
+        Path {
+            global: self.global,
+            segments: self.segments.clean().move_iter().collect(),
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct PathSegment {
+    pub name: String,
+    pub lifetimes: Vec<Lifetime>,
+    pub types: Vec<Type>,
+}
+
+impl Clean<PathSegment> for ast::PathSegment {
+    fn clean(&self) -> PathSegment {
+        PathSegment {
+            name: self.identifier.clean(),
+            lifetimes: self.lifetimes.clean().move_iter().collect(),
+            types: self.types.clean().move_iter().collect()
+        }
+    }
+}
+
+fn path_to_str(p: &ast::Path) -> String {
+    use syntax::parse::token;
+
+    let mut s = String::new();
+    let mut first = true;
+    for i in p.segments.iter().map(|x| token::get_ident(x.identifier)) {
+        if !first || p.global {
+            s.push_str("::");
+        } else {
+            first = false;
+        }
+        s.push_str(i.get());
+    }
+    s
+}
+
+impl Clean<String> for ast::Ident {
+    fn clean(&self) -> String {
+        token::get_ident(*self).get().to_strbuf()
+    }
+}
+
+impl Clean<String> for ast::Name {
+    fn clean(&self) -> String {
+        token::get_name(*self).get().to_strbuf()
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct Typedef {
+    pub type_: Type,
+    pub generics: Generics,
+}
+
+impl Clean<Item> for doctree::Typedef {
+    fn clean(&self) -> Item {
+        Item {
+            name: Some(self.name.clean()),
+            attrs: self.attrs.clean(),
+            source: self.where.clean(),
+            def_id: ast_util::local_def(self.id.clone()),
+            visibility: self.vis.clean(),
+            inner: TypedefItem(Typedef {
+                type_: self.ty.clean(),
+                generics: self.gen.clean(),
+            }),
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct BareFunctionDecl {
+    pub fn_style: ast::FnStyle,
+    pub generics: Generics,
+    pub decl: FnDecl,
+    pub abi: String,
+}
+
+impl Clean<BareFunctionDecl> for ast::BareFnTy {
+    fn clean(&self) -> BareFunctionDecl {
+        BareFunctionDecl {
+            fn_style: self.fn_style,
+            generics: Generics {
+                lifetimes: self.lifetimes.clean().move_iter().collect(),
+                type_params: Vec::new(),
+            },
+            decl: self.decl.clean(),
+            abi: self.abi.to_str().to_strbuf(),
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct Static {
+    pub type_: Type,
+    pub mutability: Mutability,
+    /// It's useful to have the value of a static documented, but I have no
+    /// desire to represent expressions (that'd basically be all of the AST,
+    /// which is huge!). So, have a string.
+    pub expr: String,
+}
+
+impl Clean<Item> for doctree::Static {
+    fn clean(&self) -> Item {
+        debug!("claning static {}: {:?}", self.name.clean(), self);
+        Item {
+            name: Some(self.name.clean()),
+            attrs: self.attrs.clean(),
+            source: self.where.clean(),
+            def_id: ast_util::local_def(self.id),
+            visibility: self.vis.clean(),
+            inner: StaticItem(Static {
+                type_: self.type_.clean(),
+                mutability: self.mutability.clean(),
+                expr: self.expr.span.to_src(),
+            }),
+        }
+    }
+}
+
+#[deriving(Show, Clone, Encodable, Decodable, Eq)]
+pub enum Mutability {
+    Mutable,
+    Immutable,
+}
+
+impl Clean<Mutability> for ast::Mutability {
+    fn clean(&self) -> Mutability {
+        match self {
+            &ast::MutMutable => Mutable,
+            &ast::MutImmutable => Immutable,
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct Impl {
+    pub generics: Generics,
+    pub trait_: Option<Type>,
+    pub for_: Type,
+    pub methods: Vec<Item>,
+    pub derived: bool,
+}
+
+fn detect_derived<M: AttrMetaMethods>(attrs: &[M]) -> bool {
+    attr::contains_name(attrs, "automatically_derived")
+}
+
+impl Clean<Item> for doctree::Impl {
+    fn clean(&self) -> Item {
+        Item {
+            name: None,
+            attrs: self.attrs.clean(),
+            source: self.where.clean(),
+            def_id: ast_util::local_def(self.id),
+            visibility: self.vis.clean(),
+            inner: ImplItem(Impl {
+                generics: self.generics.clean(),
+                trait_: self.trait_.clean(),
+                for_: self.for_.clean(),
+                methods: self.methods.clean(),
+                derived: detect_derived(self.attrs.as_slice()),
+            }),
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct ViewItem {
+    pub inner: ViewItemInner,
+}
+
+impl Clean<Vec<Item>> for ast::ViewItem {
+    fn clean(&self) -> Vec<Item> {
+        // We consider inlining the documentation of `pub use` statments, but we
+        // forcefully don't inline if this is not public or if the
+        // #[doc(no_inline)] attribute is present.
+        let denied = self.vis != ast::Public || self.attrs.iter().any(|a| {
+            a.name().get() == "doc" && match a.meta_item_list() {
+                Some(l) => attr::contains_name(l, "no_inline"),
+                None => false,
+            }
+        });
+        let convert = |node: &ast::ViewItem_| {
+            Item {
+                name: None,
+                attrs: self.attrs.clean().move_iter().collect(),
+                source: self.span.clean(),
+                def_id: ast_util::local_def(0),
+                visibility: self.vis.clean(),
+                inner: ViewItemItem(ViewItem { inner: node.clean() }),
+            }
+        };
+        let mut ret = Vec::new();
+        match self.node {
+            ast::ViewItemUse(ref path) if !denied => {
+                match path.node {
+                    ast::ViewPathGlob(..) => ret.push(convert(&self.node)),
+                    ast::ViewPathList(ref a, ref list, ref b) => {
+                        // Attempt to inline all reexported items, but be sure
+                        // to keep any non-inlineable reexports so they can be
+                        // listed in the documentation.
+                        let remaining = list.iter().filter(|path| {
+                            match inline::try_inline(path.node.id) {
+                                Some(items) => {
+                                    ret.extend(items.move_iter()); false
+                                }
+                                None => true,
+                            }
+                        }).map(|a| a.clone()).collect::<Vec<ast::PathListIdent>>();
+                        if remaining.len() > 0 {
+                            let path = ast::ViewPathList(a.clone(),
+                                                         remaining,
+                                                         b.clone());
+                            let path = syntax::codemap::dummy_spanned(path);
+                            ret.push(convert(&ast::ViewItemUse(@path)));
+                        }
+                    }
+                    ast::ViewPathSimple(_, _, id) => {
+                        match inline::try_inline(id) {
+                            Some(items) => ret.extend(items.move_iter()),
+                            None => ret.push(convert(&self.node)),
+                        }
+                    }
+                }
+            }
+            ref n => ret.push(convert(n)),
+        }
+        return ret;
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub enum ViewItemInner {
+    ExternCrate(String, Option<String>, ast::NodeId),
+    Import(ViewPath)
+}
+
+impl Clean<ViewItemInner> for ast::ViewItem_ {
+    fn clean(&self) -> ViewItemInner {
+        match self {
+            &ast::ViewItemExternCrate(ref i, ref p, ref id) => {
+                let string = match *p {
+                    None => None,
+                    Some((ref x, _)) => Some(x.get().to_strbuf()),
+                };
+                ExternCrate(i.clean(), string, *id)
+            }
+            &ast::ViewItemUse(ref vp) => {
+                Import(vp.clean())
+            }
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub enum ViewPath {
+    // use str = source;
+    SimpleImport(String, ImportSource),
+    // use source::*;
+    GlobImport(ImportSource),
+    // use source::{a, b, c};
+    ImportList(ImportSource, Vec<ViewListIdent>),
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct ImportSource {
+    pub path: Path,
+    pub did: Option<ast::DefId>,
+}
+
+impl Clean<ViewPath> for ast::ViewPath {
+    fn clean(&self) -> ViewPath {
+        match self.node {
+            ast::ViewPathSimple(ref i, ref p, id) =>
+                SimpleImport(i.clean(), resolve_use_source(p.clean(), id)),
+            ast::ViewPathGlob(ref p, id) =>
+                GlobImport(resolve_use_source(p.clean(), id)),
+            ast::ViewPathList(ref p, ref pl, id) => {
+                ImportList(resolve_use_source(p.clean(), id),
+                           pl.clean().move_iter().collect())
+            }
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct ViewListIdent {
+    pub name: String,
+    pub source: Option<ast::DefId>,
+}
+
+impl Clean<ViewListIdent> for ast::PathListIdent {
+    fn clean(&self) -> ViewListIdent {
+        ViewListIdent {
+            name: self.node.name.clean(),
+            source: resolve_def(self.node.id),
+        }
+    }
+}
+
+impl Clean<Vec<Item>> for ast::ForeignMod {
+    fn clean(&self) -> Vec<Item> {
+        self.items.clean()
+    }
+}
+
+impl Clean<Item> for ast::ForeignItem {
+    fn clean(&self) -> Item {
+        let inner = match self.node {
+            ast::ForeignItemFn(ref decl, ref generics) => {
+                ForeignFunctionItem(Function {
+                    decl: decl.clean(),
+                    generics: generics.clean(),
+                    fn_style: ast::UnsafeFn,
+                })
+            }
+            ast::ForeignItemStatic(ref ty, mutbl) => {
+                ForeignStaticItem(Static {
+                    type_: ty.clean(),
+                    mutability: if mutbl {Mutable} else {Immutable},
+                    expr: "".to_strbuf(),
+                })
+            }
+        };
+        Item {
+            name: Some(self.ident.clean()),
+            attrs: self.attrs.clean().move_iter().collect(),
+            source: self.span.clean(),
+            def_id: ast_util::local_def(self.id),
+            visibility: self.vis.clean(),
+            inner: inner,
+        }
+    }
+}
+
+// Utilities
+
+trait ToSource {
+    fn to_src(&self) -> String;
+}
+
+impl ToSource for syntax::codemap::Span {
+    fn to_src(&self) -> String {
+        debug!("converting span {:?} to snippet", self.clean());
+        let ctxt = super::ctxtkey.get().unwrap();
+        let cm = ctxt.sess().codemap().clone();
+        let sn = match cm.span_to_snippet(*self) {
+            Some(x) => x.to_strbuf(),
+            None    => "".to_strbuf()
+        };
+        debug!("got snippet {}", sn);
+        sn
+    }
+}
+
+fn lit_to_str(lit: &ast::Lit) -> String {
+    match lit.node {
+        ast::LitStr(ref st, _) => st.get().to_strbuf(),
+        ast::LitBinary(ref data) => format_strbuf!("{:?}", data.as_slice()),
+        ast::LitChar(c) => format_strbuf!("'{}'", c),
+        ast::LitInt(i, _t) => i.to_str().to_strbuf(),
+        ast::LitUint(u, _t) => u.to_str().to_strbuf(),
+        ast::LitIntUnsuffixed(i) => i.to_str().to_strbuf(),
+        ast::LitFloat(ref f, _t) => f.get().to_strbuf(),
+        ast::LitFloatUnsuffixed(ref f) => f.get().to_strbuf(),
+        ast::LitBool(b) => b.to_str().to_strbuf(),
+        ast::LitNil => "".to_strbuf(),
+    }
+}
+
+fn name_from_pat(p: &ast::Pat) -> String {
+    use syntax::ast::*;
+    debug!("Trying to get a name from pattern: {:?}", p);
+
+    match p.node {
+        PatWild => "_".to_strbuf(),
+        PatWildMulti => "..".to_strbuf(),
+        PatIdent(_, ref p, _) => path_to_str(p),
+        PatEnum(ref p, _) => path_to_str(p),
+        PatStruct(..) => fail!("tried to get argument name from pat_struct, \
+                                which is not allowed in function arguments"),
+        PatTup(..) => "(tuple arg NYI)".to_strbuf(),
+        PatUniq(p) => name_from_pat(p),
+        PatRegion(p) => name_from_pat(p),
+        PatLit(..) => {
+            warn!("tried to get argument name from PatLit, \
+                  which is silly in function arguments");
+            "()".to_strbuf()
+        },
+        PatRange(..) => fail!("tried to get argument name from PatRange, \
+                              which is not allowed in function arguments"),
+        PatVec(..) => fail!("tried to get argument name from pat_vec, \
+                             which is not allowed in function arguments")
+    }
+}
+
+/// Given a Type, resolve it using the def_map
+fn resolve_type(path: Path, tpbs: Option<Vec<TyParamBound>>,
+                id: ast::NodeId) -> Type {
+    let cx = super::ctxtkey.get().unwrap();
+    let tycx = match cx.maybe_typed {
+        core::Typed(ref tycx) => tycx,
+        // If we're extracting tests, this return value doesn't matter.
+        core::NotTyped(_) => return Bool
+    };
+    debug!("searching for {:?} in defmap", id);
+    let def = match tycx.def_map.borrow().find(&id) {
+        Some(&k) => k,
+        None => fail!("unresolved id not in defmap")
+    };
+
+    match def {
+        ast::DefSelfTy(i) => return Self(ast_util::local_def(i)),
+        ast::DefPrimTy(p) => match p {
+            ast::TyStr => return String,
+            ast::TyBool => return Bool,
+            _ => return Primitive(p)
+        },
+        ast::DefTyParam(i, _) => return Generic(i),
+        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::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(did) { return did }
+    let tcx = match cx.maybe_typed {
+        core::Typed(ref t) => t,
+        core::NotTyped(_) => return did
+    };
+    inline::record_extern_fqn(cx, did, kind);
+    match kind {
+        TypeTrait => {
+            let t = inline::build_external_trait(tcx, did);
+            cx.external_traits.borrow_mut().get_mut_ref().insert(did, t);
+        }
+        _ => {}
+    }
+    return did;
+}
+
+fn resolve_use_source(path: Path, id: ast::NodeId) -> ImportSource {
+    ImportSource {
+        path: path,
+        did: resolve_def(id),
+    }
+}
+
+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(|&def| register_def(&**cx, def))
+        }
+        core::NotTyped(_) => None
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct Macro {
+    pub source: String,
+}
+
+impl Clean<Item> for doctree::Macro {
+    fn clean(&self) -> Item {
+        Item {
+            name: Some(format_strbuf!("{}!", self.name.clean())),
+            attrs: self.attrs.clean(),
+            source: self.where.clean(),
+            visibility: ast::Public.clean(),
+            def_id: ast_util::local_def(self.id),
+            inner: MacroItem(Macro {
+                source: self.where.to_src(),
+            }),
+        }
+    }
+}
index ce7f230ea53f0022484ed9797d03811e8ec163a7..d601d2ae957feb5563a7d1cdd828fce5d0f629cc 100644 (file)
@@ -143,7 +143,7 @@ pub struct Cache {
 
     /// Similar to `paths`, but only holds external paths. This is only used for
     /// generating explicit hyperlinks to other crates.
-    pub external_paths: HashMap<ast::DefId, Vec<StrBuf>>,
+    pub external_paths: HashMap<ast::DefId, Vec<String>>,
 
     /// This map contains information about all known traits of this crate.
     /// Implementations of a crate should inherit the documentation of the
@@ -253,7 +253,7 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
     let analysis = ::analysiskey.get();
     let public_items = analysis.as_ref().map(|a| a.public_items.clone());
     let public_items = public_items.unwrap_or(NodeSet::new());
-    let paths: HashMap<ast::DefId, (Vec<StrBuf>, ItemType)> =
+    let paths: HashMap<ast::DefId, (Vec<String>, ItemType)> =
       analysis.as_ref().map(|a| {
         let paths = a.external_paths.borrow_mut().take_unwrap();
         paths.move_iter().map(|(k, (v, t))| {
@@ -1041,7 +1041,19 @@ fn ismodule(&self) -> bool {
         }
     }
 
-    fn link(&self) -> Option<String> {
+    /// Generate a url appropriate for an `href` attribute back to the source of
+    /// this item.
+    ///
+    /// The url generated, when clicked, will redirect the browser back to the
+    /// original source code.
+    ///
+    /// 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> {
+        // 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.
         if ast_util::is_local(self.item.def_id) {
             let mut path = Vec::new();
             clean_srcpath(self.item.source.filename.as_bytes(), |component| {
@@ -1059,6 +1071,18 @@ fn link(&self) -> Option<String> {
                          krate = self.cx.layout.krate,
                          path = path.connect("/"),
                          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_key.get().unwrap();
             let path = cache.external_paths.get(&self.item.def_id);
@@ -1120,8 +1144,13 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         }
 
         // Write `src` tag
+        //
+        // When this item is part of a `pub use` in a downstream crate, the
+        // [src] link in the downstream documentation will actually come back to
+        // this page, and this link will be auto-clicked. The `id` attribute is
+        // used to find the link to auto-click.
         if self.cx.include_sources {
-            match self.link() {
+            match self.href() {
                 Some(l) => {
                     try!(write!(fmt,
                                 "<a class='source' id='src-{}' \
@@ -1288,7 +1317,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                         try!(write!(f, "<code> = </code>"));
                         if s.contains("\n") {
                             write!(f, "<a href='{}'>[definition]</a>",
-                                   item.link())
+                                   item.href())
                         } else {
                             write!(f, "<code>{}</code>", s.as_slice())
                         }
index ec58162fa92657f3c6a3455dc5b14b28134674df..2fb824653d3dbd4df42bbe7bf82d4939479f6278 100644 (file)
         window.register_implementors(window.pending_implementors);
     }
 
-
-    var query = window.location.search.substring(1);
-    var vars = query.split('&');
-    for (var i = 0; i < vars.length; i++) {
-        var pair = vars[i].split('=');
-        if (pair[0] == 'gotosrc') {
-            window.location = $('#src-' + pair[1]).attr('href');
-        }
+    // See documentaiton in html/render.rs for what this is doing.
+    var query = getQueryStringParams();
+    if (query['gotosrc']) {
+        window.location = $('#src-' + query['gotosrc']).attr('href');
     }
 }());
index 0d42e1743f561f0a098ae3b4da3a93c621ac5d55..1786cc8062e214181d21224cf662403aba23e95c 100644 (file)
 //!
 //! ## Intrinsic types and operations
 //!
-//! The [`ptr`](../core/ptr/index.html) and [`mem`](../core/mem/index.html)
+//! The [`ptr`](ptr/index.html) and [`mem`](mem/index.html)
 //! modules deal with unsafe pointers and memory manipulation.
-//! [`kinds`](../core/kinds/index.html) defines the special built-in traits,
-//! and [`raw`](../core/raw/index.html) the runtime representation of Rust types.
+//! [`kinds`](kinds/index.html) defines the special built-in traits,
+//! and [`raw`](raw/index.html) the runtime representation of Rust types.
 //! These are some of the lowest-level building blocks in Rust.
 //!
 //! ## Math on primitive types and math traits
 //!
 //! ## Pervasive types
 //!
-//! The [`option`](option/index.html) and [`result`](../core/result/index.html)
+//! The [`option`](option/index.html) and [`result`](result/index.html)
 //! modules define optional and error-handling types, `Option` and `Result`.
-//! [`iter`](../core/iter/index.html) defines Rust's iterator protocol
+//! [`iter`](iter/index.html) defines Rust's iterator protocol
 //! along with a wide variety of iterators.
-//! [`Cell` and `RefCell`](../core/cell/index.html) are for creating types that
+//! [`Cell` and `RefCell`](cell/index.html) are for creating types that
 //! manage their own mutability.
 //!
 //! ## Vectors, slices and strings
index ef05f3b167a68144767cc6ba6ee6c6c517b09570..07aaeac64be1c811caa19284bc1e3add7e91d839 100644 (file)
 //! `drop`, `spawn`, and `channel`.
 
 // Reexported core operators
-#[doc(noinline)] pub use kinds::{Copy, Send, Sized, Share};
-#[doc(noinline)] pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
-#[doc(noinline)] pub use ops::{BitAnd, BitOr, BitXor};
-#[doc(noinline)] pub use ops::{Drop, Deref, DerefMut};
-#[doc(noinline)] pub use ops::{Shl, Shr, Index};
-#[doc(noinline)] pub use option::{Option, Some, None};
-#[doc(noinline)] pub use result::{Result, Ok, Err};
+#[doc(no_inline)] pub use kinds::{Copy, Send, Sized, Share};
+#[doc(no_inline)] pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
+#[doc(no_inline)] pub use ops::{BitAnd, BitOr, BitXor};
+#[doc(no_inline)] pub use ops::{Drop, Deref, DerefMut};
+#[doc(no_inline)] pub use ops::{Shl, Shr, Index};
+#[doc(no_inline)] pub use option::{Option, Some, None};
+#[doc(no_inline)] pub use result::{Result, Ok, Err};
 
 // Reexported functions
-#[doc(noinline)] pub use from_str::from_str;
-#[doc(noinline)] pub use iter::range;
-#[doc(noinline)] pub use mem::drop;
+#[doc(no_inline)] pub use from_str::from_str;
+#[doc(no_inline)] pub use iter::range;
+#[doc(no_inline)] pub use mem::drop;
 
 // Reexported types and traits
 
-#[doc(noinline)] pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr};
-#[doc(noinline)] pub use ascii::IntoBytes;
-#[doc(noinline)] pub use c_str::ToCStr;
-#[doc(noinline)] pub use char::Char;
-#[doc(noinline)] pub use clone::Clone;
-#[doc(noinline)] pub use cmp::{Eq, Ord, TotalEq, TotalOrd};
-#[doc(noinline)] pub use cmp::{Ordering, Less, Equal, Greater, Equiv};
-#[doc(noinline)] pub use container::{Container, Mutable, Map, MutableMap};
-#[doc(noinline)] pub use container::{Set, MutableSet};
-#[doc(noinline)] pub use iter::{FromIterator, Extendable, ExactSize};
-#[doc(noinline)] pub use iter::{Iterator, DoubleEndedIterator};
-#[doc(noinline)] pub use iter::{RandomAccessIterator, CloneableIterator};
-#[doc(noinline)] pub use iter::{OrdIterator, MutableDoubleEndedIterator};
-#[doc(noinline)] pub use num::{Num, NumCast, CheckedAdd, CheckedSub, CheckedMul};
-#[doc(noinline)] pub use num::{Signed, Unsigned, Primitive, Int, Float};
-#[doc(noinline)] pub use num::{FloatMath, ToPrimitive, FromPrimitive};
-#[doc(noinline)] pub use option::Expect;
-#[doc(noinline)] pub use owned::Box;
-#[doc(noinline)] pub use path::{GenericPath, Path, PosixPath, WindowsPath};
-#[doc(noinline)] pub use ptr::RawPtr;
-#[doc(noinline)] pub use io::{Buffer, Writer, Reader, Seek};
-#[doc(noinline)] pub use str::{Str, StrVector, StrSlice, OwnedStr};
-#[doc(noinline)] pub use str::{IntoMaybeOwned, StrAllocating};
-#[doc(noinline)] pub use to_str::{ToStr, IntoStr};
-#[doc(noinline)] pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4};
-#[doc(noinline)] pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8};
-#[doc(noinline)] pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12};
-#[doc(noinline)] pub use slice::{CloneableVector, ImmutableCloneableVector};
-#[doc(noinline)] pub use slice::{MutableCloneableVector, MutableTotalOrdVector};
-#[doc(noinline)] pub use slice::{ImmutableVector, MutableVector};
-#[doc(noinline)] pub use slice::{ImmutableEqVector, ImmutableTotalOrdVector};
-#[doc(noinline)] pub use slice::{Vector, VectorVector, OwnedVector};
-#[doc(noinline)] pub use slice::MutableVectorAllocating;
-#[doc(noinline)] pub use string::String;
-#[doc(noinline)] pub use vec::Vec;
+#[doc(no_inline)] pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr};
+#[doc(no_inline)] pub use ascii::IntoBytes;
+#[doc(no_inline)] pub use c_str::ToCStr;
+#[doc(no_inline)] pub use char::Char;
+#[doc(no_inline)] pub use clone::Clone;
+#[doc(no_inline)] pub use cmp::{Eq, Ord, TotalEq, TotalOrd};
+#[doc(no_inline)] pub use cmp::{Ordering, Less, Equal, Greater, Equiv};
+#[doc(no_inline)] pub use container::{Container, Mutable, Map, MutableMap};
+#[doc(no_inline)] pub use container::{Set, MutableSet};
+#[doc(no_inline)] pub use iter::{FromIterator, Extendable, ExactSize};
+#[doc(no_inline)] pub use iter::{Iterator, DoubleEndedIterator};
+#[doc(no_inline)] pub use iter::{RandomAccessIterator, CloneableIterator};
+#[doc(no_inline)] pub use iter::{OrdIterator, MutableDoubleEndedIterator};
+#[doc(no_inline)] pub use num::{Num, NumCast, CheckedAdd, CheckedSub, CheckedMul};
+#[doc(no_inline)] pub use num::{Signed, Unsigned, Primitive, Int, Float};
+#[doc(no_inline)] pub use num::{FloatMath, ToPrimitive, FromPrimitive};
+#[doc(no_inline)] pub use option::Expect;
+#[doc(no_inline)] pub use owned::Box;
+#[doc(no_inline)] pub use path::{GenericPath, Path, PosixPath, WindowsPath};
+#[doc(no_inline)] pub use ptr::RawPtr;
+#[doc(no_inline)] pub use io::{Buffer, Writer, Reader, Seek};
+#[doc(no_inline)] pub use str::{Str, StrVector, StrSlice, OwnedStr};
+#[doc(no_inline)] pub use str::{IntoMaybeOwned, StrAllocating};
+#[doc(no_inline)] pub use to_str::{ToStr, IntoStr};
+#[doc(no_inline)] pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4};
+#[doc(no_inline)] pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8};
+#[doc(no_inline)] pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12};
+#[doc(no_inline)] pub use slice::{CloneableVector, ImmutableCloneableVector};
+#[doc(no_inline)] pub use slice::{MutableCloneableVector, MutableTotalOrdVector};
+#[doc(no_inline)] pub use slice::{ImmutableVector, MutableVector};
+#[doc(no_inline)] pub use slice::{ImmutableEqVector, ImmutableTotalOrdVector};
+#[doc(no_inline)] pub use slice::{Vector, VectorVector, OwnedVector};
+#[doc(no_inline)] pub use slice::MutableVectorAllocating;
+#[doc(no_inline)] pub use string::String;
+#[doc(no_inline)] pub use vec::Vec;
 
 // Reexported runtime types
-#[doc(noinline)] pub use comm::{sync_channel, channel};
-#[doc(noinline)] pub use comm::{SyncSender, Sender, Receiver};
-#[doc(noinline)] pub use task::spawn;
+#[doc(no_inline)] pub use comm::{sync_channel, channel};
+#[doc(no_inline)] pub use comm::{SyncSender, Sender, Receiver};
+#[doc(no_inline)] pub use task::spawn;
 
 // Reexported statics
 #[cfg(not(test))]
-#[doc(noinline)] pub use gc::GC;
+#[doc(no_inline)] pub use gc::GC;