]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/stability_summary.rs
doc: remove incomplete sentence
[rust.git] / src / librustdoc / stability_summary.rs
1 // Copyright 2014 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 crawls a `clean::Crate` and produces a summarization of the
12 //! stability levels within the crate. The summary contains the module
13 //! hierarchy, with item counts for every stability level per module. A parent
14 //! module's count includes its children's.
15
16 use std::cmp::Ordering;
17 use std::num::Zero;
18 use std::ops::Add;
19
20 use syntax::attr::{Deprecated, Experimental, Unstable, Stable, Frozen, Locked};
21 use syntax::ast::Public;
22
23 use clean::{Crate, Item, ModuleItem, Module, EnumItem, Enum};
24 use clean::{ImplItem, Impl, Trait, TraitItem, TraitMethod, ProvidedMethod, RequiredMethod};
25 use clean::{TypeTraitItem, ViewItemItem, PrimitiveItem, Stability};
26
27 use html::render::cache;
28
29 #[deriving(Zero, RustcEncodable, RustcDecodable, PartialEq, Eq)]
30 /// The counts for each stability level.
31 #[deriving(Copy)]
32 pub struct Counts {
33     pub deprecated: uint,
34     pub experimental: uint,
35     pub unstable: uint,
36     pub stable: uint,
37     pub frozen: uint,
38     pub locked: uint,
39
40     /// No stability level, inherited or otherwise.
41     pub unmarked: uint,
42 }
43
44 impl Add for Counts {
45     type Output = Counts;
46
47     fn add(self, other: Counts) -> Counts {
48         Counts {
49             deprecated:   self.deprecated   + other.deprecated,
50             experimental: self.experimental + other.experimental,
51             unstable:     self.unstable     + other.unstable,
52             stable:       self.stable       + other.stable,
53             frozen:       self.frozen       + other.frozen,
54             locked:       self.locked       + other.locked,
55             unmarked:     self.unmarked     + other.unmarked,
56         }
57     }
58 }
59
60 impl Counts {
61     fn zero() -> Counts {
62         Counts {
63             deprecated:   0,
64             experimental: 0,
65             unstable:     0,
66             stable:       0,
67             frozen:       0,
68             locked:       0,
69             unmarked:     0,
70         }
71     }
72
73     pub fn total(&self) -> uint {
74         self.deprecated + self.experimental + self.unstable + self.stable +
75             self.frozen + self.locked + self.unmarked
76     }
77 }
78
79 #[deriving(RustcEncodable, RustcDecodable, PartialEq, Eq)]
80 /// A summarized module, which includes total counts and summarized children
81 /// modules.
82 pub struct ModuleSummary {
83     pub name: String,
84     pub counts: Counts,
85     pub submodules: Vec<ModuleSummary>,
86 }
87
88 impl PartialOrd for ModuleSummary {
89     fn partial_cmp(&self, other: &ModuleSummary) -> Option<Ordering> {
90         self.name.partial_cmp(&other.name)
91     }
92 }
93
94 impl Ord for ModuleSummary {
95     fn cmp(&self, other: &ModuleSummary) -> Ordering {
96         self.name.cmp(&other.name)
97     }
98 }
99
100 // is the item considered publically visible?
101 fn visible(item: &Item) -> bool {
102     match item.inner {
103         ImplItem(_) => true,
104         _ => item.visibility == Some(Public)
105     }
106 }
107
108 fn count_stability(stab: Option<&Stability>) -> Counts {
109     match stab {
110         None             => Counts { unmarked: 1,     .. Counts::zero() },
111         Some(ref stab) => match stab.level {
112             Deprecated   => Counts { deprecated: 1,   .. Counts::zero() },
113             Experimental => Counts { experimental: 1, .. Counts::zero() },
114             Unstable     => Counts { unstable: 1,     .. Counts::zero() },
115             Stable       => Counts { stable: 1,       .. Counts::zero() },
116             Frozen       => Counts { frozen: 1,       .. Counts::zero() },
117             Locked       => Counts { locked: 1,       .. Counts::zero() },
118         }
119     }
120 }
121
122 fn summarize_methods(item: &Item) -> Counts {
123     match cache().impls.get(&item.def_id) {
124         Some(v) => {
125             v.iter().map(|i| {
126                 let count = count_stability(i.stability.as_ref());
127                 if i.impl_.trait_.is_none() {
128                     count + i.impl_.items.iter()
129                         .map(|ti| summarize_item(ti).0)
130                         .fold(Counts::zero(), |acc, c| acc + c)
131                 } else {
132                     count
133                 }
134             }).fold(Counts::zero(), |acc, c| acc + c)
135         },
136         None => {
137             Counts::zero()
138         },
139     }
140 }
141
142
143 // Produce the summary for an arbitrary item. If the item is a module, include a
144 // module summary. The counts for items with nested items (e.g. modules, traits,
145 // impls) include all children counts.
146 fn summarize_item(item: &Item) -> (Counts, Option<ModuleSummary>) {
147     let item_counts = count_stability(item.stability.as_ref()) + summarize_methods(item);
148
149     // Count this item's children, if any. Note that a trait impl is
150     // considered to have no children.
151     match item.inner {
152         // Require explicit `pub` to be visible
153         ImplItem(Impl { items: ref subitems, trait_: None, .. }) => {
154             let subcounts = subitems.iter().filter(|i| visible(*i))
155                                            .map(summarize_item)
156                                            .map(|s| s.0)
157                                            .fold(Counts::zero(), |acc, x| acc + x);
158             (subcounts, None)
159         }
160         // `pub` automatically
161         EnumItem(Enum { variants: ref subitems, .. }) => {
162             let subcounts = subitems.iter().map(summarize_item)
163                                            .map(|s| s.0)
164                                            .fold(Counts::zero(), |acc, x| acc + x);
165             (item_counts + subcounts, None)
166         }
167         TraitItem(Trait {
168             items: ref trait_items,
169             ..
170         }) => {
171             fn extract_item<'a>(trait_item: &'a TraitMethod) -> &'a Item {
172                 match *trait_item {
173                     ProvidedMethod(ref item) |
174                     RequiredMethod(ref item) |
175                     TypeTraitItem(ref item) => item
176                 }
177             }
178             let subcounts = trait_items.iter()
179                                        .map(extract_item)
180                                        .map(summarize_item)
181                                        .map(|s| s.0)
182                                        .fold(Counts::zero(), |acc, x| acc + x);
183             (item_counts + subcounts, None)
184         }
185         ModuleItem(Module { ref items, .. }) => {
186             let mut counts = item_counts;
187             let mut submodules = Vec::new();
188
189             for (subcounts, submodule) in items.iter().filter(|i| visible(*i))
190                                                       .map(summarize_item) {
191                 counts = counts + subcounts;
192                 submodule.map(|m| submodules.push(m));
193             }
194             submodules.sort();
195
196             (counts, Some(ModuleSummary {
197                 name: item.name.as_ref().map_or("".to_string(), |n| n.clone()),
198                 counts: counts,
199                 submodules: submodules,
200             }))
201         }
202         // no stability information for the following items:
203         ViewItemItem(_) | PrimitiveItem(_) => (Counts::zero(), None),
204         _ => (item_counts, None)
205     }
206 }
207
208 /// Summarizes the stability levels in a crate.
209 pub fn build(krate: &Crate) -> ModuleSummary {
210     match krate.module {
211         None => ModuleSummary {
212             name: krate.name.clone(),
213             counts: Counts::zero(),
214             submodules: Vec::new(),
215         },
216         Some(ref item) => ModuleSummary {
217             name: krate.name.clone(), .. summarize_item(item).1.unwrap()
218         }
219     }
220 }