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.
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.
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.
19 use syntax::attr::{Deprecated, Experimental, Unstable, Stable, Frozen, Locked};
20 use syntax::ast::Public;
22 use clean::{Crate, Item, ModuleItem, Module, EnumItem, Enum};
23 use clean::{ImplItem, Impl, Trait, TraitItem, TraitMethod, ProvidedMethod, RequiredMethod};
24 use clean::{TypeTraitItem, ViewItemItem, PrimitiveItem, Stability};
26 use html::render::cache_key;
28 #[deriving(Zero, Encodable, Decodable, PartialEq, Eq)]
29 /// The counts for each stability level.
32 pub experimental: uint,
38 /// No stability level, inherited or otherwise.
42 impl Add<Counts, Counts> for Counts {
43 fn add(&self, other: &Counts) -> Counts {
45 deprecated: self.deprecated + other.deprecated,
46 experimental: self.experimental + other.experimental,
47 unstable: self.unstable + other.unstable,
48 stable: self.stable + other.stable,
49 frozen: self.frozen + other.frozen,
50 locked: self.locked + other.locked,
51 unmarked: self.unmarked + other.unmarked,
69 pub fn total(&self) -> uint {
70 self.deprecated + self.experimental + self.unstable + self.stable +
71 self.frozen + self.locked + self.unmarked
75 #[deriving(Encodable, Decodable, PartialEq, Eq)]
76 /// A summarized module, which includes total counts and summarized children
78 pub struct ModuleSummary {
81 pub submodules: Vec<ModuleSummary>,
84 impl PartialOrd for ModuleSummary {
85 fn partial_cmp(&self, other: &ModuleSummary) -> Option<Ordering> {
86 self.name.partial_cmp(&other.name)
90 impl Ord for ModuleSummary {
91 fn cmp(&self, other: &ModuleSummary) -> Ordering {
92 self.name.cmp(&other.name)
96 // is the item considered publically visible?
97 fn visible(item: &Item) -> bool {
100 _ => item.visibility == Some(Public)
104 fn count_stability(stab: Option<&Stability>) -> Counts {
106 None => Counts { unmarked: 1, .. Counts::zero() },
107 Some(ref stab) => match stab.level {
108 Deprecated => Counts { deprecated: 1, .. Counts::zero() },
109 Experimental => Counts { experimental: 1, .. Counts::zero() },
110 Unstable => Counts { unstable: 1, .. Counts::zero() },
111 Stable => Counts { stable: 1, .. Counts::zero() },
112 Frozen => Counts { frozen: 1, .. Counts::zero() },
113 Locked => Counts { locked: 1, .. Counts::zero() },
118 fn summarize_methods(item: &Item) -> Counts {
119 match cache_key.get().unwrap().impls.get(&item.def_id) {
122 let count = count_stability(i.stability.as_ref());
123 if i.impl_.trait_.is_none() {
124 count + i.impl_.items.iter()
125 .map(|ti| summarize_item(ti).0)
126 .fold(Counts::zero(), |acc, c| acc + c)
130 }).fold(Counts::zero(), |acc, c| acc + c)
139 // Produce the summary for an arbitrary item. If the item is a module, include a
140 // module summary. The counts for items with nested items (e.g. modules, traits,
141 // impls) include all children counts.
142 fn summarize_item(item: &Item) -> (Counts, Option<ModuleSummary>) {
143 let item_counts = count_stability(item.stability.as_ref()) + summarize_methods(item);
145 // Count this item's children, if any. Note that a trait impl is
146 // considered to have no children.
148 // Require explicit `pub` to be visible
149 ImplItem(Impl { items: ref subitems, trait_: None, .. }) => {
150 let subcounts = subitems.iter().filter(|i| visible(*i))
153 .fold(Counts::zero(), |acc, x| acc + x);
156 // `pub` automatically
157 EnumItem(Enum { variants: ref subitems, .. }) => {
158 let subcounts = subitems.iter().map(summarize_item)
160 .fold(Counts::zero(), |acc, x| acc + x);
161 (item_counts + subcounts, None)
164 items: ref trait_items,
167 fn extract_item<'a>(trait_item: &'a TraitMethod) -> &'a Item {
169 ProvidedMethod(ref item) |
170 RequiredMethod(ref item) |
171 TypeTraitItem(ref item) => item
174 let subcounts = trait_items.iter()
178 .fold(Counts::zero(), |acc, x| acc + x);
179 (item_counts + subcounts, None)
181 ModuleItem(Module { ref items, .. }) => {
182 let mut counts = item_counts;
183 let mut submodules = Vec::new();
185 for (subcounts, submodule) in items.iter().filter(|i| visible(*i))
186 .map(summarize_item) {
187 counts = counts + subcounts;
188 submodule.map(|m| submodules.push(m));
192 (counts, Some(ModuleSummary {
193 name: item.name.as_ref().map_or("".to_string(), |n| n.clone()),
195 submodules: submodules,
198 // no stability information for the following items:
199 ViewItemItem(_) | PrimitiveItem(_) => (Counts::zero(), None),
200 _ => (item_counts, None)
204 /// Summarizes the stability levels in a crate.
205 pub fn build(krate: &Crate) -> ModuleSummary {
207 None => ModuleSummary {
208 name: krate.name.clone(),
209 counts: Counts::zero(),
210 submodules: Vec::new(),
212 Some(ref item) => ModuleSummary {
213 name: krate.name.clone(), .. summarize_item(item).val1().unwrap()