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