|
1 | 1 | use crate::clean;
|
2 | 2 | use crate::core::DocContext;
|
3 |
| -use crate::html::item_type::ItemType; |
4 | 3 | use crate::fold::{self, DocFolder};
|
5 | 4 | use crate::passes::Pass;
|
6 | 5 |
|
7 | 6 | use syntax::attr;
|
| 7 | +use syntax_pos::FileName; |
8 | 8 |
|
9 | 9 | use std::collections::BTreeMap;
|
10 | 10 | use std::fmt;
|
@@ -75,74 +75,51 @@ impl fmt::Display for ItemCount {
|
75 | 75 |
|
76 | 76 | #[derive(Default)]
|
77 | 77 | struct CoverageCalculator {
|
78 |
| - items: BTreeMap<ItemType, ItemCount>, |
| 78 | + items: BTreeMap<FileName, ItemCount>, |
79 | 79 | }
|
80 | 80 |
|
81 | 81 | impl CoverageCalculator {
|
82 | 82 | fn print_results(&self) {
|
83 |
| - use crate::html::item_type::ItemType::*; |
84 |
| - |
85 | 83 | let mut total = ItemCount::default();
|
86 | 84 |
|
87 |
| - let main_types = [ |
88 |
| - Module, Function, |
89 |
| - Struct, StructField, |
90 |
| - Enum, Variant, |
91 |
| - Union, |
92 |
| - Method, |
93 |
| - Trait, TyMethod, |
94 |
| - AssociatedType, AssociatedConst, |
95 |
| - Macro, |
96 |
| - Static, Constant, |
97 |
| - ForeignType, Existential, |
98 |
| - Typedef, TraitAlias, |
99 |
| - Primitive, Keyword, |
100 |
| - ]; |
101 |
| - |
102 |
| - println!("+-{0:->25}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", ""); |
103 |
| - println!("| {:<25} | {:>10} | {:>10} | {:>10} |", |
104 |
| - "Item Type", "Documented", "Total", "Percentage"); |
105 |
| - println!("+-{0:->25}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", ""); |
106 |
| - |
107 |
| - for item_type in &main_types { |
108 |
| - let count = self.items.get(item_type).cloned().unwrap_or_default(); |
109 |
| - |
110 |
| - if let Some(percentage) = count.percentage() { |
111 |
| - println!("| {:<25} | {:>10} | {:>10} | {:>9.1}% |", |
112 |
| - table_name(item_type), count.with_docs, count.total, percentage); |
| 85 | + fn print_table_line() { |
| 86 | + println!("+-{0:->35}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", ""); |
| 87 | + } |
113 | 88 |
|
114 |
| - total += count; |
115 |
| - } |
| 89 | + fn print_table_record(name: &str, count: ItemCount, percentage: f64) { |
| 90 | + println!("| {:<35} | {:>10} | {:>10} | {:>9.1}% |", |
| 91 | + name, count.with_docs, count.total, percentage); |
116 | 92 | }
|
117 | 93 |
|
118 |
| - println!("+-{0:->25}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", ""); |
| 94 | + print_table_line(); |
| 95 | + println!("| {:<35} | {:>10} | {:>10} | {:>10} |", |
| 96 | + "File", "Documented", "Total", "Percentage"); |
| 97 | + print_table_line(); |
119 | 98 |
|
120 |
| - if let Some(count) = self.items.get(&Impl) { |
| 99 | + for (file, &count) in &self.items { |
121 | 100 | if let Some(percentage) = count.percentage() {
|
122 |
| - if let Some(percentage) = total.percentage() { |
123 |
| - println!("| {:<25} | {:>10} | {:>10} | {:>9.1}% |", |
124 |
| - "Total (non trait impls)", total.with_docs, total.total, percentage); |
| 101 | + let mut name = file.to_string(); |
| 102 | + // if a filename is too long, shorten it so we don't blow out the table |
| 103 | + // FIXME(misdreavus): this needs to count graphemes, and probably also track |
| 104 | + // double-wide characters... |
| 105 | + if name.len() > 35 { |
| 106 | + name = "...".to_string() + &name[name.len()-32..]; |
125 | 107 | }
|
126 | 108 |
|
127 |
| - println!("+-{0:->25}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", ""); |
128 |
| - |
129 |
| - println!("| {:<25} | {:>10} | {:>10} | {:>9.1}% |", |
130 |
| - table_name(&Impl), count.with_docs, count.total, percentage); |
131 |
| - |
132 |
| - println!("+-{0:->25}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", ""); |
| 109 | + print_table_record(&name, count, percentage); |
133 | 110 |
|
134 |
| - total += *count; |
| 111 | + total += count; |
135 | 112 | }
|
136 | 113 | }
|
137 | 114 |
|
138 |
| - println!("| {:<25} | {:>10} | {:>10} | {:>9.1}% |", |
139 |
| - "Total", total.with_docs, total.total, total.percentage().unwrap_or(0.0)); |
140 |
| - println!("+-{0:->25}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", ""); |
| 115 | + print_table_line(); |
| 116 | + print_table_record("Total", total, total.percentage().unwrap_or(0.0)); |
| 117 | + print_table_line(); |
141 | 118 | }
|
142 | 119 | }
|
143 | 120 |
|
144 | 121 | impl fold::DocFolder for CoverageCalculator {
|
145 |
| - fn fold_item(&mut self, mut i: clean::Item) -> Option<clean::Item> { |
| 122 | + fn fold_item(&mut self, i: clean::Item) -> Option<clean::Item> { |
146 | 123 | let has_docs = !i.attrs.doc_strings.is_empty();
|
147 | 124 |
|
148 | 125 | match i.inner {
|
@@ -171,87 +148,26 @@ impl fold::DocFolder for CoverageCalculator {
|
171 | 148 | }
|
172 | 149 | clean::ImplItem(ref impl_) => {
|
173 | 150 | if let Some(ref tr) = impl_.trait_ {
|
174 |
| - debug!("counting impl {:#} for {:#}", tr, impl_.for_); |
175 |
| - |
176 |
| - // trait impls inherit their docs from the trait definition, so documenting |
177 |
| - // them can be considered optional |
178 |
| - self.items.entry(ItemType::Impl).or_default().count_item(has_docs); |
179 |
| - |
180 |
| - for it in &impl_.items { |
181 |
| - let has_docs = !it.attrs.doc_strings.is_empty(); |
182 |
| - self.items.entry(ItemType::Impl).or_default().count_item(has_docs); |
183 |
| - } |
| 151 | + debug!("impl {:#} for {:#} in {}", tr, impl_.for_, i.source.filename); |
184 | 152 |
|
185 |
| - // now skip recursing, so that we don't double-count this impl's items |
| 153 | + // don't count trait impls, the missing-docs lint doesn't so we shouldn't |
| 154 | + // either |
186 | 155 | return Some(i);
|
187 | 156 | } else {
|
188 | 157 | // inherent impls *can* be documented, and those docs show up, but in most
|
189 | 158 | // cases it doesn't make sense, as all methods on a type are in one single
|
190 | 159 | // impl block
|
191 |
| - debug!("not counting impl {:#}", impl_.for_); |
| 160 | + debug!("impl {:#} in {}", impl_.for_, i.source.filename); |
192 | 161 | }
|
193 | 162 | }
|
194 |
| - clean::MacroItem(..) | clean::ProcMacroItem(..) => { |
195 |
| - // combine `macro_rules!` macros and proc-macros in the same count |
196 |
| - debug!("counting macro {:?}", i.name); |
197 |
| - self.items.entry(ItemType::Macro).or_default().count_item(has_docs); |
198 |
| - } |
199 |
| - clean::TraitItem(ref mut trait_) => { |
200 |
| - // because both trait methods with a default impl and struct methods are |
201 |
| - // ItemType::Method, we need to properly tag trait methods as TyMethod instead |
202 |
| - debug!("counting trait {:?}", i.name); |
203 |
| - self.items.entry(ItemType::Trait).or_default().count_item(has_docs); |
204 |
| - |
205 |
| - // since we're not going on to document the crate, it doesn't matter if we discard |
206 |
| - // the item after counting it |
207 |
| - trait_.items.retain(|it| { |
208 |
| - if it.type_() == ItemType::Method { |
209 |
| - let has_docs = !it.attrs.doc_strings.is_empty(); |
210 |
| - self.items.entry(ItemType::TyMethod).or_default().count_item(has_docs); |
211 |
| - false |
212 |
| - } else { |
213 |
| - true |
214 |
| - } |
215 |
| - }); |
216 |
| - } |
217 | 163 | _ => {
|
218 |
| - debug!("counting {} {:?}", i.type_(), i.name); |
219 |
| - self.items.entry(i.type_()).or_default().count_item(has_docs); |
| 164 | + debug!("counting {} {:?} in {}", i.type_(), i.name, i.source.filename); |
| 165 | + self.items.entry(i.source.filename.clone()) |
| 166 | + .or_default() |
| 167 | + .count_item(has_docs); |
220 | 168 | }
|
221 | 169 | }
|
222 | 170 |
|
223 | 171 | self.fold_item_recur(i)
|
224 | 172 | }
|
225 | 173 | }
|
226 |
| - |
227 |
| -fn table_name(type_: &ItemType) -> &'static str { |
228 |
| - match *type_ { |
229 |
| - ItemType::Module => "Modules", |
230 |
| - ItemType::Struct => "Structs", |
231 |
| - ItemType::Union => "Unions", |
232 |
| - ItemType::Enum => "Enums", |
233 |
| - ItemType::Function => "Functions", |
234 |
| - ItemType::Typedef => "Type Aliases", |
235 |
| - ItemType::Static => "Statics", |
236 |
| - ItemType::Trait => "Traits", |
237 |
| - // inherent impls aren't counted, and trait impls get all their items thrown into this |
238 |
| - // counter |
239 |
| - ItemType::Impl => "Trait Impl Items", |
240 |
| - // even though trait methods with a default impl get cleaned as Method, we convert them |
241 |
| - // to TyMethod when counting |
242 |
| - ItemType::TyMethod => "Trait Methods", |
243 |
| - ItemType::Method => "Methods", |
244 |
| - ItemType::StructField => "Struct Fields", |
245 |
| - ItemType::Variant => "Enum Variants", |
246 |
| - ItemType::Macro => "Macros", |
247 |
| - ItemType::Primitive => "Primitives", |
248 |
| - ItemType::AssociatedType => "Associated Types", |
249 |
| - ItemType::Constant => "Constants", |
250 |
| - ItemType::AssociatedConst => "Associated Constants", |
251 |
| - ItemType::ForeignType => "Extern Types", |
252 |
| - ItemType::Keyword => "Keywords", |
253 |
| - ItemType::Existential => "Existential Types", |
254 |
| - ItemType::TraitAlias => "Trait Aliases", |
255 |
| - _ => panic!("unanticipated ItemType: {}", type_), |
256 |
| - } |
257 |
| -} |
0 commit comments