mod.rs 63.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
// 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.

C
Corey Richardson 已提交
11 12 13 14 15
//! This module contains the "cleaned" pieces of the AST, and the functions
//! that clean them.

use syntax;
use syntax::ast;
16
use syntax::ast_util;
17
use syntax::attr;
18
use syntax::attr::{AttributeMethods, AttrMetaMethods};
19
use syntax::codemap::Pos;
20 21
use syntax::parse::token::InternedString;
use syntax::parse::token;
C
Corey Richardson 已提交
22

23 24
use rustc::back::link;
use rustc::driver::driver;
25 26 27
use rustc::metadata::cstore;
use rustc::metadata::csearch;
use rustc::metadata::decoder;
28
use rustc::middle::def;
29
use rustc::middle::subst;
30
use rustc::middle::ty;
31

32
use std::rc::Rc;
33
use std::u32;
34

E
Eduard Burtescu 已提交
35
use core;
C
Corey Richardson 已提交
36 37 38
use doctree;
use visit_ast;

39 40 41 42
/// 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";

43 44
mod inline;

C
Corey Richardson 已提交
45 46 47 48
pub trait Clean<T> {
    fn clean(&self) -> T;
}

49 50 51 52 53 54
impl<T: Clean<U>, U> Clean<Vec<U>> for Vec<T> {
    fn clean(&self) -> Vec<U> {
        self.iter().map(|x| x.clean()).collect()
    }
}

C
Corey Richardson 已提交
55 56 57 58 59 60
impl<T: Clean<U>, U> Clean<U> for @T {
    fn clean(&self) -> U {
        (**self).clean()
    }
}

61 62 63 64 65 66
impl<T: Clean<U>, U> Clean<U> for Rc<T> {
    fn clean(&self) -> U {
        (**self).clean()
    }
}

C
Corey Richardson 已提交
67 68 69 70 71 72 73 74 75
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())
        }
    }
}

76
impl<T: Clean<U>, U> Clean<Vec<U>> for syntax::owned_slice::OwnedSlice<T> {
77
    fn clean(&self) -> Vec<U> {
78
        self.iter().map(|x| x.clean()).collect()
C
Corey Richardson 已提交
79 80 81 82 83
    }
}

#[deriving(Clone, Encodable, Decodable)]
pub struct Crate {
84
    pub name: String,
85 86
    pub module: Option<Item>,
    pub externs: Vec<(ast::CrateNum, ExternalCrate)>,
87
    pub primitives: Vec<Primitive>,
C
Corey Richardson 已提交
88 89
}

A
Alex Crichton 已提交
90
impl<'a> Clean<Crate> for visit_ast::RustdocVisitor<'a> {
C
Corey Richardson 已提交
91
    fn clean(&self) -> Crate {
92
        let cx = super::ctxtkey.get().unwrap();
93

94
        let mut externs = Vec::new();
E
Eduard Burtescu 已提交
95
        cx.sess().cstore.iter_crate_data(|n, meta| {
96
            externs.push((n, meta.clean()));
97
        });
98
        externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
C
Corey Richardson 已提交
99

100
        // Figure out the name of this crate
101 102 103 104 105 106 107
        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(),
108
                                     t_outputs.out_filestem.as_slice());
109

110
        // Clean the crate, translating the entire libsyntax AST to one that is
111 112 113 114 115
        // understood by rustdoc.
        let mut module = self.module.clean();

        // Collect all inner modules which are tagged as implementations of
        // primitives.
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
        //
        // Note that this loop only searches the top-level items of the crate,
        // and this is intentional. If we were to search the entire crate for an
        // item tagged with `#[doc(primitive)]` then we we would also have to
        // search the entirety of external modules for items tagged
        // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
        // all that metadata unconditionally).
        //
        // In order to keep the metadata load under control, the
        // `#[doc(primitive)]` feature is explicitly designed to only allow the
        // primitive tags to show up as the top level items in a crate.
        //
        // Also note that this does not attempt to deal with modules tagged
        // duplicately for the same primitive. This is handled later on when
        // rendering by delegating everything to a hash map.
131 132 133 134 135 136 137
        let mut primitives = Vec::new();
        {
            let m = match module.inner {
                ModuleItem(ref mut m) => m,
                _ => unreachable!(),
            };
            let mut tmp = Vec::new();
138 139 140
            for child in m.items.mut_iter() {
                let inner = match child.inner {
                    ModuleItem(ref mut m) => m,
141
                    _ => continue,
142
                };
143 144 145 146 147
                let prim = match Primitive::find(child.attrs.as_slice()) {
                    Some(prim) => prim,
                    None => continue,
                };
                primitives.push(prim);
148
                let mut i = Item {
149 150
                    source: Span::empty(),
                    name: Some(prim.to_url_str().to_string()),
151 152
                    attrs: Vec::new(),
                    visibility: None,
153 154
                    def_id: ast_util::local_def(prim.to_node_id()),
                    inner: PrimitiveItem(prim),
155 156 157 158 159 160 161 162 163 164
                };
                // Push one copy to get indexed for the whole crate, and push a
                // another copy in the proper location which will actually get
                // documented. The first copy will also serve as a redirect to
                // the other copy.
                tmp.push(i.clone());
                i.visibility = Some(ast::Public);
                i.attrs = child.attrs.clone();
                inner.items.push(i);

165 166 167 168
            }
            m.items.extend(tmp.move_iter());
        }

C
Corey Richardson 已提交
169
        Crate {
170
            name: id.name.to_string(),
171
            module: Some(module),
172
            externs: externs,
173
            primitives: primitives,
174 175 176 177 178 179
        }
    }
}

#[deriving(Clone, Encodable, Decodable)]
pub struct ExternalCrate {
180
    pub name: String,
181
    pub attrs: Vec<Attribute>,
182
    pub primitives: Vec<Primitive>,
183 184 185 186
}

impl Clean<ExternalCrate> for cstore::crate_metadata {
    fn clean(&self) -> ExternalCrate {
187 188 189 190 191 192 193 194
        let mut primitives = Vec::new();
        let cx = super::ctxtkey.get().unwrap();
        match cx.maybe_typed {
            core::Typed(ref tcx) => {
                csearch::each_top_level_item_of_crate(&tcx.sess.cstore,
                                                      self.cnum,
                                                      |def, _, _| {
                    let did = match def {
195
                        decoder::DlDef(def::DefMod(did)) => did,
196 197 198 199 200 201 202 203 204 205 206
                        _ => return
                    };
                    let attrs = inline::load_attrs(tcx, did);
                    match Primitive::find(attrs.as_slice()) {
                        Some(prim) => primitives.push(prim),
                        None => {}
                    }
                });
            }
            core::NotTyped(..) => {}
        }
207
        ExternalCrate {
208
            name: self.name.to_string(),
209 210
            attrs: decoder::get_crate_attributes(self.data()).clean(),
            primitives: primitives,
C
Corey Richardson 已提交
211 212 213 214 215 216 217 218 219 220
        }
    }
}

/// 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
221
    pub source: Span,
C
Corey Richardson 已提交
222
    /// Not everything has a name. E.g., impls
223
    pub name: Option<String>,
224 225 226
    pub attrs: Vec<Attribute> ,
    pub inner: ItemEnum,
    pub visibility: Option<Visibility>,
227
    pub def_id: ast::DefId,
C
Corey Richardson 已提交
228 229
}

230 231 232 233 234 235
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 {
236 237 238
                List(ref x, ref list) if "doc" == x.as_slice() => {
                    return Some(list.as_slice());
                }
239 240 241 242 243 244 245 246 247 248 249
                _ => {}
            }
        }
        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 {
250 251 252
                NameValue(ref x, ref v) if "doc" == x.as_slice() => {
                    return Some(v.as_slice());
                }
253 254 255 256 257 258
                _ => {}
            }
        }
        return None;
    }

259 260 261 262 263
    pub fn is_hidden_from_doc(&self) -> bool {
        match self.doc_list() {
            Some(ref l) => {
                for innerattr in l.iter() {
                    match *innerattr {
264 265 266
                        Word(ref s) if "hidden" == s.as_slice() => {
                            return true
                        }
267 268 269 270 271 272 273 274 275
                        _ => (),
                    }
                }
            },
            None => ()
        }
        return false;
    }

276
    pub fn is_mod(&self) -> bool {
A
Alex Crichton 已提交
277
        match self.inner { ModuleItem(..) => true, _ => false }
278 279
    }
    pub fn is_trait(&self) -> bool {
A
Alex Crichton 已提交
280
        match self.inner { TraitItem(..) => true, _ => false }
281 282
    }
    pub fn is_struct(&self) -> bool {
A
Alex Crichton 已提交
283
        match self.inner { StructItem(..) => true, _ => false }
284 285
    }
    pub fn is_enum(&self) -> bool {
A
Alex Crichton 已提交
286
        match self.inner { EnumItem(..) => true, _ => false }
287 288
    }
    pub fn is_fn(&self) -> bool {
A
Alex Crichton 已提交
289
        match self.inner { FunctionItem(..) => true, _ => false }
290 291 292
    }
}

C
Corey Richardson 已提交
293 294 295 296 297 298 299 300 301 302
#[deriving(Clone, Encodable, Decodable)]
pub enum ItemEnum {
    StructItem(Struct),
    EnumItem(Enum),
    FunctionItem(Function),
    ModuleItem(Module),
    TypedefItem(Typedef),
    StaticItem(Static),
    TraitItem(Trait),
    ImplItem(Impl),
303
    /// `use` and `extern crate`
C
Corey Richardson 已提交
304
    ViewItemItem(ViewItem),
305 306
    /// A method signature only. Used for required methods in traits (ie,
    /// non-default-methods).
C
Corey Richardson 已提交
307
    TyMethodItem(TyMethod),
308
    /// A method with a body.
C
Corey Richardson 已提交
309 310 311
    MethodItem(Method),
    StructFieldItem(StructField),
    VariantItem(Variant),
312
    /// `fn`s from an extern block
313
    ForeignFunctionItem(Function),
314
    /// `static`s from an extern block
315
    ForeignStaticItem(Static),
316
    MacroItem(Macro),
317
    PrimitiveItem(Primitive),
C
Corey Richardson 已提交
318 319 320 321
}

#[deriving(Clone, Encodable, Decodable)]
pub struct Module {
322 323
    pub items: Vec<Item>,
    pub is_crate: bool,
C
Corey Richardson 已提交
324 325 326 327 328 329 330
}

impl Clean<Item> for doctree::Module {
    fn clean(&self) -> Item {
        let name = if self.name.is_some() {
            self.name.unwrap().clean()
        } else {
331
            "".to_string()
C
Corey Richardson 已提交
332
        };
333
        let mut foreigns = Vec::new();
334 335 336 337 338
        for subforeigns in self.foreigns.clean().move_iter() {
            for foreign in subforeigns.move_iter() {
                foreigns.push(foreign)
            }
        }
339
        let items: Vec<Vec<Item> > = vec!(
340 341 342 343 344 345 346 347 348
            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(),
349 350
            self.view_items.clean().move_iter()
                           .flat_map(|s| s.move_iter()).collect(),
351
            self.macros.clean().move_iter().collect()
352
        );
353 354 355 356

        // determine if we should display the inner contents or
        // the outer `mod` item for the source code.
        let where = {
357
            let ctxt = super::ctxtkey.get().unwrap();
358 359 360 361 362 363 364 365 366 367 368 369
            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
            }
        };

C
Corey Richardson 已提交
370 371 372
        Item {
            name: Some(name),
            attrs: self.attrs.clean(),
373
            source: where.clean(),
C
Corey Richardson 已提交
374
            visibility: self.vis.clean(),
375
            def_id: ast_util::local_def(self.id),
C
Corey Richardson 已提交
376
            inner: ModuleItem(Module {
377
               is_crate: self.is_crate,
378 379 380
               items: items.iter()
                           .flat_map(|x| x.iter().map(|x| (*x).clone()))
                           .collect(),
C
Corey Richardson 已提交
381 382 383 384 385 386 387
            })
        }
    }
}

#[deriving(Clone, Encodable, Decodable)]
pub enum Attribute {
388 389 390
    Word(String),
    List(String, Vec<Attribute> ),
    NameValue(String, String)
C
Corey Richardson 已提交
391 392 393 394 395
}

impl Clean<Attribute> for ast::MetaItem {
    fn clean(&self) -> Attribute {
        match self.node {
396
            ast::MetaWord(ref s) => Word(s.get().to_string()),
397
            ast::MetaList(ref s, ref l) => {
398
                List(s.get().to_string(), l.clean().move_iter().collect())
399 400
            }
            ast::MetaNameValue(ref s, ref v) => {
401
                NameValue(s.get().to_string(), lit_to_str(v))
402
            }
C
Corey Richardson 已提交
403 404 405 406 407 408
        }
    }
}

impl Clean<Attribute> for ast::Attribute {
    fn clean(&self) -> Attribute {
409
        self.desugar_doc().node.value.clean()
C
Corey Richardson 已提交
410 411 412
    }
}

413
// This is a rough approximation that gets us what we want.
414
impl attr::AttrMetaMethods for Attribute {
415
    fn name(&self) -> InternedString {
416
        match *self {
417
            Word(ref n) | List(ref n, _) | NameValue(ref n, _) => {
418
                token::intern_and_get_ident(n.as_slice())
419
            }
420 421 422
        }
    }

423
    fn value_str(&self) -> Option<InternedString> {
424
        match *self {
425 426 427
            NameValue(_, ref v) => {
                Some(token::intern_and_get_ident(v.as_slice()))
            }
428 429 430 431 432
            _ => None,
        }
    }
    fn meta_item_list<'a>(&'a self) -> Option<&'a [@ast::MetaItem]> { None }
}
433 434 435 436 437
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 }
}
438

C
Corey Richardson 已提交
439 440
#[deriving(Clone, Encodable, Decodable)]
pub struct TyParam {
441
    pub name: String,
442
    pub did: ast::DefId,
443 444
    pub bounds: Vec<TyParamBound>,
}
C
Corey Richardson 已提交
445 446 447 448 449

impl Clean<TyParam> for ast::TyParam {
    fn clean(&self) -> TyParam {
        TyParam {
            name: self.ident.clean(),
450
            did: ast::DefId { krate: ast::LOCAL_CRATE, node: self.id },
451
            bounds: self.bounds.clean().move_iter().collect(),
C
Corey Richardson 已提交
452 453 454 455
        }
    }
}

456 457 458 459 460 461 462 463 464 465 466 467 468
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(),
        }
    }
}

C
Corey Richardson 已提交
469 470 471 472 473 474 475 476 477
#[deriving(Clone, Encodable, Decodable)]
pub enum TyParamBound {
    RegionBound,
    TraitBound(Type)
}

impl Clean<TyParamBound> for ast::TyParamBound {
    fn clean(&self) -> TyParamBound {
        match *self {
478 479
            ast::StaticRegionTyParamBound => RegionBound,
            ast::OtherRegionTyParamBound(_) => RegionBound,
480 481 482 483
            ast::UnboxedFnTyParamBound(_) => {
                // FIXME(pcwalton): Wrong.
                RegionBound
            }
C
Corey Richardson 已提交
484 485 486 487 488
            ast::TraitTyParamBound(ref t) => TraitBound(t.clean()),
        }
    }
}

489
fn external_path(name: &str, substs: &subst::Substs) -> Path {
490 491 492
    Path {
        global: false,
        segments: vec![PathSegment {
493
            name: name.to_string(),
494
            lifetimes: match substs.regions {
495 496
                subst::ErasedRegions => Vec::new(),
                subst::NonerasedRegions(ref v) => {
497 498 499 500 501
                    v.iter().filter_map(|v| v.clean()).collect()
                }
            },
            types: substs.tps.clean(),
        }],
502 503 504 505 506 507 508 509 510 511
    }
}

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,
        };
512
        let empty = subst::Substs::empty();
513 514 515
        let (did, path) = match *self {
            ty::BoundStatic => return RegionBound,
            ty::BoundSend =>
516 517
                (tcx.lang_items.send_trait().unwrap(),
                 external_path("Send", &empty)),
518
            ty::BoundSized =>
519 520
                (tcx.lang_items.sized_trait().unwrap(),
                 external_path("Sized", &empty)),
521
            ty::BoundCopy =>
522 523
                (tcx.lang_items.copy_trait().unwrap(),
                 external_path("Copy", &empty)),
524
            ty::BoundShare =>
525 526
                (tcx.lang_items.share_trait().unwrap(),
                 external_path("Share", &empty)),
527 528
        };
        let fqn = csearch::get_item_path(tcx, did);
529
        let fqn = fqn.move_iter().map(|i| i.to_str()).collect();
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547
        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);
548
        let fqn = fqn.move_iter().map(|i| i.to_str())
549
                     .collect::<Vec<String>>();
550 551
        let path = external_path(fqn.last().unwrap().as_slice(),
                                 &self.substs);
552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576
        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;
    }
}

577
impl Clean<Option<Vec<TyParamBound>>> for subst::Substs {
578 579 580
    fn clean(&self) -> Option<Vec<TyParamBound>> {
        let mut v = Vec::new();
        match self.regions {
581 582
            subst::NonerasedRegions(..) => v.push(RegionBound),
            subst::ErasedRegions => {}
583 584 585 586 587 588 589
        }
        v.extend(self.tps.iter().map(|t| TraitBound(t.clean())));

        if v.len() > 0 {Some(v)} else {None}
    }
}

590
#[deriving(Clone, Encodable, Decodable, PartialEq)]
591
pub struct Lifetime(String);
C
Corey Richardson 已提交
592

593 594 595
impl Lifetime {
    pub fn get_ref<'a>(&'a self) -> &'a str {
        let Lifetime(ref s) = *self;
596
        let s: &'a str = s.as_slice();
597 598 599 600
        return s;
    }
}

C
Corey Richardson 已提交
601 602
impl Clean<Lifetime> for ast::Lifetime {
    fn clean(&self) -> Lifetime {
603
        Lifetime(token::get_name(self.name).get().to_string())
C
Corey Richardson 已提交
604 605 606
    }
}

607 608
impl Clean<Lifetime> for ty::RegionParameterDef {
    fn clean(&self) -> Lifetime {
609
        Lifetime(token::get_name(self.name).get().to_string())
610 611 612 613 614 615
    }
}

impl Clean<Option<Lifetime>> for ty::Region {
    fn clean(&self) -> Option<Lifetime> {
        match *self {
616
            ty::ReStatic => Some(Lifetime("static".to_string())),
617
            ty::ReLateBound(_, ty::BrNamed(_, name)) =>
618
                Some(Lifetime(token::get_name(name).get().to_string())),
619
            ty::ReEarlyBound(_, _, name) => Some(Lifetime(name.clean())),
620 621 622 623 624 625 626 627 628 629

            ty::ReLateBound(..) |
            ty::ReFree(..) |
            ty::ReScope(..) |
            ty::ReInfer(..) |
            ty::ReEmpty(..) => None
        }
    }
}

C
Corey Richardson 已提交
630 631 632
// maybe use a Generic enum and use ~[Generic]?
#[deriving(Clone, Encodable, Decodable)]
pub struct Generics {
633 634 635
    pub lifetimes: Vec<Lifetime>,
    pub type_params: Vec<TyParam>,
}
C
Corey Richardson 已提交
636 637 638 639

impl Clean<Generics> for ast::Generics {
    fn clean(&self) -> Generics {
        Generics {
640 641
            lifetimes: self.lifetimes.clean().move_iter().collect(),
            type_params: self.ty_params.clean().move_iter().collect(),
C
Corey Richardson 已提交
642 643 644 645
        }
    }
}

646 647 648 649 650 651 652 653 654
impl Clean<Generics> for ty::Generics {
    fn clean(&self) -> Generics {
        Generics {
            lifetimes: self.region_param_defs.clean(),
            type_params: self.type_param_defs.clean(),
        }
    }
}

C
Corey Richardson 已提交
655 656
#[deriving(Clone, Encodable, Decodable)]
pub struct Method {
657 658
    pub generics: Generics,
    pub self_: SelfTy,
659
    pub fn_style: ast::FnStyle,
660
    pub decl: FnDecl,
C
Corey Richardson 已提交
661 662
}

663
impl Clean<Item> for ast::Method {
C
Corey Richardson 已提交
664
    fn clean(&self) -> Item {
665 666 667 668 669
        let inputs = match self.explicit_self.node {
            ast::SelfStatic => self.decl.inputs.as_slice(),
            _ => self.decl.inputs.slice_from(1)
        };
        let decl = FnDecl {
670 671 672
            inputs: Arguments {
                values: inputs.iter().map(|x| x.clean()).collect(),
            },
673 674
            output: (self.decl.output.clean()),
            cf: self.decl.cf.clean(),
675
            attrs: Vec::new()
676
        };
C
Corey Richardson 已提交
677 678
        Item {
            name: Some(self.ident.clean()),
679
            attrs: self.attrs.clean().move_iter().collect(),
C
Corey Richardson 已提交
680
            source: self.span.clean(),
681
            def_id: ast_util::local_def(self.id.clone()),
682
            visibility: self.vis.clean(),
C
Corey Richardson 已提交
683 684
            inner: MethodItem(Method {
                generics: self.generics.clean(),
685
                self_: self.explicit_self.node.clean(),
686
                fn_style: self.fn_style.clone(),
687
                decl: decl,
C
Corey Richardson 已提交
688 689 690 691 692 693 694
            }),
        }
    }
}

#[deriving(Clone, Encodable, Decodable)]
pub struct TyMethod {
695
    pub fn_style: ast::FnStyle,
696 697 698
    pub decl: FnDecl,
    pub generics: Generics,
    pub self_: SelfTy,
C
Corey Richardson 已提交
699 700 701 702
}

impl Clean<Item> for ast::TypeMethod {
    fn clean(&self) -> Item {
703 704 705 706 707
        let inputs = match self.explicit_self.node {
            ast::SelfStatic => self.decl.inputs.as_slice(),
            _ => self.decl.inputs.slice_from(1)
        };
        let decl = FnDecl {
708 709 710
            inputs: Arguments {
                values: inputs.iter().map(|x| x.clean()).collect(),
            },
711 712
            output: (self.decl.output.clean()),
            cf: self.decl.cf.clean(),
713
            attrs: Vec::new()
714
        };
C
Corey Richardson 已提交
715 716
        Item {
            name: Some(self.ident.clean()),
717
            attrs: self.attrs.clean().move_iter().collect(),
C
Corey Richardson 已提交
718
            source: self.span.clean(),
719
            def_id: ast_util::local_def(self.id),
C
Corey Richardson 已提交
720 721
            visibility: None,
            inner: TyMethodItem(TyMethod {
722
                fn_style: self.fn_style.clone(),
723
                decl: decl,
724
                self_: self.explicit_self.node.clean(),
C
Corey Richardson 已提交
725 726 727 728 729 730
                generics: self.generics.clean(),
            }),
        }
    }
}

731
#[deriving(Clone, Encodable, Decodable, PartialEq)]
C
Corey Richardson 已提交
732 733 734 735 736 737 738
pub enum SelfTy {
    SelfStatic,
    SelfValue,
    SelfBorrowed(Option<Lifetime>, Mutability),
    SelfOwned,
}

739
impl Clean<SelfTy> for ast::ExplicitSelf_ {
C
Corey Richardson 已提交
740
    fn clean(&self) -> SelfTy {
741
        match *self {
742
            ast::SelfStatic => SelfStatic,
743 744
            ast::SelfValue => SelfValue,
            ast::SelfUniq => SelfOwned,
745
            ast::SelfRegion(lt, mt) => SelfBorrowed(lt.clean(), mt.clean()),
C
Corey Richardson 已提交
746 747 748 749 750 751
        }
    }
}

#[deriving(Clone, Encodable, Decodable)]
pub struct Function {
752 753
    pub decl: FnDecl,
    pub generics: Generics,
754
    pub fn_style: ast::FnStyle,
C
Corey Richardson 已提交
755 756 757 758 759 760 761 762 763
}

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(),
764
            def_id: ast_util::local_def(self.id),
C
Corey Richardson 已提交
765 766 767
            inner: FunctionItem(Function {
                decl: self.decl.clean(),
                generics: self.generics.clean(),
768
                fn_style: self.fn_style,
C
Corey Richardson 已提交
769 770 771 772 773 774 775
            }),
        }
    }
}

#[deriving(Clone, Encodable, Decodable)]
pub struct ClosureDecl {
776 777 778
    pub lifetimes: Vec<Lifetime>,
    pub decl: FnDecl,
    pub onceness: ast::Onceness,
779
    pub fn_style: ast::FnStyle,
780 781
    pub bounds: Vec<TyParamBound>,
}
C
Corey Richardson 已提交
782

783
impl Clean<ClosureDecl> for ast::ClosureTy {
C
Corey Richardson 已提交
784 785
    fn clean(&self) -> ClosureDecl {
        ClosureDecl {
786
            lifetimes: self.lifetimes.clean(),
C
Corey Richardson 已提交
787 788
            decl: self.decl.clean(),
            onceness: self.onceness,
789
            fn_style: self.fn_style,
C
Corey Richardson 已提交
790
            bounds: match self.bounds {
791
                Some(ref x) => x.clean().move_iter().collect(),
792
                None        => Vec::new()
C
Corey Richardson 已提交
793 794 795 796 797 798 799
            },
        }
    }
}

#[deriving(Clone, Encodable, Decodable)]
pub struct FnDecl {
800 801 802 803 804
    pub inputs: Arguments,
    pub output: Type,
    pub cf: RetStyle,
    pub attrs: Vec<Attribute>,
}
C
Corey Richardson 已提交
805

806 807
#[deriving(Clone, Encodable, Decodable)]
pub struct Arguments {
808
    pub values: Vec<Argument>,
809 810
}

811
impl Clean<FnDecl> for ast::FnDecl {
C
Corey Richardson 已提交
812 813
    fn clean(&self) -> FnDecl {
        FnDecl {
814 815 816
            inputs: Arguments {
                values: self.inputs.iter().map(|x| x.clean()).collect(),
            },
C
Corey Richardson 已提交
817 818
            output: (self.output.clean()),
            cf: self.cf.clean(),
819
            attrs: Vec::new()
C
Corey Richardson 已提交
820 821 822 823
        }
    }
}

824
impl<'a> Clean<FnDecl> for (ast::DefId, &'a ty::FnSig) {
825
    fn clean(&self) -> FnDecl {
826 827 828
        let cx = super::ctxtkey.get().unwrap();
        let tcx = match cx.maybe_typed {
            core::Typed(ref tcx) => tcx,
829
            core::NotTyped(_) => unreachable!(),
830 831 832 833 834 835 836 837 838 839
        };
        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();
        }
840
        FnDecl {
841
            output: sig.output.clean(),
842
            cf: Return,
843
            attrs: Vec::new(),
844
            inputs: Arguments {
845
                values: sig.inputs.iter().map(|t| {
846 847 848
                    Argument {
                        type_: t.clean(),
                        id: 0,
849
                        name: names.next().unwrap_or("".to_string()),
850 851 852 853 854 855 856
                    }
                }).collect(),
            },
        }
    }
}

C
Corey Richardson 已提交
857 858
#[deriving(Clone, Encodable, Decodable)]
pub struct Argument {
859
    pub type_: Type,
860
    pub name: String,
861
    pub id: ast::NodeId,
C
Corey Richardson 已提交
862 863
}

864
impl Clean<Argument> for ast::Arg {
C
Corey Richardson 已提交
865 866 867 868 869 870 871 872 873 874 875 876 877 878 879
    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
}

880
impl Clean<RetStyle> for ast::RetStyle {
C
Corey Richardson 已提交
881 882
    fn clean(&self) -> RetStyle {
        match *self {
883 884
            ast::Return => Return,
            ast::NoReturn => NoReturn
C
Corey Richardson 已提交
885 886 887 888 889 890
        }
    }
}

#[deriving(Clone, Encodable, Decodable)]
pub struct Trait {
891 892 893
    pub methods: Vec<TraitMethod>,
    pub generics: Generics,
    pub parents: Vec<Type>,
C
Corey Richardson 已提交
894 895 896 897 898 899 900 901
}

impl Clean<Item> for doctree::Trait {
    fn clean(&self) -> Item {
        Item {
            name: Some(self.name.clean()),
            attrs: self.attrs.clean(),
            source: self.where.clean(),
902
            def_id: ast_util::local_def(self.id),
C
Corey Richardson 已提交
903 904 905 906 907 908 909 910 911 912
            visibility: self.vis.clean(),
            inner: TraitItem(Trait {
                methods: self.methods.clean(),
                generics: self.generics.clean(),
                parents: self.parents.clean(),
            }),
        }
    }
}

913
impl Clean<Type> for ast::TraitRef {
C
Corey Richardson 已提交
914
    fn clean(&self) -> Type {
915
        resolve_type(self.path.clean(), None, self.ref_id)
C
Corey Richardson 已提交
916 917 918 919 920 921 922 923 924 925
    }
}

#[deriving(Clone, Encodable, Decodable)]
pub enum TraitMethod {
    Required(Item),
    Provided(Item),
}

impl TraitMethod {
926
    pub fn is_req(&self) -> bool {
C
Corey Richardson 已提交
927
        match self {
A
Alex Crichton 已提交
928
            &Required(..) => true,
C
Corey Richardson 已提交
929 930 931
            _ => false,
        }
    }
932
    pub fn is_def(&self) -> bool {
C
Corey Richardson 已提交
933
        match self {
A
Alex Crichton 已提交
934
            &Provided(..) => true,
C
Corey Richardson 已提交
935 936 937
            _ => false,
        }
    }
938 939 940 941 942 943
    pub fn item<'a>(&'a self) -> &'a Item {
        match *self {
            Required(ref item) => item,
            Provided(ref item) => item,
        }
    }
C
Corey Richardson 已提交
944 945
}

946
impl Clean<TraitMethod> for ast::TraitMethod {
C
Corey Richardson 已提交
947 948
    fn clean(&self) -> TraitMethod {
        match self {
949 950
            &ast::Required(ref t) => Required(t.clean()),
            &ast::Provided(ref t) => Provided(t.clean()),
C
Corey Richardson 已提交
951 952 953 954
        }
    }
}

955 956
impl Clean<Item> for ty::Method {
    fn clean(&self) -> Item {
957 958 959
        let cx = super::ctxtkey.get().unwrap();
        let tcx = match cx.maybe_typed {
            core::Typed(ref tcx) => tcx,
960
            core::NotTyped(_) => unreachable!(),
961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982
        };
        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)
            }
        };
983

984
        Item {
985 986 987
            name: Some(self.ident.clean()),
            visibility: Some(ast::Inherited),
            def_id: self.def_id,
988
            attrs: inline::load_attrs(tcx, self.def_id),
989
            source: Span::empty(),
990 991 992 993
            inner: TyMethodItem(TyMethod {
                fn_style: self.fty.fn_style,
                generics: self.generics.clean(),
                self_: self_,
994
                decl: (self.def_id, &sig).clean(),
995
            })
996
        }
997 998 999
    }
}

C
Corey Richardson 已提交
1000 1001 1002 1003 1004
/// 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 {
1005
    /// structs/enums/traits (anything that'd be an ast::TyPath)
1006
    ResolvedPath {
1007 1008
        pub path: Path,
        pub typarams: Option<Vec<TyParamBound>>,
1009
        pub did: ast::DefId,
1010
    },
C
Corey Richardson 已提交
1011 1012 1013 1014
    // 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.
1015
    Generic(ast::DefId),
C
Corey Richardson 已提交
1016
    /// For references to self
1017
    Self(ast::DefId),
C
Corey Richardson 已提交
1018
    /// Primitives are just the fixed-size numeric types (plus int/uint/float), and char.
1019
    Primitive(Primitive),
1020 1021
    Closure(Box<ClosureDecl>, Option<Lifetime>),
    Proc(Box<ClosureDecl>),
C
Corey Richardson 已提交
1022
    /// extern "ABI" fn
1023
    BareFunction(Box<BareFunctionDecl>),
1024
    Tuple(Vec<Type>),
1025
    Vector(Box<Type>),
1026
    FixedVector(Box<Type>, String),
1027
    /// aka TyBot
C
Corey Richardson 已提交
1028
    Bottom,
1029 1030 1031
    Unique(Box<Type>),
    Managed(Box<Type>),
    RawPointer(Mutability, Box<Type>),
1032 1033 1034
    BorrowedRef {
        pub lifetime: Option<Lifetime>,
        pub mutability: Mutability,
1035
        pub type_: Box<Type>,
1036
    },
C
Corey Richardson 已提交
1037 1038 1039
    // region, raw, other boxes, mutable
}

1040
#[deriving(Clone, Encodable, Decodable, PartialEq, Eq, Hash)]
1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052
pub enum Primitive {
    Int, I8, I16, I32, I64,
    Uint, U8, U16, U32, U64,
    F32, F64, F128,
    Char,
    Bool,
    Nil,
    Str,
    Slice,
    PrimitiveTuple,
}

1053 1054 1055 1056
#[deriving(Clone, Encodable, Decodable)]
pub enum TypeKind {
    TypeEnum,
    TypeFunction,
1057 1058 1059 1060 1061
    TypeModule,
    TypeStatic,
    TypeStruct,
    TypeTrait,
    TypeVariant,
1062 1063
}

1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149
impl Primitive {
    fn from_str(s: &str) -> Option<Primitive> {
        match s.as_slice() {
            "int" => Some(Int),
            "i8" => Some(I8),
            "i16" => Some(I16),
            "i32" => Some(I32),
            "i64" => Some(I64),
            "uint" => Some(Uint),
            "u8" => Some(U8),
            "u16" => Some(U16),
            "u32" => Some(U32),
            "u64" => Some(U64),
            "bool" => Some(Bool),
            "nil" => Some(Nil),
            "char" => Some(Char),
            "str" => Some(Str),
            "f32" => Some(F32),
            "f64" => Some(F64),
            "f128" => Some(F128),
            "slice" => Some(Slice),
            "tuple" => Some(PrimitiveTuple),
            _ => None,
        }
    }

    fn find(attrs: &[Attribute]) -> Option<Primitive> {
        for attr in attrs.iter() {
            let list = match *attr {
                List(ref k, ref l) if k.as_slice() == "doc" => l,
                _ => continue,
            };
            for sub_attr in list.iter() {
                let value = match *sub_attr {
                    NameValue(ref k, ref v)
                        if k.as_slice() == "primitive" => v.as_slice(),
                    _ => continue,
                };
                match Primitive::from_str(value) {
                    Some(p) => return Some(p),
                    None => {}
                }
            }
        }
        return None
    }

    pub fn to_str(&self) -> &'static str {
        match *self {
            Int => "int",
            I8 => "i8",
            I16 => "i16",
            I32 => "i32",
            I64 => "i64",
            Uint => "uint",
            U8 => "u8",
            U16 => "u16",
            U32 => "u32",
            U64 => "u64",
            F32 => "f32",
            F64 => "f64",
            F128 => "f128",
            Str => "str",
            Bool => "bool",
            Char => "char",
            Nil => "()",
            Slice => "slice",
            PrimitiveTuple => "tuple",
        }
    }

    pub fn to_url_str(&self) -> &'static str {
        match *self {
            Nil => "nil",
            other => other.to_str(),
        }
    }

    /// Creates a rustdoc-specific node id for primitive types.
    ///
    /// These node ids are generally never used by the AST itself.
    pub fn to_node_id(&self) -> ast::NodeId {
        u32::MAX - 1 - (*self as u32)
    }
}

C
Corey Richardson 已提交
1150 1151 1152
impl Clean<Type> for ast::Ty {
    fn clean(&self) -> Type {
        use syntax::ast::*;
1153
        match self.node {
1154
            TyNil => Primitive(Nil),
1155
            TyPtr(ref m) => RawPointer(m.mutbl.clean(), box m.ty.clean()),
1156
            TyRptr(ref l, ref m) =>
C
Corey Richardson 已提交
1157
                BorrowedRef {lifetime: l.clean(), mutability: m.mutbl.clean(),
1158 1159 1160 1161 1162
                             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(),
1163 1164
                                                       e.span.to_src()),
            TyTup(ref tys) => Tuple(tys.iter().map(|x| x.clean()).collect()),
1165 1166 1167 1168 1169
            TyPath(ref p, ref tpbs, id) => {
                resolve_type(p.clean(),
                             tpbs.clean().map(|x| x.move_iter().collect()),
                             id)
            }
1170 1171 1172
            TyClosure(ref c, region) => Closure(box c.clean(), region.clean()),
            TyProc(ref c) => Proc(box c.clean()),
            TyBareFn(ref barefn) => BareFunction(box barefn.clean()),
1173
            TyBot => Bottom,
1174
            ref x => fail!("Unimplemented type {:?}", x),
1175
        }
C
Corey Richardson 已提交
1176 1177 1178
    }
}

1179 1180 1181 1182
impl Clean<Type> for ty::t {
    fn clean(&self) -> Type {
        match ty::get(*self).sty {
            ty::ty_bot => Bottom,
1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199
            ty::ty_nil => Primitive(Nil),
            ty::ty_bool => Primitive(Bool),
            ty::ty_char => Primitive(Char),
            ty::ty_int(ast::TyI) => Primitive(Int),
            ty::ty_int(ast::TyI8) => Primitive(I8),
            ty::ty_int(ast::TyI16) => Primitive(I16),
            ty::ty_int(ast::TyI32) => Primitive(I32),
            ty::ty_int(ast::TyI64) => Primitive(I64),
            ty::ty_uint(ast::TyU) => Primitive(Uint),
            ty::ty_uint(ast::TyU8) => Primitive(U8),
            ty::ty_uint(ast::TyU16) => Primitive(U16),
            ty::ty_uint(ast::TyU32) => Primitive(U32),
            ty::ty_uint(ast::TyU64) => Primitive(U64),
            ty::ty_float(ast::TyF32) => Primitive(F32),
            ty::ty_float(ast::TyF64) => Primitive(F64),
            ty::ty_float(ast::TyF128) => Primitive(F128),
            ty::ty_str => Primitive(Str),
1200 1201 1202 1203
            ty::ty_box(t) => Managed(box t.clean()),
            ty::ty_uniq(t) => Unique(box t.clean()),
            ty::ty_vec(mt, None) => Vector(box mt.ty.clean()),
            ty::ty_vec(mt, Some(i)) => FixedVector(box mt.ty.clean(),
A
Alex Crichton 已提交
1204
                                                   format!("{}", i)),
1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215
            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()
                },
1216
                decl: (ast_util::local_def(0), &fty.sig).clean(),
1217
                abi: fty.abi.to_str(),
1218 1219 1220 1221
            }),
            ty::ty_closure(ref fty) => {
                let decl = box ClosureDecl {
                    lifetimes: Vec::new(), // FIXME: this looks wrong...
1222
                    decl: (ast_util::local_def(0), &fty.sig).clean(),
1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237
                    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,
1238
                    core::NotTyped(_) => unreachable!(),
1239 1240
                };
                let fqn = csearch::get_item_path(tcx, did);
1241
                let fqn: Vec<String> = fqn.move_iter().map(|i| {
1242
                    i.to_str()
1243 1244 1245 1246 1247 1248
                }).collect();
                let kind = match ty::get(*self).sty {
                    ty::ty_struct(..) => TypeStruct,
                    ty::ty_trait(..) => TypeTrait,
                    _ => TypeEnum,
                };
1249 1250
                let path = external_path(fqn.last().unwrap().to_str().as_slice(),
                                         substs);
1251 1252 1253
                cx.external_paths.borrow_mut().get_mut_ref().insert(did,
                                                                    (fqn, kind));
                ResolvedPath {
1254
                    path: path,
1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269
                    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"),
        }
    }
}

C
Corey Richardson 已提交
1270
#[deriving(Clone, Encodable, Decodable)]
1271
pub enum StructField {
1272
    HiddenStructField, // inserted later by strip passes
1273
    TypedStructField(Type),
C
Corey Richardson 已提交
1274 1275
}

1276
impl Clean<Item> for ast::StructField {
C
Corey Richardson 已提交
1277 1278
    fn clean(&self) -> Item {
        let (name, vis) = match self.node.kind {
1279 1280
            ast::NamedField(id, vis) => (Some(id), vis),
            ast::UnnamedField(vis) => (None, vis)
C
Corey Richardson 已提交
1281 1282 1283
        };
        Item {
            name: name.clean(),
1284
            attrs: self.node.attrs.clean().move_iter().collect(),
C
Corey Richardson 已提交
1285
            source: self.span.clean(),
1286
            visibility: Some(vis),
1287
            def_id: ast_util::local_def(self.node.id),
1288
            inner: StructFieldItem(TypedStructField(self.node.ty.clean())),
C
Corey Richardson 已提交
1289 1290 1291 1292
        }
    }
}

1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303
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,
1304
            core::NotTyped(_) => unreachable!(),
1305 1306 1307 1308
        };
        let ty = ty::lookup_item_type(tcx, self.id);
        Item {
            name: name.clean(),
1309
            attrs: inline::load_attrs(tcx, self.id),
1310 1311 1312 1313 1314 1315 1316 1317
            source: Span::empty(),
            visibility: Some(self.vis),
            def_id: self.id,
            inner: StructFieldItem(TypedStructField(ty.ty.clean())),
        }
    }
}

1318
pub type Visibility = ast::Visibility;
C
Corey Richardson 已提交
1319

1320
impl Clean<Option<Visibility>> for ast::Visibility {
C
Corey Richardson 已提交
1321 1322 1323 1324 1325 1326 1327
    fn clean(&self) -> Option<Visibility> {
        Some(*self)
    }
}

#[deriving(Clone, Encodable, Decodable)]
pub struct Struct {
1328 1329 1330 1331
    pub struct_type: doctree::StructType,
    pub generics: Generics,
    pub fields: Vec<Item>,
    pub fields_stripped: bool,
C
Corey Richardson 已提交
1332 1333 1334 1335 1336 1337 1338 1339
}

impl Clean<Item> for doctree::Struct {
    fn clean(&self) -> Item {
        Item {
            name: Some(self.name.clean()),
            attrs: self.attrs.clean(),
            source: self.where.clean(),
1340
            def_id: ast_util::local_def(self.id),
C
Corey Richardson 已提交
1341 1342 1343 1344 1345
            visibility: self.vis.clean(),
            inner: StructItem(Struct {
                struct_type: self.struct_type,
                generics: self.generics.clean(),
                fields: self.fields.clean(),
S
Steven Fackler 已提交
1346
                fields_stripped: false,
C
Corey Richardson 已提交
1347 1348 1349 1350 1351
            }),
        }
    }
}

1352
/// This is a more limited form of the standard Struct, different in that
C
Corey Richardson 已提交
1353 1354 1355 1356
/// 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 {
1357 1358 1359
    pub struct_type: doctree::StructType,
    pub fields: Vec<Item>,
    pub fields_stripped: bool,
C
Corey Richardson 已提交
1360 1361
}

1362
impl Clean<VariantStruct> for syntax::ast::StructDef {
C
Corey Richardson 已提交
1363 1364 1365
    fn clean(&self) -> VariantStruct {
        VariantStruct {
            struct_type: doctree::struct_type_from_def(self),
1366
            fields: self.fields.clean().move_iter().collect(),
S
Steven Fackler 已提交
1367
            fields_stripped: false,
C
Corey Richardson 已提交
1368 1369 1370 1371 1372 1373
        }
    }
}

#[deriving(Clone, Encodable, Decodable)]
pub struct Enum {
1374 1375 1376
    pub variants: Vec<Item>,
    pub generics: Generics,
    pub variants_stripped: bool,
C
Corey Richardson 已提交
1377 1378 1379 1380 1381 1382 1383 1384
}

impl Clean<Item> for doctree::Enum {
    fn clean(&self) -> Item {
        Item {
            name: Some(self.name.clean()),
            attrs: self.attrs.clean(),
            source: self.where.clean(),
1385
            def_id: ast_util::local_def(self.id),
C
Corey Richardson 已提交
1386 1387 1388 1389
            visibility: self.vis.clean(),
            inner: EnumItem(Enum {
                variants: self.variants.clean(),
                generics: self.generics.clean(),
S
Steven Fackler 已提交
1390
                variants_stripped: false,
C
Corey Richardson 已提交
1391 1392 1393 1394 1395 1396 1397
            }),
        }
    }
}

#[deriving(Clone, Encodable, Decodable)]
pub struct Variant {
1398
    pub kind: VariantKind,
C
Corey Richardson 已提交
1399 1400 1401 1402 1403 1404 1405 1406 1407
}

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(),
1408
            def_id: ast_util::local_def(self.id),
C
Corey Richardson 已提交
1409 1410 1411 1412 1413 1414 1415
            inner: VariantItem(Variant {
                kind: self.kind.clean(),
            }),
        }
    }
}

1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438
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),
1439 1440 1441 1442 1443
                            // 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,
1444 1445 1446 1447 1448 1449 1450 1451 1452 1453
                            inner: StructFieldItem(
                                TypedStructField(ty.clean())
                            )
                        }
                    }).collect()
                })
            }
        };
        Item {
            name: Some(self.name.clean()),
1454
            attrs: inline::load_attrs(tcx, self.id),
1455 1456 1457 1458 1459 1460 1461 1462
            source: Span::empty(),
            visibility: Some(ast::Public),
            def_id: self.id,
            inner: VariantItem(Variant { kind: kind }),
        }
    }
}

C
Corey Richardson 已提交
1463 1464 1465
#[deriving(Clone, Encodable, Decodable)]
pub enum VariantKind {
    CLikeVariant,
1466
    TupleVariant(Vec<Type>),
C
Corey Richardson 已提交
1467 1468 1469
    StructVariant(VariantStruct),
}

1470
impl Clean<VariantKind> for ast::VariantKind {
C
Corey Richardson 已提交
1471 1472
    fn clean(&self) -> VariantKind {
        match self {
1473
            &ast::TupleVariantKind(ref args) => {
C
Corey Richardson 已提交
1474 1475 1476 1477 1478 1479
                if args.len() == 0 {
                    CLikeVariant
                } else {
                    TupleVariant(args.iter().map(|x| x.ty.clean()).collect())
                }
            },
1480
            &ast::StructVariantKind(ref sd) => StructVariant(sd.clean()),
C
Corey Richardson 已提交
1481 1482 1483 1484
        }
    }
}

1485 1486
#[deriving(Clone, Encodable, Decodable)]
pub struct Span {
1487
    pub filename: String,
1488 1489 1490 1491
    pub loline: uint,
    pub locol: uint,
    pub hiline: uint,
    pub hicol: uint,
1492 1493
}

1494 1495 1496
impl Span {
    fn empty() -> Span {
        Span {
1497
            filename: "".to_string(),
1498 1499 1500 1501 1502 1503
            loline: 0, locol: 0,
            hiline: 0, hicol: 0,
        }
    }
}

1504 1505
impl Clean<Span> for syntax::codemap::Span {
    fn clean(&self) -> Span {
1506
        let ctxt = super::ctxtkey.get().unwrap();
N
Niko Matsakis 已提交
1507
        let cm = ctxt.sess().codemap();
1508 1509 1510 1511
        let filename = cm.span_to_filename(*self);
        let lo = cm.lookup_char_pos(self.lo);
        let hi = cm.lookup_char_pos(self.hi);
        Span {
1512
            filename: filename.to_string(),
1513
            loline: lo.line,
1514
            locol: lo.col.to_uint(),
1515
            hiline: hi.line,
1516
            hicol: hi.col.to_uint(),
1517
        }
C
Corey Richardson 已提交
1518 1519 1520 1521 1522
    }
}

#[deriving(Clone, Encodable, Decodable)]
pub struct Path {
1523 1524
    pub global: bool,
    pub segments: Vec<PathSegment>,
C
Corey Richardson 已提交
1525 1526 1527 1528 1529
}

impl Clean<Path> for ast::Path {
    fn clean(&self) -> Path {
        Path {
1530
            global: self.global,
1531
            segments: self.segments.clean().move_iter().collect(),
1532 1533 1534 1535 1536 1537
        }
    }
}

#[deriving(Clone, Encodable, Decodable)]
pub struct PathSegment {
1538
    pub name: String,
1539 1540
    pub lifetimes: Vec<Lifetime>,
    pub types: Vec<Type>,
1541 1542 1543 1544 1545 1546
}

impl Clean<PathSegment> for ast::PathSegment {
    fn clean(&self) -> PathSegment {
        PathSegment {
            name: self.identifier.clean(),
1547 1548
            lifetimes: self.lifetimes.clean().move_iter().collect(),
            types: self.types.clean().move_iter().collect()
C
Corey Richardson 已提交
1549 1550 1551 1552
        }
    }
}

1553
fn path_to_str(p: &ast::Path) -> String {
1554
    use syntax::parse::token;
C
Corey Richardson 已提交
1555

1556
    let mut s = String::new();
C
Corey Richardson 已提交
1557
    let mut first = true;
1558
    for i in p.segments.iter().map(|x| token::get_ident(x.identifier)) {
C
Corey Richardson 已提交
1559 1560 1561 1562 1563
        if !first || p.global {
            s.push_str("::");
        } else {
            first = false;
        }
1564
        s.push_str(i.get());
C
Corey Richardson 已提交
1565
    }
1566
    s
C
Corey Richardson 已提交
1567 1568
}

1569 1570
impl Clean<String> for ast::Ident {
    fn clean(&self) -> String {
1571
        token::get_ident(*self).get().to_string()
C
Corey Richardson 已提交
1572 1573 1574
    }
}

1575 1576
impl Clean<String> for ast::Name {
    fn clean(&self) -> String {
1577
        token::get_name(*self).get().to_string()
1578 1579 1580
    }
}

C
Corey Richardson 已提交
1581 1582
#[deriving(Clone, Encodable, Decodable)]
pub struct Typedef {
1583 1584
    pub type_: Type,
    pub generics: Generics,
C
Corey Richardson 已提交
1585 1586 1587 1588 1589 1590 1591 1592
}

impl Clean<Item> for doctree::Typedef {
    fn clean(&self) -> Item {
        Item {
            name: Some(self.name.clean()),
            attrs: self.attrs.clean(),
            source: self.where.clean(),
1593
            def_id: ast_util::local_def(self.id.clone()),
C
Corey Richardson 已提交
1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604
            visibility: self.vis.clean(),
            inner: TypedefItem(Typedef {
                type_: self.ty.clean(),
                generics: self.gen.clean(),
            }),
        }
    }
}

#[deriving(Clone, Encodable, Decodable)]
pub struct BareFunctionDecl {
1605
    pub fn_style: ast::FnStyle,
1606 1607
    pub generics: Generics,
    pub decl: FnDecl,
1608
    pub abi: String,
C
Corey Richardson 已提交
1609 1610
}

1611
impl Clean<BareFunctionDecl> for ast::BareFnTy {
C
Corey Richardson 已提交
1612 1613
    fn clean(&self) -> BareFunctionDecl {
        BareFunctionDecl {
1614
            fn_style: self.fn_style,
C
Corey Richardson 已提交
1615
            generics: Generics {
1616
                lifetimes: self.lifetimes.clean().move_iter().collect(),
1617
                type_params: Vec::new(),
C
Corey Richardson 已提交
1618 1619
            },
            decl: self.decl.clean(),
1620
            abi: self.abi.to_str(),
C
Corey Richardson 已提交
1621 1622 1623 1624 1625 1626
        }
    }
}

#[deriving(Clone, Encodable, Decodable)]
pub struct Static {
1627 1628
    pub type_: Type,
    pub mutability: Mutability,
C
Corey Richardson 已提交
1629 1630 1631
    /// 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.
1632
    pub expr: String,
C
Corey Richardson 已提交
1633 1634 1635 1636
}

impl Clean<Item> for doctree::Static {
    fn clean(&self) -> Item {
1637
        debug!("claning static {}: {:?}", self.name.clean(), self);
C
Corey Richardson 已提交
1638 1639 1640 1641
        Item {
            name: Some(self.name.clean()),
            attrs: self.attrs.clean(),
            source: self.where.clean(),
1642
            def_id: ast_util::local_def(self.id),
C
Corey Richardson 已提交
1643 1644 1645 1646 1647 1648 1649 1650 1651 1652
            visibility: self.vis.clean(),
            inner: StaticItem(Static {
                type_: self.type_.clean(),
                mutability: self.mutability.clean(),
                expr: self.expr.span.to_src(),
            }),
        }
    }
}

1653
#[deriving(Show, Clone, Encodable, Decodable, PartialEq)]
C
Corey Richardson 已提交
1654 1655 1656 1657 1658
pub enum Mutability {
    Mutable,
    Immutable,
}

1659
impl Clean<Mutability> for ast::Mutability {
C
Corey Richardson 已提交
1660 1661
    fn clean(&self) -> Mutability {
        match self {
1662 1663
            &ast::MutMutable => Mutable,
            &ast::MutImmutable => Immutable,
C
Corey Richardson 已提交
1664 1665 1666 1667 1668 1669
        }
    }
}

#[deriving(Clone, Encodable, Decodable)]
pub struct Impl {
1670 1671 1672 1673 1674
    pub generics: Generics,
    pub trait_: Option<Type>,
    pub for_: Type,
    pub methods: Vec<Item>,
    pub derived: bool,
C
Corey Richardson 已提交
1675 1676
}

1677
fn detect_derived<M: AttrMetaMethods>(attrs: &[M]) -> bool {
1678
    attr::contains_name(attrs, "automatically_derived")
1679 1680
}

C
Corey Richardson 已提交
1681 1682 1683 1684 1685 1686
impl Clean<Item> for doctree::Impl {
    fn clean(&self) -> Item {
        Item {
            name: None,
            attrs: self.attrs.clean(),
            source: self.where.clean(),
1687
            def_id: ast_util::local_def(self.id),
C
Corey Richardson 已提交
1688 1689 1690 1691 1692 1693
            visibility: self.vis.clean(),
            inner: ImplItem(Impl {
                generics: self.generics.clean(),
                trait_: self.trait_.clean(),
                for_: self.for_.clean(),
                methods: self.methods.clean(),
1694
                derived: detect_derived(self.attrs.as_slice()),
C
Corey Richardson 已提交
1695 1696 1697 1698 1699 1700 1701
            }),
        }
    }
}

#[deriving(Clone, Encodable, Decodable)]
pub struct ViewItem {
1702
    pub inner: ViewItemInner,
C
Corey Richardson 已提交
1703 1704
}

1705 1706
impl Clean<Vec<Item>> for ast::ViewItem {
    fn clean(&self) -> Vec<Item> {
1707 1708 1709
        // 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.
1710 1711
        let denied = self.vis != ast::Public || self.attrs.iter().any(|a| {
            a.name().get() == "doc" && match a.meta_item_list() {
1712
                Some(l) => attr::contains_name(l, "no_inline"),
1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731
                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) => {
1732 1733 1734
                        // Attempt to inline all reexported items, but be sure
                        // to keep any non-inlineable reexports so they can be
                        // listed in the documentation.
1735
                        let remaining = list.iter().filter(|path| {
1736
                            match inline::try_inline(path.node.id) {
1737 1738 1739
                                Some(items) => {
                                    ret.extend(items.move_iter()); false
                                }
1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751
                                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) => {
1752
                        match inline::try_inline(id) {
1753
                            Some(items) => ret.extend(items.move_iter()),
1754 1755 1756 1757 1758 1759
                            None => ret.push(convert(&self.node)),
                        }
                    }
                }
            }
            ref n => ret.push(convert(n)),
C
Corey Richardson 已提交
1760
        }
1761
        return ret;
C
Corey Richardson 已提交
1762 1763 1764 1765 1766
    }
}

#[deriving(Clone, Encodable, Decodable)]
pub enum ViewItemInner {
1767
    ExternCrate(String, Option<String>, ast::NodeId),
1768
    Import(ViewPath)
C
Corey Richardson 已提交
1769 1770
}

1771
impl Clean<ViewItemInner> for ast::ViewItem_ {
C
Corey Richardson 已提交
1772 1773
    fn clean(&self) -> ViewItemInner {
        match self {
1774
            &ast::ViewItemExternCrate(ref i, ref p, ref id) => {
P
Patrick Walton 已提交
1775 1776
                let string = match *p {
                    None => None,
1777
                    Some((ref x, _)) => Some(x.get().to_string()),
P
Patrick Walton 已提交
1778
                };
1779
                ExternCrate(i.clean(), string, *id)
P
Patrick Walton 已提交
1780
            }
1781
            &ast::ViewItemUse(ref vp) => {
1782
                Import(vp.clean())
1783
            }
C
Corey Richardson 已提交
1784 1785 1786 1787 1788 1789
        }
    }
}

#[deriving(Clone, Encodable, Decodable)]
pub enum ViewPath {
A
Alex Crichton 已提交
1790
    // use str = source;
1791
    SimpleImport(String, ImportSource),
A
Alex Crichton 已提交
1792 1793 1794
    // use source::*;
    GlobImport(ImportSource),
    // use source::{a, b, c};
1795
    ImportList(ImportSource, Vec<ViewListIdent>),
A
Alex Crichton 已提交
1796 1797 1798 1799
}

#[deriving(Clone, Encodable, Decodable)]
pub struct ImportSource {
1800 1801
    pub path: Path,
    pub did: Option<ast::DefId>,
C
Corey Richardson 已提交
1802 1803
}

1804
impl Clean<ViewPath> for ast::ViewPath {
C
Corey Richardson 已提交
1805 1806
    fn clean(&self) -> ViewPath {
        match self.node {
1807
            ast::ViewPathSimple(ref i, ref p, id) =>
A
Alex Crichton 已提交
1808
                SimpleImport(i.clean(), resolve_use_source(p.clean(), id)),
1809
            ast::ViewPathGlob(ref p, id) =>
A
Alex Crichton 已提交
1810
                GlobImport(resolve_use_source(p.clean(), id)),
1811 1812 1813 1814
            ast::ViewPathList(ref p, ref pl, id) => {
                ImportList(resolve_use_source(p.clean(), id),
                           pl.clean().move_iter().collect())
            }
C
Corey Richardson 已提交
1815 1816 1817 1818
        }
    }
}

A
Alex Crichton 已提交
1819 1820
#[deriving(Clone, Encodable, Decodable)]
pub struct ViewListIdent {
1821
    pub name: String,
1822
    pub source: Option<ast::DefId>,
A
Alex Crichton 已提交
1823
}
C
Corey Richardson 已提交
1824

1825
impl Clean<ViewListIdent> for ast::PathListIdent {
C
Corey Richardson 已提交
1826
    fn clean(&self) -> ViewListIdent {
A
Alex Crichton 已提交
1827 1828 1829 1830
        ViewListIdent {
            name: self.node.name.clean(),
            source: resolve_def(self.node.id),
        }
C
Corey Richardson 已提交
1831 1832 1833
    }
}

1834 1835
impl Clean<Vec<Item>> for ast::ForeignMod {
    fn clean(&self) -> Vec<Item> {
1836 1837 1838 1839
        self.items.clean()
    }
}

1840
impl Clean<Item> for ast::ForeignItem {
1841 1842
    fn clean(&self) -> Item {
        let inner = match self.node {
1843
            ast::ForeignItemFn(ref decl, ref generics) => {
1844 1845 1846
                ForeignFunctionItem(Function {
                    decl: decl.clean(),
                    generics: generics.clean(),
1847
                    fn_style: ast::UnsafeFn,
1848 1849
                })
            }
1850
            ast::ForeignItemStatic(ref ty, mutbl) => {
1851 1852 1853
                ForeignStaticItem(Static {
                    type_: ty.clean(),
                    mutability: if mutbl {Mutable} else {Immutable},
1854
                    expr: "".to_string(),
1855 1856 1857 1858 1859
                })
            }
        };
        Item {
            name: Some(self.ident.clean()),
1860
            attrs: self.attrs.clean().move_iter().collect(),
1861
            source: self.span.clean(),
1862
            def_id: ast_util::local_def(self.id),
1863 1864 1865 1866 1867 1868
            visibility: self.vis.clean(),
            inner: inner,
        }
    }
}

C
Corey Richardson 已提交
1869 1870 1871
// Utilities

trait ToSource {
1872
    fn to_src(&self) -> String;
C
Corey Richardson 已提交
1873 1874
}

1875
impl ToSource for syntax::codemap::Span {
1876
    fn to_src(&self) -> String {
1877
        debug!("converting span {:?} to snippet", self.clean());
1878
        let ctxt = super::ctxtkey.get().unwrap();
N
Niko Matsakis 已提交
1879
        let cm = ctxt.sess().codemap().clone();
C
Corey Richardson 已提交
1880
        let sn = match cm.span_to_snippet(*self) {
1881 1882
            Some(x) => x.to_string(),
            None    => "".to_string()
C
Corey Richardson 已提交
1883
        };
1884
        debug!("got snippet {}", sn);
C
Corey Richardson 已提交
1885 1886 1887 1888
        sn
    }
}

1889
fn lit_to_str(lit: &ast::Lit) -> String {
C
Corey Richardson 已提交
1890
    match lit.node {
1891
        ast::LitStr(ref st, _) => st.get().to_string(),
A
Alex Crichton 已提交
1892 1893
        ast::LitBinary(ref data) => format!("{:?}", data.as_slice()),
        ast::LitChar(c) => format!("'{}'", c),
1894 1895 1896
        ast::LitInt(i, _t) => i.to_str(),
        ast::LitUint(u, _t) => u.to_str(),
        ast::LitIntUnsuffixed(i) => i.to_str(),
1897 1898
        ast::LitFloat(ref f, _t) => f.get().to_string(),
        ast::LitFloatUnsuffixed(ref f) => f.get().to_string(),
1899
        ast::LitBool(b) => b.to_str(),
1900
        ast::LitNil => "".to_string(),
C
Corey Richardson 已提交
1901 1902 1903
    }
}

1904
fn name_from_pat(p: &ast::Pat) -> String {
C
Corey Richardson 已提交
1905
    use syntax::ast::*;
1906 1907
    debug!("Trying to get a name from pattern: {:?}", p);

C
Corey Richardson 已提交
1908
    match p.node {
1909 1910
        PatWild => "_".to_string(),
        PatWildMulti => "..".to_string(),
1911 1912
        PatIdent(_, ref p, _) => path_to_str(p),
        PatEnum(ref p, _) => path_to_str(p),
A
Alex Crichton 已提交
1913
        PatStruct(..) => fail!("tried to get argument name from pat_struct, \
1914
                                which is not allowed in function arguments"),
1915
        PatTup(..) => "(tuple arg NYI)".to_string(),
1916
        PatBox(p) => name_from_pat(p),
1917
        PatRegion(p) => name_from_pat(p),
1918 1919 1920
        PatLit(..) => {
            warn!("tried to get argument name from PatLit, \
                  which is silly in function arguments");
1921
            "()".to_string()
1922 1923
        },
        PatRange(..) => fail!("tried to get argument name from PatRange, \
1924
                              which is not allowed in function arguments"),
A
Alex Crichton 已提交
1925
        PatVec(..) => fail!("tried to get argument name from pat_vec, \
1926 1927 1928 1929 1930 1931
                             which is not allowed in function arguments"),
        PatMac(..) => {
            warn!("can't document the name of a function argument \
                   produced by a pattern macro");
            "(argument produced by macro)".to_string()
        }
C
Corey Richardson 已提交
1932 1933 1934 1935
    }
}

/// Given a Type, resolve it using the def_map
1936
fn resolve_type(path: Path, tpbs: Option<Vec<TyParamBound>>,
1937
                id: ast::NodeId) -> Type {
1938
    let cx = super::ctxtkey.get().unwrap();
E
Eduard Burtescu 已提交
1939 1940
    let tycx = match cx.maybe_typed {
        core::Typed(ref tycx) => tycx,
1941
        // If we're extracting tests, this return value doesn't matter.
1942
        core::NotTyped(_) => return Primitive(Bool),
1943
    };
1944
    debug!("searching for {:?} in defmap", id);
1945
    let def = match tycx.def_map.borrow().find(&id) {
1946
        Some(&k) => k,
1947
        None => fail!("unresolved id not in defmap")
C
Corey Richardson 已提交
1948 1949
    };

1950
    match def {
1951 1952
        def::DefSelfTy(i) => return Self(ast_util::local_def(i)),
        def::DefPrimTy(p) => match p {
1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968
            ast::TyStr => return Primitive(Str),
            ast::TyBool => return Primitive(Bool),
            ast::TyChar => return Primitive(Char),
            ast::TyInt(ast::TyI) => return Primitive(Int),
            ast::TyInt(ast::TyI8) => return Primitive(I8),
            ast::TyInt(ast::TyI16) => return Primitive(I16),
            ast::TyInt(ast::TyI32) => return Primitive(I32),
            ast::TyInt(ast::TyI64) => return Primitive(I64),
            ast::TyUint(ast::TyU) => return Primitive(Uint),
            ast::TyUint(ast::TyU8) => return Primitive(U8),
            ast::TyUint(ast::TyU16) => return Primitive(U16),
            ast::TyUint(ast::TyU32) => return Primitive(U32),
            ast::TyUint(ast::TyU64) => return Primitive(U64),
            ast::TyFloat(ast::TyF32) => return Primitive(F32),
            ast::TyFloat(ast::TyF64) => return Primitive(F64),
            ast::TyFloat(ast::TyF128) => return Primitive(F128),
C
Corey Richardson 已提交
1969
        },
1970 1971
        def::DefTyParam(i, _) => return Generic(i),
        def::DefTyParamBinder(i) => return TyParamBinder(i),
1972 1973 1974 1975 1976 1977
        _ => {}
    };
    let did = register_def(&**cx, def);
    ResolvedPath { path: path, typarams: tpbs, did: did }
}

1978
fn register_def(cx: &core::DocContext, def: def::Def) -> ast::DefId {
1979
    let (did, kind) = match def {
1980 1981 1982 1983 1984 1985 1986 1987
        def::DefFn(i, _) => (i, TypeFunction),
        def::DefTy(i) => (i, TypeEnum),
        def::DefTrait(i) => (i, TypeTrait),
        def::DefStruct(i) => (i, TypeStruct),
        def::DefMod(i) => (i, TypeModule),
        def::DefStatic(i, _) => (i, TypeStatic),
        def::DefVariant(i, _, _) => (i, TypeEnum),
        _ => return def.def_id()
C
Corey Richardson 已提交
1988
    };
1989 1990 1991 1992 1993
    if ast_util::is_local(did) { return did }
    let tcx = match cx.maybe_typed {
        core::Typed(ref t) => t,
        core::NotTyped(_) => return did
    };
1994
    inline::record_extern_fqn(cx, did, kind);
1995 1996
    match kind {
        TypeTrait => {
1997
            let t = inline::build_external_trait(tcx, did);
1998 1999 2000 2001
            cx.external_traits.borrow_mut().get_mut_ref().insert(did, t);
        }
        _ => {}
    }
2002
    return did;
C
Corey Richardson 已提交
2003
}
A
Alex Crichton 已提交
2004 2005 2006 2007 2008 2009 2010 2011 2012

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> {
2013
    let cx = super::ctxtkey.get().unwrap();
E
Eduard Burtescu 已提交
2014 2015
    match cx.maybe_typed {
        core::Typed(ref tcx) => {
2016
            tcx.def_map.borrow().find(&id).map(|&def| register_def(&**cx, def))
2017
        }
E
Eduard Burtescu 已提交
2018
        core::NotTyped(_) => None
2019
    }
A
Alex Crichton 已提交
2020
}
2021 2022 2023

#[deriving(Clone, Encodable, Decodable)]
pub struct Macro {
2024
    pub source: String,
2025 2026 2027 2028 2029
}

impl Clean<Item> for doctree::Macro {
    fn clean(&self) -> Item {
        Item {
A
Alex Crichton 已提交
2030
            name: Some(format!("{}!", self.name.clean())),
2031 2032 2033
            attrs: self.attrs.clean(),
            source: self.where.clean(),
            visibility: ast::Public.clean(),
2034
            def_id: ast_util::local_def(self.id),
2035 2036 2037 2038 2039 2040
            inner: MacroItem(Macro {
                source: self.where.to_src(),
            }),
        }
    }
}