auto import from //depot/cupcake/@135843
diff --git a/tools/droiddoc/src/TodoFile.java b/tools/droiddoc/src/TodoFile.java
new file mode 100644
index 0000000..ebef27e
--- /dev/null
+++ b/tools/droiddoc/src/TodoFile.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.clearsilver.HDF;
+import org.clearsilver.CS;
+import java.util.*;
+import java.io.*;
+
+public class TodoFile {
+
+    public static final String MISSING = "No description text";
+
+    public static boolean areTagsUseful(InheritedTags tags) {
+        while (tags != null) {
+            if (areTagsUseful(tags.tags())) {
+                return true;
+            }
+            tags = tags.inherited();
+        }
+        return false;
+    }
+
+    public static boolean areTagsUseful(TagInfo[] tags) {
+        for (TagInfo t: tags) {
+            if ("Text".equals(t.name()) && t.text().trim().length() != 0) {
+                return true;
+            }
+            if ("@inheritDoc".equals(t.name())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static void setHDF(HDF data, String base, SourcePositionInfo pos, String name,
+            String descr) {
+        data.setValue(base + ".pos", pos.toString());
+        data.setValue(base + ".name", name);
+        data.setValue(base + ".descr", descr);
+    }
+
+    static class PackageStats {
+        String name;
+        public int total;
+        public int errors;
+    }
+
+    public static String percent(int a, int b) {
+        return ""+Math.round((((b-a)/(float)b))*100) + "%";
+    }
+
+    public static void writeTodoFile(String filename) {
+        HDF data = DroidDoc.makeHDF();
+        DroidDoc.setPageTitle(data, "Missing Documentation");
+        TreeMap<String,PackageStats> packageStats = new TreeMap<String,PackageStats>();
+
+        ClassInfo[] classes = Converter.rootClasses();
+        Arrays.sort(classes);
+
+        int classIndex = 0;
+        
+        for (ClassInfo cl: classes) {
+            if (cl.isHidden()) {
+                continue;
+            }
+
+            String classBase = "classes." + classIndex;
+
+            String base = classBase + ".errors.";
+            int errors = 0;
+            int total = 1;
+
+            if (!areTagsUseful(cl.inlineTags())) {
+                setHDF(data, base + errors, cl.position(), "&lt;class comment&gt;", MISSING);
+                errors++;
+            }
+
+
+            for (MethodInfo m: cl.constructors()) {
+                boolean good = true;
+                total++;
+                if (m.checkLevel()) {
+                    if (!areTagsUseful(m.inlineTags())) {
+                        setHDF(data, base + errors, m.position(), m.name() + m.prettySignature(),
+                                MISSING);
+                        good = false;
+                    }
+                }
+                if (!good) {
+                    errors++;
+                }
+            }
+            
+            for (MethodInfo m: cl.selfMethods()) {
+                boolean good = true;
+                total++;
+                if (m.checkLevel()) {
+                    if (!areTagsUseful(m.inlineTags())) {
+                        setHDF(data, base + errors, m.position(), m.name() + m.prettySignature(),
+                                MISSING);
+                        good = false;
+                    }
+                }
+                if (!good) {
+                    errors++;
+                }
+            }
+            
+
+            for (FieldInfo f: cl.enumConstants()) {
+                boolean good = true;
+                total++;
+                if (f.checkLevel()) {
+                    if (!areTagsUseful(f.inlineTags())) {
+                        setHDF(data, base + errors, f.position(), f.name(), MISSING);
+                        good = false;
+                    }
+                }
+                if (!good) {
+                    errors++;
+                }
+            }
+            
+            for (FieldInfo f: cl.selfFields()) {
+                boolean good = true;
+                total++;
+                if (f.checkLevel()) {
+                    if (!areTagsUseful(f.inlineTags())) {
+                        setHDF(data, base + errors, f.position(), f.name(), MISSING);
+                        good = false;
+                    }
+                }
+                if (!good) {
+                    errors++;
+                }
+            }
+
+            if (errors > 0) {
+                data.setValue(classBase + ".qualified", cl.qualifiedName());
+                data.setValue(classBase + ".errorCount", ""+errors);
+                data.setValue(classBase + ".totalCount", ""+total);
+                data.setValue(classBase + ".percentGood", percent(errors, total));
+            }
+
+            PackageInfo pkg = cl.containingPackage();
+            String pkgName = pkg != null ? pkg.name() : "";
+            PackageStats ps = packageStats.get(pkgName);
+            if (ps == null) {
+                ps = new PackageStats();
+                ps.name = pkgName;
+                packageStats.put(pkgName, ps);
+            }
+            ps.total += total;
+            ps.errors += errors;
+
+            classIndex++;
+        }
+
+        int allTotal = 0;
+        int allErrors = 0;
+
+        int i = 0;
+        for (PackageStats ps: packageStats.values()) {
+            data.setValue("packages." + i + ".name", ""+ps.name);
+            data.setValue("packages." + i + ".errorCount", ""+ps.errors);
+            data.setValue("packages." + i + ".totalCount", ""+ps.total);
+            data.setValue("packages." + i + ".percentGood", percent(ps.errors, ps.total));
+
+            allTotal += ps.total;
+            allErrors += ps.errors;
+
+            i++;
+        }
+
+        data.setValue("all.errorCount", ""+allErrors);
+        data.setValue("all.totalCount", ""+allTotal);
+        data.setValue("all.percentGood", percent(allErrors, allTotal));
+
+        ClearPage.write(data, "todo.cs", filename, true);
+    }
+}
+