1 /* 2 * Copyright (C) 2010 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.doclava; 18 19 import com.google.clearsilver.jsilver.data.Data; 20 21 import java.util.*; 22 import java.util.stream.Collectors; 23 24 public class TodoFile { 25 26 public static final String MISSING = "No description text"; 27 areTagsUseful(InheritedTags tags)28 public static boolean areTagsUseful(InheritedTags tags) { 29 while (tags != null) { 30 if (areTagsUseful(tags.tags())) { 31 return true; 32 } 33 tags = tags.inherited(); 34 } 35 return false; 36 } 37 areTagsUseful(TagInfo[] tags)38 public static boolean areTagsUseful(TagInfo[] tags) { 39 for (TagInfo t : tags) { 40 if ("Text".equals(t.name()) && t.text().trim().length() != 0) { 41 return true; 42 } 43 if ("@inheritDoc".equals(t.name())) { 44 return true; 45 } 46 } 47 return false; 48 } 49 setHDF(Data data, String base, SourcePositionInfo pos, String name, String descr)50 public static void setHDF(Data data, String base, SourcePositionInfo pos, String name, 51 String descr) { 52 data.setValue(base + ".pos", pos.toString()); 53 data.setValue(base + ".name", name); 54 data.setValue(base + ".descr", descr); 55 } 56 57 static class PackageStats { 58 String name; 59 public int total; 60 public int errors; 61 } 62 percent(int a, int b)63 public static String percent(int a, int b) { 64 return "" + Math.round((((b - a) / (float) b)) * 100) + "%"; 65 } 66 writeTodoFile(String filename)67 public static void writeTodoFile(String filename) { 68 Data data = Doclava.makeHDF(); 69 Doclava.setPageTitle(data, "Missing Documentation"); 70 TreeMap<String, PackageStats> packageStats = new TreeMap<String, PackageStats>(); 71 72 Collection<ClassInfo> classes = Converter.rootClasses().stream().sorted(ClassInfo.comparator) 73 .collect(Collectors.toList()); 74 75 int classIndex = 0; 76 77 for (ClassInfo cl : classes) { 78 if (cl.isHiddenOrRemoved()){ 79 continue; 80 } 81 82 String classBase = "classes." + classIndex; 83 84 String base = classBase + ".errors."; 85 int errors = 0; 86 int total = 1; 87 88 if (!areTagsUseful(cl.inlineTags())) { 89 setHDF(data, base + errors, cl.position(), "<class comment>", MISSING); 90 errors++; 91 } 92 93 94 for (MethodInfo m : cl.constructors()) { 95 boolean good = true; 96 total++; 97 if (m.checkLevel()) { 98 if (!areTagsUseful(m.inlineTags())) { 99 setHDF(data, base + errors, m.position(), m.prettySignature(), MISSING); 100 good = false; 101 } 102 } 103 if (!good) { 104 errors++; 105 } 106 } 107 108 for (MethodInfo m : cl.selfMethods()) { 109 boolean good = true; 110 total++; 111 if (m.checkLevel()) { 112 if (!areTagsUseful(m.inlineTags())) { 113 setHDF(data, base + errors, m.position(), m.name() + m.prettySignature(), MISSING); 114 good = false; 115 } 116 } 117 if (!good) { 118 errors++; 119 } 120 } 121 122 123 for (FieldInfo f : cl.enumConstants()) { 124 boolean good = true; 125 total++; 126 if (f.checkLevel()) { 127 if (!areTagsUseful(f.inlineTags())) { 128 setHDF(data, base + errors, f.position(), f.name(), MISSING); 129 good = false; 130 } 131 } 132 if (!good) { 133 errors++; 134 } 135 } 136 137 for (FieldInfo f : cl.selfFields()) { 138 boolean good = true; 139 total++; 140 if (f.checkLevel()) { 141 if (!areTagsUseful(f.inlineTags())) { 142 setHDF(data, base + errors, f.position(), f.name(), MISSING); 143 good = false; 144 } 145 } 146 if (!good) { 147 errors++; 148 } 149 } 150 151 if (errors > 0) { 152 data.setValue(classBase + ".qualified", cl.qualifiedName()); 153 data.setValue(classBase + ".errorCount", "" + errors); 154 data.setValue(classBase + ".totalCount", "" + total); 155 data.setValue(classBase + ".percentGood", percent(errors, total)); 156 } 157 158 PackageInfo pkg = cl.containingPackage(); 159 String pkgName = pkg != null ? pkg.name() : ""; 160 PackageStats ps = packageStats.get(pkgName); 161 if (ps == null) { 162 ps = new PackageStats(); 163 ps.name = pkgName; 164 packageStats.put(pkgName, ps); 165 } 166 ps.total += total; 167 ps.errors += errors; 168 169 classIndex++; 170 } 171 172 int allTotal = 0; 173 int allErrors = 0; 174 175 int i = 0; 176 for (PackageStats ps : packageStats.values()) { 177 data.setValue("packages." + i + ".name", "" + ps.name); 178 data.setValue("packages." + i + ".errorCount", "" + ps.errors); 179 data.setValue("packages." + i + ".totalCount", "" + ps.total); 180 data.setValue("packages." + i + ".percentGood", percent(ps.errors, ps.total)); 181 182 allTotal += ps.total; 183 allErrors += ps.errors; 184 185 i++; 186 } 187 188 data.setValue("all.errorCount", "" + allErrors); 189 data.setValue("all.totalCount", "" + allTotal); 190 data.setValue("all.percentGood", percent(allErrors, allTotal)); 191 192 ClearPage.write(data, "todo.cs", filename, true); 193 } 194 } 195