]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/clean.rs
auto merge of #12995 : Kroisse/rust/vec_ng_mut_slices, r=alexcrichton
[rust.git] / src / librustdoc / clean.rs
1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! This module contains the "cleaned" pieces of the AST, and the functions
12 //! that clean them.
13
14 use syntax;
15 use syntax::ast;
16 use syntax::ast_util;
17 use syntax::attr;
18 use syntax::attr::AttributeMethods;
19 use syntax::codemap::Pos;
20 use syntax::parse::token::InternedString;
21 use syntax::parse::token;
22
23 use rustc::metadata::cstore;
24 use rustc::metadata::csearch;
25 use rustc::metadata::decoder;
26
27 use std;
28
29 use core;
30 use doctree;
31 use visit_ast;
32 use std::local_data;
33
34 pub trait Clean<T> {
35     fn clean(&self) -> T;
36 }
37
38 impl<T: Clean<U>, U> Clean<Vec<U>> for Vec<T> {
39     fn clean(&self) -> Vec<U> {
40         self.iter().map(|x| x.clean()).collect()
41     }
42 }
43
44 impl<T: Clean<U>, U> Clean<U> for @T {
45     fn clean(&self) -> U {
46         (**self).clean()
47     }
48 }
49
50 impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
51     fn clean(&self) -> Option<U> {
52         match self {
53             &None => None,
54             &Some(ref v) => Some(v.clean())
55         }
56     }
57 }
58
59 impl<T: Clean<U>, U> Clean<Vec<U>> for syntax::owned_slice::OwnedSlice<T> {
60     fn clean(&self) -> Vec<U> {
61         self.iter().map(|x| x.clean()).collect()
62     }
63 }
64
65 #[deriving(Clone, Encodable, Decodable)]
66 pub struct Crate {
67     name: ~str,
68     module: Option<Item>,
69     externs: Vec<(ast::CrateNum, ExternalCrate)> ,
70 }
71
72 impl<'a> Clean<Crate> for visit_ast::RustdocVisitor<'a> {
73     fn clean(&self) -> Crate {
74         use syntax::attr::find_crateid;
75         let cx = local_data::get(super::ctxtkey, |x| *x.unwrap());
76
77         let mut externs = Vec::new();
78         cx.sess().cstore.iter_crate_data(|n, meta| {
79             externs.push((n, meta.clean()));
80         });
81
82         Crate {
83             name: match find_crateid(self.attrs.as_slice()) {
84                 Some(n) => n.name,
85                 None => fail!("rustdoc requires a `crate_id` crate attribute"),
86             },
87             module: Some(self.module.clean()),
88             externs: externs,
89         }
90     }
91 }
92
93 #[deriving(Clone, Encodable, Decodable)]
94 pub struct ExternalCrate {
95     name: ~str,
96     attrs: Vec<Attribute> ,
97 }
98
99 impl Clean<ExternalCrate> for cstore::crate_metadata {
100     fn clean(&self) -> ExternalCrate {
101         ExternalCrate {
102             name: self.name.to_owned(),
103             attrs: decoder::get_crate_attributes(self.data()).clean()
104                                                              .move_iter()
105                                                              .collect(),
106         }
107     }
108 }
109
110 /// Anything with a source location and set of attributes and, optionally, a
111 /// name. That is, anything that can be documented. This doesn't correspond
112 /// directly to the AST's concept of an item; it's a strict superset.
113 #[deriving(Clone, Encodable, Decodable)]
114 pub struct Item {
115     /// Stringified span
116     source: Span,
117     /// Not everything has a name. E.g., impls
118     name: Option<~str>,
119     attrs: Vec<Attribute> ,
120     inner: ItemEnum,
121     visibility: Option<Visibility>,
122     id: ast::NodeId,
123 }
124
125 impl Item {
126     /// Finds the `doc` attribute as a List and returns the list of attributes
127     /// nested inside.
128     pub fn doc_list<'a>(&'a self) -> Option<&'a [Attribute]> {
129         for attr in self.attrs.iter() {
130             match *attr {
131                 List(ref x, ref list) if "doc" == *x => { return Some(list.as_slice()); }
132                 _ => {}
133             }
134         }
135         return None;
136     }
137
138     /// Finds the `doc` attribute as a NameValue and returns the corresponding
139     /// value found.
140     pub fn doc_value<'a>(&'a self) -> Option<&'a str> {
141         for attr in self.attrs.iter() {
142             match *attr {
143                 NameValue(ref x, ref v) if "doc" == *x => { return Some(v.as_slice()); }
144                 _ => {}
145             }
146         }
147         return None;
148     }
149
150     pub fn is_mod(&self) -> bool {
151         match self.inner { ModuleItem(..) => true, _ => false }
152     }
153     pub fn is_trait(&self) -> bool {
154         match self.inner { TraitItem(..) => true, _ => false }
155     }
156     pub fn is_struct(&self) -> bool {
157         match self.inner { StructItem(..) => true, _ => false }
158     }
159     pub fn is_enum(&self) -> bool {
160         match self.inner { EnumItem(..) => true, _ => false }
161     }
162     pub fn is_fn(&self) -> bool {
163         match self.inner { FunctionItem(..) => true, _ => false }
164     }
165 }
166
167 #[deriving(Clone, Encodable, Decodable)]
168 pub enum ItemEnum {
169     StructItem(Struct),
170     EnumItem(Enum),
171     FunctionItem(Function),
172     ModuleItem(Module),
173     TypedefItem(Typedef),
174     StaticItem(Static),
175     TraitItem(Trait),
176     ImplItem(Impl),
177     ViewItemItem(ViewItem),
178     TyMethodItem(TyMethod),
179     MethodItem(Method),
180     StructFieldItem(StructField),
181     VariantItem(Variant),
182     ForeignFunctionItem(Function),
183     ForeignStaticItem(Static),
184     MacroItem(Macro),
185 }
186
187 #[deriving(Clone, Encodable, Decodable)]
188 pub struct Module {
189     items: Vec<Item> ,
190     is_crate: bool,
191 }
192
193 impl Clean<Item> for doctree::Module {
194     fn clean(&self) -> Item {
195         let name = if self.name.is_some() {
196             self.name.unwrap().clean()
197         } else {
198             ~""
199         };
200         let mut foreigns = Vec::new();
201         for subforeigns in self.foreigns.clean().move_iter() {
202             for foreign in subforeigns.move_iter() {
203                 foreigns.push(foreign)
204             }
205         }
206         let items: Vec<Vec<Item> > = vec!(
207             self.structs.clean().move_iter().collect(),
208             self.enums.clean().move_iter().collect(),
209             self.fns.clean().move_iter().collect(),
210             foreigns,
211             self.mods.clean().move_iter().collect(),
212             self.typedefs.clean().move_iter().collect(),
213             self.statics.clean().move_iter().collect(),
214             self.traits.clean().move_iter().collect(),
215             self.impls.clean().move_iter().collect(),
216             self.view_items.clean().move_iter().collect(),
217             self.macros.clean().move_iter().collect()
218         );
219         Item {
220             name: Some(name),
221             attrs: self.attrs.clean(),
222             source: self.where.clean(),
223             visibility: self.vis.clean(),
224             id: self.id,
225             inner: ModuleItem(Module {
226                is_crate: self.is_crate,
227                items: items.iter()
228                            .flat_map(|x| x.iter().map(|x| (*x).clone()))
229                            .collect(),
230             })
231         }
232     }
233 }
234
235 #[deriving(Clone, Encodable, Decodable)]
236 pub enum Attribute {
237     Word(~str),
238     List(~str, Vec<Attribute> ),
239     NameValue(~str, ~str)
240 }
241
242 impl Clean<Attribute> for ast::MetaItem {
243     fn clean(&self) -> Attribute {
244         match self.node {
245             ast::MetaWord(ref s) => Word(s.get().to_owned()),
246             ast::MetaList(ref s, ref l) => {
247                 List(s.get().to_owned(), l.clean().move_iter().collect())
248             }
249             ast::MetaNameValue(ref s, ref v) => {
250                 NameValue(s.get().to_owned(), lit_to_str(v))
251             }
252         }
253     }
254 }
255
256 impl Clean<Attribute> for ast::Attribute {
257     fn clean(&self) -> Attribute {
258         self.desugar_doc().node.value.clean()
259     }
260 }
261
262 // This is a rough approximation that gets us what we want.
263 impl<'a> attr::AttrMetaMethods for &'a Attribute {
264     fn name(&self) -> InternedString {
265         match **self {
266             Word(ref n) | List(ref n, _) | NameValue(ref n, _) => {
267                 token::intern_and_get_ident(*n)
268             }
269         }
270     }
271
272     fn value_str(&self) -> Option<InternedString> {
273         match **self {
274             NameValue(_, ref v) => Some(token::intern_and_get_ident(*v)),
275             _ => None,
276         }
277     }
278     fn meta_item_list<'a>(&'a self) -> Option<&'a [@ast::MetaItem]> { None }
279     fn name_str_pair(&self) -> Option<(InternedString, InternedString)> {
280         None
281     }
282 }
283
284 #[deriving(Clone, Encodable, Decodable)]
285 pub struct TyParam {
286     name: ~str,
287     id: ast::NodeId,
288     bounds: Vec<TyParamBound> }
289
290 impl Clean<TyParam> for ast::TyParam {
291     fn clean(&self) -> TyParam {
292         TyParam {
293             name: self.ident.clean(),
294             id: self.id,
295             bounds: self.bounds.clean().move_iter().collect(),
296         }
297     }
298 }
299
300 #[deriving(Clone, Encodable, Decodable)]
301 pub enum TyParamBound {
302     RegionBound,
303     TraitBound(Type)
304 }
305
306 impl Clean<TyParamBound> for ast::TyParamBound {
307     fn clean(&self) -> TyParamBound {
308         match *self {
309             ast::RegionTyParamBound => RegionBound,
310             ast::TraitTyParamBound(ref t) => TraitBound(t.clean()),
311         }
312     }
313 }
314
315 #[deriving(Clone, Encodable, Decodable)]
316 pub struct Lifetime(~str);
317
318 impl Lifetime {
319     pub fn get_ref<'a>(&'a self) -> &'a str {
320         let Lifetime(ref s) = *self;
321         let s: &'a str = *s;
322         return s;
323     }
324 }
325
326 impl Clean<Lifetime> for ast::Lifetime {
327     fn clean(&self) -> Lifetime {
328         Lifetime(token::get_name(self.name).get().to_owned())
329     }
330 }
331
332 // maybe use a Generic enum and use ~[Generic]?
333 #[deriving(Clone, Encodable, Decodable)]
334 pub struct Generics {
335     lifetimes: Vec<Lifetime> ,
336     type_params: Vec<TyParam> }
337
338 impl Clean<Generics> for ast::Generics {
339     fn clean(&self) -> Generics {
340         Generics {
341             lifetimes: self.lifetimes.clean().move_iter().collect(),
342             type_params: self.ty_params.clean().move_iter().collect(),
343         }
344     }
345 }
346
347 #[deriving(Clone, Encodable, Decodable)]
348 pub struct Method {
349     generics: Generics,
350     self_: SelfTy,
351     purity: ast::Purity,
352     decl: FnDecl,
353 }
354
355 impl Clean<Item> for ast::Method {
356     fn clean(&self) -> Item {
357         let inputs = match self.explicit_self.node {
358             ast::SelfStatic => self.decl.inputs.as_slice(),
359             _ => self.decl.inputs.slice_from(1)
360         };
361         let decl = FnDecl {
362             inputs: Arguments {
363                 values: inputs.iter().map(|x| x.clean()).collect(),
364             },
365             output: (self.decl.output.clean()),
366             cf: self.decl.cf.clean(),
367             attrs: Vec::new()
368         };
369         Item {
370             name: Some(self.ident.clean()),
371             attrs: self.attrs.clean().move_iter().collect(),
372             source: self.span.clean(),
373             id: self.id.clone(),
374             visibility: self.vis.clean(),
375             inner: MethodItem(Method {
376                 generics: self.generics.clean(),
377                 self_: self.explicit_self.clean(),
378                 purity: self.purity.clone(),
379                 decl: decl,
380             }),
381         }
382     }
383 }
384
385 #[deriving(Clone, Encodable, Decodable)]
386 pub struct TyMethod {
387     purity: ast::Purity,
388     decl: FnDecl,
389     generics: Generics,
390     self_: SelfTy,
391 }
392
393 impl Clean<Item> for ast::TypeMethod {
394     fn clean(&self) -> Item {
395         let inputs = match self.explicit_self.node {
396             ast::SelfStatic => self.decl.inputs.as_slice(),
397             _ => self.decl.inputs.slice_from(1)
398         };
399         let decl = FnDecl {
400             inputs: Arguments {
401                 values: inputs.iter().map(|x| x.clean()).collect(),
402             },
403             output: (self.decl.output.clean()),
404             cf: self.decl.cf.clean(),
405             attrs: Vec::new()
406         };
407         Item {
408             name: Some(self.ident.clean()),
409             attrs: self.attrs.clean().move_iter().collect(),
410             source: self.span.clean(),
411             id: self.id,
412             visibility: None,
413             inner: TyMethodItem(TyMethod {
414                 purity: self.purity.clone(),
415                 decl: decl,
416                 self_: self.explicit_self.clean(),
417                 generics: self.generics.clean(),
418             }),
419         }
420     }
421 }
422
423 #[deriving(Clone, Encodable, Decodable)]
424 pub enum SelfTy {
425     SelfStatic,
426     SelfValue,
427     SelfBorrowed(Option<Lifetime>, Mutability),
428     SelfOwned,
429 }
430
431 impl Clean<SelfTy> for ast::ExplicitSelf {
432     fn clean(&self) -> SelfTy {
433         match self.node {
434             ast::SelfStatic => SelfStatic,
435             ast::SelfValue => SelfValue,
436             ast::SelfUniq => SelfOwned,
437             ast::SelfRegion(lt, mt) => SelfBorrowed(lt.clean(), mt.clean()),
438         }
439     }
440 }
441
442 #[deriving(Clone, Encodable, Decodable)]
443 pub struct Function {
444     decl: FnDecl,
445     generics: Generics,
446     purity: ast::Purity,
447 }
448
449 impl Clean<Item> for doctree::Function {
450     fn clean(&self) -> Item {
451         Item {
452             name: Some(self.name.clean()),
453             attrs: self.attrs.clean(),
454             source: self.where.clean(),
455             visibility: self.vis.clean(),
456             id: self.id,
457             inner: FunctionItem(Function {
458                 decl: self.decl.clean(),
459                 generics: self.generics.clean(),
460                 purity: self.purity,
461             }),
462         }
463     }
464 }
465
466 #[deriving(Clone, Encodable, Decodable)]
467 pub struct ClosureDecl {
468     sigil: ast::Sigil,
469     region: Option<Lifetime>,
470     lifetimes: Vec<Lifetime> ,
471     decl: FnDecl,
472     onceness: ast::Onceness,
473     purity: ast::Purity,
474     bounds: Vec<TyParamBound> }
475
476 impl Clean<ClosureDecl> for ast::ClosureTy {
477     fn clean(&self) -> ClosureDecl {
478         ClosureDecl {
479             sigil: self.sigil,
480             region: self.region.clean(),
481             lifetimes: self.lifetimes.clean().move_iter().collect(),
482             decl: self.decl.clean(),
483             onceness: self.onceness,
484             purity: self.purity,
485             bounds: match self.bounds {
486                 Some(ref x) => x.clean().move_iter().collect(),
487                 None        => Vec::new()
488             },
489         }
490     }
491 }
492
493 #[deriving(Clone, Encodable, Decodable)]
494 pub struct FnDecl {
495     inputs: Arguments,
496     output: Type,
497     cf: RetStyle,
498     attrs: Vec<Attribute> }
499
500 #[deriving(Clone, Encodable, Decodable)]
501 pub struct Arguments {
502     values: Vec<Argument> ,
503 }
504
505 impl Clean<FnDecl> for ast::FnDecl {
506     fn clean(&self) -> FnDecl {
507         FnDecl {
508             inputs: Arguments {
509                 values: self.inputs.iter().map(|x| x.clean()).collect(),
510             },
511             output: (self.output.clean()),
512             cf: self.cf.clean(),
513             attrs: Vec::new()
514         }
515     }
516 }
517
518 #[deriving(Clone, Encodable, Decodable)]
519 pub struct Argument {
520     type_: Type,
521     name: ~str,
522     id: ast::NodeId
523 }
524
525 impl Clean<Argument> for ast::Arg {
526     fn clean(&self) -> Argument {
527         Argument {
528             name: name_from_pat(self.pat),
529             type_: (self.ty.clean()),
530             id: self.id
531         }
532     }
533 }
534
535 #[deriving(Clone, Encodable, Decodable)]
536 pub enum RetStyle {
537     NoReturn,
538     Return
539 }
540
541 impl Clean<RetStyle> for ast::RetStyle {
542     fn clean(&self) -> RetStyle {
543         match *self {
544             ast::Return => Return,
545             ast::NoReturn => NoReturn
546         }
547     }
548 }
549
550 #[deriving(Clone, Encodable, Decodable)]
551 pub struct Trait {
552     methods: Vec<TraitMethod> ,
553     generics: Generics,
554     parents: Vec<Type> ,
555 }
556
557 impl Clean<Item> for doctree::Trait {
558     fn clean(&self) -> Item {
559         Item {
560             name: Some(self.name.clean()),
561             attrs: self.attrs.clean(),
562             source: self.where.clean(),
563             id: self.id,
564             visibility: self.vis.clean(),
565             inner: TraitItem(Trait {
566                 methods: self.methods.clean(),
567                 generics: self.generics.clean(),
568                 parents: self.parents.clean(),
569             }),
570         }
571     }
572 }
573
574 impl Clean<Type> for ast::TraitRef {
575     fn clean(&self) -> Type {
576         resolve_type(self.path.clean(), None, self.ref_id)
577     }
578 }
579
580 #[deriving(Clone, Encodable, Decodable)]
581 pub enum TraitMethod {
582     Required(Item),
583     Provided(Item),
584 }
585
586 impl TraitMethod {
587     pub fn is_req(&self) -> bool {
588         match self {
589             &Required(..) => true,
590             _ => false,
591         }
592     }
593     pub fn is_def(&self) -> bool {
594         match self {
595             &Provided(..) => true,
596             _ => false,
597         }
598     }
599     pub fn item<'a>(&'a self) -> &'a Item {
600         match *self {
601             Required(ref item) => item,
602             Provided(ref item) => item,
603         }
604     }
605 }
606
607 impl Clean<TraitMethod> for ast::TraitMethod {
608     fn clean(&self) -> TraitMethod {
609         match self {
610             &ast::Required(ref t) => Required(t.clean()),
611             &ast::Provided(ref t) => Provided(t.clean()),
612         }
613     }
614 }
615
616 /// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
617 /// type out of the AST/ty::ctxt given one of these, if more information is needed. Most importantly
618 /// it does not preserve mutability or boxes.
619 #[deriving(Clone, Encodable, Decodable)]
620 pub enum Type {
621     /// structs/enums/traits (anything that'd be an ast::TyPath)
622     ResolvedPath {
623         path: Path,
624         typarams: Option<Vec<TyParamBound> >,
625         id: ast::NodeId,
626     },
627     /// Same as above, but only external variants
628     ExternalPath {
629         path: Path,
630         typarams: Option<Vec<TyParamBound> >,
631         fqn: Vec<~str> ,
632         kind: TypeKind,
633         krate: ast::CrateNum,
634     },
635     // I have no idea how to usefully use this.
636     TyParamBinder(ast::NodeId),
637     /// For parameterized types, so the consumer of the JSON don't go looking
638     /// for types which don't exist anywhere.
639     Generic(ast::NodeId),
640     /// For references to self
641     Self(ast::NodeId),
642     /// Primitives are just the fixed-size numeric types (plus int/uint/float), and char.
643     Primitive(ast::PrimTy),
644     Closure(~ClosureDecl),
645     /// extern "ABI" fn
646     BareFunction(~BareFunctionDecl),
647     Tuple(Vec<Type> ),
648     Vector(~Type),
649     FixedVector(~Type, ~str),
650     String,
651     Bool,
652     /// aka TyNil
653     Unit,
654     /// aka TyBot
655     Bottom,
656     Unique(~Type),
657     Managed(~Type),
658     RawPointer(Mutability, ~Type),
659     BorrowedRef { lifetime: Option<Lifetime>, mutability: Mutability, type_: ~Type},
660     // region, raw, other boxes, mutable
661 }
662
663 #[deriving(Clone, Encodable, Decodable)]
664 pub enum TypeKind {
665     TypeStruct,
666     TypeEnum,
667     TypeTrait,
668     TypeFunction,
669 }
670
671 impl Clean<Type> for ast::Ty {
672     fn clean(&self) -> Type {
673         use syntax::ast::*;
674         debug!("cleaning type `{:?}`", self);
675         let codemap = local_data::get(super::ctxtkey, |x| *x.unwrap()).sess().codemap();
676         debug!("span corresponds to `{}`", codemap.span_to_str(self.span));
677         match self.node {
678             TyNil => Unit,
679             TyPtr(ref m) => RawPointer(m.mutbl.clean(), ~m.ty.clean()),
680             TyRptr(ref l, ref m) =>
681                 BorrowedRef {lifetime: l.clean(), mutability: m.mutbl.clean(),
682                              type_: ~m.ty.clean()},
683             TyBox(ty) => Managed(~ty.clean()),
684             TyUniq(ty) => Unique(~ty.clean()),
685             TyVec(ty) => Vector(~ty.clean()),
686             TyFixedLengthVec(ty, ref e) => FixedVector(~ty.clean(),
687                                                        e.span.to_src()),
688             TyTup(ref tys) => Tuple(tys.iter().map(|x| x.clean()).collect()),
689             TyPath(ref p, ref tpbs, id) => {
690                 resolve_type(p.clean(),
691                              tpbs.clean().map(|x| x.move_iter().collect()),
692                              id)
693             }
694             TyClosure(ref c) => Closure(~c.clean()),
695             TyBareFn(ref barefn) => BareFunction(~barefn.clean()),
696             TyBot => Bottom,
697             ref x => fail!("Unimplemented type {:?}", x),
698         }
699     }
700 }
701
702 #[deriving(Clone, Encodable, Decodable)]
703 pub struct StructField {
704     type_: Type,
705 }
706
707 impl Clean<Item> for ast::StructField {
708     fn clean(&self) -> Item {
709         let (name, vis) = match self.node.kind {
710             ast::NamedField(id, vis) => (Some(id), Some(vis)),
711             _ => (None, None)
712         };
713         Item {
714             name: name.clean(),
715             attrs: self.node.attrs.clean().move_iter().collect(),
716             source: self.span.clean(),
717             visibility: vis,
718             id: self.node.id,
719             inner: StructFieldItem(StructField {
720                 type_: self.node.ty.clean(),
721             }),
722         }
723     }
724 }
725
726 pub type Visibility = ast::Visibility;
727
728 impl Clean<Option<Visibility>> for ast::Visibility {
729     fn clean(&self) -> Option<Visibility> {
730         Some(*self)
731     }
732 }
733
734 #[deriving(Clone, Encodable, Decodable)]
735 pub struct Struct {
736     struct_type: doctree::StructType,
737     generics: Generics,
738     fields: Vec<Item> ,
739     fields_stripped: bool,
740 }
741
742 impl Clean<Item> for doctree::Struct {
743     fn clean(&self) -> Item {
744         Item {
745             name: Some(self.name.clean()),
746             attrs: self.attrs.clean(),
747             source: self.where.clean(),
748             id: self.id,
749             visibility: self.vis.clean(),
750             inner: StructItem(Struct {
751                 struct_type: self.struct_type,
752                 generics: self.generics.clean(),
753                 fields: self.fields.clean(),
754                 fields_stripped: false,
755             }),
756         }
757     }
758 }
759
760 /// This is a more limited form of the standard Struct, different in that
761 /// it lacks the things most items have (name, id, parameterization). Found
762 /// only as a variant in an enum.
763 #[deriving(Clone, Encodable, Decodable)]
764 pub struct VariantStruct {
765     struct_type: doctree::StructType,
766     fields: Vec<Item> ,
767     fields_stripped: bool,
768 }
769
770 impl Clean<VariantStruct> for syntax::ast::StructDef {
771     fn clean(&self) -> VariantStruct {
772         VariantStruct {
773             struct_type: doctree::struct_type_from_def(self),
774             fields: self.fields.clean().move_iter().collect(),
775             fields_stripped: false,
776         }
777     }
778 }
779
780 #[deriving(Clone, Encodable, Decodable)]
781 pub struct Enum {
782     variants: Vec<Item> ,
783     generics: Generics,
784     variants_stripped: bool,
785 }
786
787 impl Clean<Item> for doctree::Enum {
788     fn clean(&self) -> Item {
789         Item {
790             name: Some(self.name.clean()),
791             attrs: self.attrs.clean(),
792             source: self.where.clean(),
793             id: self.id,
794             visibility: self.vis.clean(),
795             inner: EnumItem(Enum {
796                 variants: self.variants.clean(),
797                 generics: self.generics.clean(),
798                 variants_stripped: false,
799             }),
800         }
801     }
802 }
803
804 #[deriving(Clone, Encodable, Decodable)]
805 pub struct Variant {
806     kind: VariantKind,
807 }
808
809 impl Clean<Item> for doctree::Variant {
810     fn clean(&self) -> Item {
811         Item {
812             name: Some(self.name.clean()),
813             attrs: self.attrs.clean(),
814             source: self.where.clean(),
815             visibility: self.vis.clean(),
816             id: self.id,
817             inner: VariantItem(Variant {
818                 kind: self.kind.clean(),
819             }),
820         }
821     }
822 }
823
824 #[deriving(Clone, Encodable, Decodable)]
825 pub enum VariantKind {
826     CLikeVariant,
827     TupleVariant(Vec<Type> ),
828     StructVariant(VariantStruct),
829 }
830
831 impl Clean<VariantKind> for ast::VariantKind {
832     fn clean(&self) -> VariantKind {
833         match self {
834             &ast::TupleVariantKind(ref args) => {
835                 if args.len() == 0 {
836                     CLikeVariant
837                 } else {
838                     TupleVariant(args.iter().map(|x| x.ty.clean()).collect())
839                 }
840             },
841             &ast::StructVariantKind(ref sd) => StructVariant(sd.clean()),
842         }
843     }
844 }
845
846 #[deriving(Clone, Encodable, Decodable)]
847 pub struct Span {
848     filename: ~str,
849     loline: uint,
850     locol: uint,
851     hiline: uint,
852     hicol: uint,
853 }
854
855 impl Clean<Span> for syntax::codemap::Span {
856     fn clean(&self) -> Span {
857         let cm = local_data::get(super::ctxtkey, |x| *x.unwrap()).sess().codemap();
858         let filename = cm.span_to_filename(*self);
859         let lo = cm.lookup_char_pos(self.lo);
860         let hi = cm.lookup_char_pos(self.hi);
861         Span {
862             filename: filename.to_owned(),
863             loline: lo.line,
864             locol: lo.col.to_uint(),
865             hiline: hi.line,
866             hicol: hi.col.to_uint(),
867         }
868     }
869 }
870
871 #[deriving(Clone, Encodable, Decodable)]
872 pub struct Path {
873     global: bool,
874     segments: Vec<PathSegment> ,
875 }
876
877 impl Clean<Path> for ast::Path {
878     fn clean(&self) -> Path {
879         Path {
880             global: self.global,
881             segments: self.segments.clean().move_iter().collect(),
882         }
883     }
884 }
885
886 #[deriving(Clone, Encodable, Decodable)]
887 pub struct PathSegment {
888     name: ~str,
889     lifetimes: Vec<Lifetime> ,
890     types: Vec<Type> ,
891 }
892
893 impl Clean<PathSegment> for ast::PathSegment {
894     fn clean(&self) -> PathSegment {
895         PathSegment {
896             name: self.identifier.clean(),
897             lifetimes: self.lifetimes.clean().move_iter().collect(),
898             types: self.types.clean().move_iter().collect()
899         }
900     }
901 }
902
903 fn path_to_str(p: &ast::Path) -> ~str {
904     use syntax::parse::token;
905
906     let mut s = ~"";
907     let mut first = true;
908     for i in p.segments.iter().map(|x| token::get_ident(x.identifier)) {
909         if !first || p.global {
910             s.push_str("::");
911         } else {
912             first = false;
913         }
914         s.push_str(i.get());
915     }
916     s
917 }
918
919 impl Clean<~str> for ast::Ident {
920     fn clean(&self) -> ~str {
921         token::get_ident(*self).get().to_owned()
922     }
923 }
924
925 #[deriving(Clone, Encodable, Decodable)]
926 pub struct Typedef {
927     type_: Type,
928     generics: Generics,
929 }
930
931 impl Clean<Item> for doctree::Typedef {
932     fn clean(&self) -> Item {
933         Item {
934             name: Some(self.name.clean()),
935             attrs: self.attrs.clean(),
936             source: self.where.clean(),
937             id: self.id.clone(),
938             visibility: self.vis.clean(),
939             inner: TypedefItem(Typedef {
940                 type_: self.ty.clean(),
941                 generics: self.gen.clean(),
942             }),
943         }
944     }
945 }
946
947 #[deriving(Clone, Encodable, Decodable)]
948 pub struct BareFunctionDecl {
949     purity: ast::Purity,
950     generics: Generics,
951     decl: FnDecl,
952     abi: ~str
953 }
954
955 impl Clean<BareFunctionDecl> for ast::BareFnTy {
956     fn clean(&self) -> BareFunctionDecl {
957         BareFunctionDecl {
958             purity: self.purity,
959             generics: Generics {
960                 lifetimes: self.lifetimes.clean().move_iter().collect(),
961                 type_params: Vec::new(),
962             },
963             decl: self.decl.clean(),
964             abi: self.abis.to_str(),
965         }
966     }
967 }
968
969 #[deriving(Clone, Encodable, Decodable)]
970 pub struct Static {
971     type_: Type,
972     mutability: Mutability,
973     /// It's useful to have the value of a static documented, but I have no
974     /// desire to represent expressions (that'd basically be all of the AST,
975     /// which is huge!). So, have a string.
976     expr: ~str,
977 }
978
979 impl Clean<Item> for doctree::Static {
980     fn clean(&self) -> Item {
981         debug!("claning static {}: {:?}", self.name.clean(), self);
982         Item {
983             name: Some(self.name.clean()),
984             attrs: self.attrs.clean(),
985             source: self.where.clean(),
986             id: self.id,
987             visibility: self.vis.clean(),
988             inner: StaticItem(Static {
989                 type_: self.type_.clean(),
990                 mutability: self.mutability.clean(),
991                 expr: self.expr.span.to_src(),
992             }),
993         }
994     }
995 }
996
997 #[deriving(Show, Clone, Encodable, Decodable)]
998 pub enum Mutability {
999     Mutable,
1000     Immutable,
1001 }
1002
1003 impl Clean<Mutability> for ast::Mutability {
1004     fn clean(&self) -> Mutability {
1005         match self {
1006             &ast::MutMutable => Mutable,
1007             &ast::MutImmutable => Immutable,
1008         }
1009     }
1010 }
1011
1012 #[deriving(Clone, Encodable, Decodable)]
1013 pub struct Impl {
1014     generics: Generics,
1015     trait_: Option<Type>,
1016     for_: Type,
1017     methods: Vec<Item> ,
1018 }
1019
1020 impl Clean<Item> for doctree::Impl {
1021     fn clean(&self) -> Item {
1022         Item {
1023             name: None,
1024             attrs: self.attrs.clean(),
1025             source: self.where.clean(),
1026             id: self.id,
1027             visibility: self.vis.clean(),
1028             inner: ImplItem(Impl {
1029                 generics: self.generics.clean(),
1030                 trait_: self.trait_.clean(),
1031                 for_: self.for_.clean(),
1032                 methods: self.methods.clean(),
1033             }),
1034         }
1035     }
1036 }
1037
1038 #[deriving(Clone, Encodable, Decodable)]
1039 pub struct ViewItem {
1040     inner: ViewItemInner
1041 }
1042
1043 impl Clean<Item> for ast::ViewItem {
1044     fn clean(&self) -> Item {
1045         Item {
1046             name: None,
1047             attrs: self.attrs.clean().move_iter().collect(),
1048             source: self.span.clean(),
1049             id: 0,
1050             visibility: self.vis.clean(),
1051             inner: ViewItemItem(ViewItem {
1052                 inner: self.node.clean()
1053             }),
1054         }
1055     }
1056 }
1057
1058 #[deriving(Clone, Encodable, Decodable)]
1059 pub enum ViewItemInner {
1060     ExternCrate(~str, Option<~str>, ast::NodeId),
1061     Import(Vec<ViewPath>)
1062 }
1063
1064 impl Clean<ViewItemInner> for ast::ViewItem_ {
1065     fn clean(&self) -> ViewItemInner {
1066         match self {
1067             &ast::ViewItemExternCrate(ref i, ref p, ref id) => {
1068                 let string = match *p {
1069                     None => None,
1070                     Some((ref x, _)) => Some(x.get().to_owned()),
1071                 };
1072                 ExternCrate(i.clean(), string, *id)
1073             }
1074             &ast::ViewItemUse(ref vp) => {
1075                 Import(vp.clean().move_iter().collect())
1076             }
1077         }
1078     }
1079 }
1080
1081 #[deriving(Clone, Encodable, Decodable)]
1082 pub enum ViewPath {
1083     // use str = source;
1084     SimpleImport(~str, ImportSource),
1085     // use source::*;
1086     GlobImport(ImportSource),
1087     // use source::{a, b, c};
1088     ImportList(ImportSource, Vec<ViewListIdent> ),
1089 }
1090
1091 #[deriving(Clone, Encodable, Decodable)]
1092 pub struct ImportSource {
1093     path: Path,
1094     did: Option<ast::DefId>,
1095 }
1096
1097 impl Clean<ViewPath> for ast::ViewPath {
1098     fn clean(&self) -> ViewPath {
1099         match self.node {
1100             ast::ViewPathSimple(ref i, ref p, id) =>
1101                 SimpleImport(i.clean(), resolve_use_source(p.clean(), id)),
1102             ast::ViewPathGlob(ref p, id) =>
1103                 GlobImport(resolve_use_source(p.clean(), id)),
1104             ast::ViewPathList(ref p, ref pl, id) => {
1105                 ImportList(resolve_use_source(p.clean(), id),
1106                            pl.clean().move_iter().collect())
1107             }
1108         }
1109     }
1110 }
1111
1112 #[deriving(Clone, Encodable, Decodable)]
1113 pub struct ViewListIdent {
1114     name: ~str,
1115     source: Option<ast::DefId>,
1116 }
1117
1118 impl Clean<ViewListIdent> for ast::PathListIdent {
1119     fn clean(&self) -> ViewListIdent {
1120         ViewListIdent {
1121             name: self.node.name.clean(),
1122             source: resolve_def(self.node.id),
1123         }
1124     }
1125 }
1126
1127 impl Clean<Vec<Item>> for ast::ForeignMod {
1128     fn clean(&self) -> Vec<Item> {
1129         self.items.clean()
1130     }
1131 }
1132
1133 impl Clean<Item> for ast::ForeignItem {
1134     fn clean(&self) -> Item {
1135         let inner = match self.node {
1136             ast::ForeignItemFn(ref decl, ref generics) => {
1137                 ForeignFunctionItem(Function {
1138                     decl: decl.clean(),
1139                     generics: generics.clean(),
1140                     purity: ast::ExternFn,
1141                 })
1142             }
1143             ast::ForeignItemStatic(ref ty, mutbl) => {
1144                 ForeignStaticItem(Static {
1145                     type_: ty.clean(),
1146                     mutability: if mutbl {Mutable} else {Immutable},
1147                     expr: ~"",
1148                 })
1149             }
1150         };
1151         Item {
1152             name: Some(self.ident.clean()),
1153             attrs: self.attrs.clean().move_iter().collect(),
1154             source: self.span.clean(),
1155             id: self.id,
1156             visibility: self.vis.clean(),
1157             inner: inner,
1158         }
1159     }
1160 }
1161
1162 // Utilities
1163
1164 trait ToSource {
1165     fn to_src(&self) -> ~str;
1166 }
1167
1168 impl ToSource for syntax::codemap::Span {
1169     fn to_src(&self) -> ~str {
1170         debug!("converting span {:?} to snippet", self.clean());
1171         let cm = local_data::get(super::ctxtkey, |x| x.unwrap().clone()).sess().codemap().clone();
1172         let sn = match cm.span_to_snippet(*self) {
1173             Some(x) => x,
1174             None    => ~""
1175         };
1176         debug!("got snippet {}", sn);
1177         sn
1178     }
1179 }
1180
1181 fn lit_to_str(lit: &ast::Lit) -> ~str {
1182     match lit.node {
1183         ast::LitStr(ref st, _) => st.get().to_owned(),
1184         ast::LitBinary(ref data) => format!("{:?}", data.as_slice()),
1185         ast::LitChar(c) => ~"'" + std::char::from_u32(c).unwrap().to_str() + "'",
1186         ast::LitInt(i, _t) => i.to_str(),
1187         ast::LitUint(u, _t) => u.to_str(),
1188         ast::LitIntUnsuffixed(i) => i.to_str(),
1189         ast::LitFloat(ref f, _t) => f.get().to_str(),
1190         ast::LitFloatUnsuffixed(ref f) => f.get().to_str(),
1191         ast::LitBool(b) => b.to_str(),
1192         ast::LitNil => ~"",
1193     }
1194 }
1195
1196 fn name_from_pat(p: &ast::Pat) -> ~str {
1197     use syntax::ast::*;
1198     debug!("Trying to get a name from pattern: {:?}", p);
1199
1200     match p.node {
1201         PatWild => ~"_",
1202         PatWildMulti => ~"..",
1203         PatIdent(_, ref p, _) => path_to_str(p),
1204         PatEnum(ref p, _) => path_to_str(p),
1205         PatStruct(..) => fail!("tried to get argument name from pat_struct, \
1206                                 which is not allowed in function arguments"),
1207         PatTup(..) => ~"(tuple arg NYI)",
1208         PatUniq(p) => name_from_pat(p),
1209         PatRegion(p) => name_from_pat(p),
1210         PatLit(..) => {
1211             warn!("tried to get argument name from PatLit, \
1212                   which is silly in function arguments");
1213             ~"()"
1214         },
1215         PatRange(..) => fail!("tried to get argument name from PatRange, \
1216                               which is not allowed in function arguments"),
1217         PatVec(..) => fail!("tried to get argument name from pat_vec, \
1218                              which is not allowed in function arguments")
1219     }
1220 }
1221
1222 /// Given a Type, resolve it using the def_map
1223 fn resolve_type(path: Path, tpbs: Option<Vec<TyParamBound> >,
1224                 id: ast::NodeId) -> Type {
1225     let cx = local_data::get(super::ctxtkey, |x| *x.unwrap());
1226     let tycx = match cx.maybe_typed {
1227         core::Typed(ref tycx) => tycx,
1228         // If we're extracting tests, this return value doesn't matter.
1229         core::NotTyped(_) => return Bool
1230     };
1231     debug!("searching for {:?} in defmap", id);
1232     let d = match tycx.def_map.borrow().find(&id) {
1233         Some(&k) => k,
1234         None => {
1235             debug!("could not find {:?} in defmap (`{}`)", id, tycx.map.node_to_str(id));
1236             fail!("Unexpected failure: unresolved id not in defmap (this is a bug!)")
1237         }
1238     };
1239
1240     let (def_id, kind) = match d {
1241         ast::DefFn(i, _) => (i, TypeFunction),
1242         ast::DefSelfTy(i) => return Self(i),
1243         ast::DefTy(i) => (i, TypeEnum),
1244         ast::DefTrait(i) => {
1245             debug!("saw DefTrait in def_to_id");
1246             (i, TypeTrait)
1247         },
1248         ast::DefPrimTy(p) => match p {
1249             ast::TyStr => return String,
1250             ast::TyBool => return Bool,
1251             _ => return Primitive(p)
1252         },
1253         ast::DefTyParam(i, _) => return Generic(i.node),
1254         ast::DefStruct(i) => (i, TypeStruct),
1255         ast::DefTyParamBinder(i) => {
1256             debug!("found a typaram_binder, what is it? {}", i);
1257             return TyParamBinder(i);
1258         },
1259         x => fail!("resolved type maps to a weird def {:?}", x),
1260     };
1261     if ast_util::is_local(def_id) {
1262         ResolvedPath{ path: path, typarams: tpbs, id: def_id.node }
1263     } else {
1264         let fqn = csearch::get_item_path(tycx, def_id);
1265         let fqn = fqn.move_iter().map(|i| i.to_str()).collect();
1266         ExternalPath {
1267             path: path,
1268             typarams: tpbs,
1269             fqn: fqn,
1270             kind: kind,
1271             krate: def_id.krate,
1272         }
1273     }
1274 }
1275
1276 fn resolve_use_source(path: Path, id: ast::NodeId) -> ImportSource {
1277     ImportSource {
1278         path: path,
1279         did: resolve_def(id),
1280     }
1281 }
1282
1283 fn resolve_def(id: ast::NodeId) -> Option<ast::DefId> {
1284     let cx = local_data::get(super::ctxtkey, |x| *x.unwrap());
1285     match cx.maybe_typed {
1286         core::Typed(ref tcx) => {
1287             tcx.def_map.borrow().find(&id).map(|&d| ast_util::def_id_of_def(d))
1288         }
1289         core::NotTyped(_) => None
1290     }
1291 }
1292
1293 #[deriving(Clone, Encodable, Decodable)]
1294 pub struct Macro {
1295     source: ~str,
1296 }
1297
1298 impl Clean<Item> for doctree::Macro {
1299     fn clean(&self) -> Item {
1300         Item {
1301             name: Some(self.name.clean()),
1302             attrs: self.attrs.clean(),
1303             source: self.where.clean(),
1304             visibility: ast::Public.clean(),
1305             id: self.id,
1306             inner: MacroItem(Macro {
1307                 source: self.where.to_src(),
1308             }),
1309         }
1310     }
1311 }