8004832: Add new doclint package
authorjjg
Mon, 17 Dec 2012 07:47:05 -0800
changeset 14952 d0022ae20516
parent 14951 8d9ea42e4aba
child 14953 89a34297b198
8004832: Add new doclint package Reviewed-by: mcimadamore
langtools/make/build.properties
langtools/src/share/classes/com/sun/source/util/DocTrees.java
langtools/src/share/classes/com/sun/source/util/JavacTask.java
langtools/src/share/classes/com/sun/source/util/TreePath.java
langtools/src/share/classes/com/sun/tools/doclint/Checker.java
langtools/src/share/classes/com/sun/tools/doclint/DocLint.java
langtools/src/share/classes/com/sun/tools/doclint/Entity.java
langtools/src/share/classes/com/sun/tools/doclint/Env.java
langtools/src/share/classes/com/sun/tools/doclint/HtmlTag.java
langtools/src/share/classes/com/sun/tools/doclint/Messages.java
langtools/src/share/classes/com/sun/tools/doclint/resources/doclint.properties
langtools/src/share/classes/com/sun/tools/javac/api/BasicJavacTask.java
langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java
langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java
langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java
langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java
langtools/src/share/classes/com/sun/tools/javac/parser/DocCommentParser.java
langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties
langtools/src/share/classes/com/sun/tools/javac/tree/DCTree.java
langtools/src/share/classes/com/sun/tools/javac/tree/DocPretty.java
langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java
langtools/test/tools/doclint/AccessTest.java
langtools/test/tools/doclint/AccessTest.package.out
langtools/test/tools/doclint/AccessTest.private.out
langtools/test/tools/doclint/AccessTest.protected.out
langtools/test/tools/doclint/AccessTest.public.out
langtools/test/tools/doclint/AccessibilityTest.java
langtools/test/tools/doclint/AccessibilityTest.out
langtools/test/tools/doclint/DocLintTester.java
langtools/test/tools/doclint/EmptyAuthorTest.java
langtools/test/tools/doclint/EmptyAuthorTest.out
langtools/test/tools/doclint/EmptyExceptionTest.java
langtools/test/tools/doclint/EmptyExceptionTest.out
langtools/test/tools/doclint/EmptyParamTest.java
langtools/test/tools/doclint/EmptyParamTest.out
langtools/test/tools/doclint/EmptyReturnTest.java
langtools/test/tools/doclint/EmptyReturnTest.out
langtools/test/tools/doclint/EmptySerialDataTest.java
langtools/test/tools/doclint/EmptySerialDataTest.out
langtools/test/tools/doclint/EmptySerialFieldTest.java
langtools/test/tools/doclint/EmptySerialFieldTest.out
langtools/test/tools/doclint/EmptySinceTest.java
langtools/test/tools/doclint/EmptySinceTest.out
langtools/test/tools/doclint/EmptyVersionTest.java
langtools/test/tools/doclint/EmptyVersionTest.out
langtools/test/tools/doclint/HtmlAttrsTest.java
langtools/test/tools/doclint/HtmlAttrsTest.out
langtools/test/tools/doclint/HtmlTagsTest.java
langtools/test/tools/doclint/HtmlTagsTest.out
langtools/test/tools/doclint/MissingCommentTest.java
langtools/test/tools/doclint/MissingCommentTest.out
langtools/test/tools/doclint/MissingParamsTest.java
langtools/test/tools/doclint/MissingParamsTest.out
langtools/test/tools/doclint/MissingReturnTest.java
langtools/test/tools/doclint/MissingReturnTest.out
langtools/test/tools/doclint/MissingThrowsTest.java
langtools/test/tools/doclint/MissingThrowsTest.out
langtools/test/tools/doclint/OptionTest.java
langtools/test/tools/doclint/OverridesTest.java
langtools/test/tools/doclint/ReferenceTest.java
langtools/test/tools/doclint/ReferenceTest.out
langtools/test/tools/doclint/RunTest.java
langtools/test/tools/doclint/SyntaxTest.java
langtools/test/tools/doclint/SyntaxTest.out
langtools/test/tools/doclint/SyntheticTest.java
langtools/test/tools/doclint/ValidTest.java
langtools/test/tools/doclint/tidy/AnchorAlreadyDefined.java
langtools/test/tools/doclint/tidy/AnchorAlreadyDefined.out
langtools/test/tools/doclint/tidy/BadEnd.java
langtools/test/tools/doclint/tidy/BadEnd.out
langtools/test/tools/doclint/tidy/InsertImplicit.java
langtools/test/tools/doclint/tidy/InsertImplicit.out
langtools/test/tools/doclint/tidy/InvalidEntity.java
langtools/test/tools/doclint/tidy/InvalidEntity.out
langtools/test/tools/doclint/tidy/InvalidName.java
langtools/test/tools/doclint/tidy/InvalidName.out
langtools/test/tools/doclint/tidy/InvalidTag.java
langtools/test/tools/doclint/tidy/InvalidTag.out
langtools/test/tools/doclint/tidy/InvalidURI.java
langtools/test/tools/doclint/tidy/InvalidURI.out
langtools/test/tools/doclint/tidy/MissingGT.java
langtools/test/tools/doclint/tidy/MissingGT.out
langtools/test/tools/doclint/tidy/MissingTag.java
langtools/test/tools/doclint/tidy/MissingTag.out
langtools/test/tools/doclint/tidy/NestedTag.java
langtools/test/tools/doclint/tidy/NestedTag.out
langtools/test/tools/doclint/tidy/ParaInPre.java
langtools/test/tools/doclint/tidy/ParaInPre.out
langtools/test/tools/doclint/tidy/README.txt
langtools/test/tools/doclint/tidy/RepeatedAttr.java
langtools/test/tools/doclint/tidy/RepeatedAttr.out
langtools/test/tools/doclint/tidy/TextNotAllowed.java
langtools/test/tools/doclint/tidy/TextNotAllowed.out
langtools/test/tools/doclint/tidy/TrimmingEmptyTag.java
langtools/test/tools/doclint/tidy/TrimmingEmptyTag.out
langtools/test/tools/doclint/tidy/UnescapedOrUnknownEntity.java
langtools/test/tools/doclint/tidy/UnescapedOrUnknownEntity.out
langtools/test/tools/doclint/tidy/util/Main.java
langtools/test/tools/doclint/tidy/util/tidy.sh
langtools/test/tools/javac/diags/examples/NoContent.java
--- a/langtools/make/build.properties	Mon Dec 17 14:54:42 2012 +0000
+++ b/langtools/make/build.properties	Mon Dec 17 07:47:05 2012 -0800
@@ -117,7 +117,8 @@
         javax/lang/model/ \
         javax/tools/ \
         com/sun/source/ \
-        com/sun/tools/javac/
+        com/sun/tools/javac/ \
+        com/sun/tools/doclint/
 
 javac.tests = \
         tools/javac
--- a/langtools/src/share/classes/com/sun/source/util/DocTrees.java	Mon Dec 17 14:54:42 2012 +0000
+++ b/langtools/src/share/classes/com/sun/source/util/DocTrees.java	Mon Dec 17 07:47:05 2012 -0800
@@ -45,9 +45,7 @@
      * @throws IllegalArgumentException if the task does not support the Trees API.
      */
     public static DocTrees instance(CompilationTask task) {
-        if (!task.getClass().getName().equals("com.sun.tools.javac.api.JavacTaskImpl"))
-            throw new IllegalArgumentException();
-        return (DocTrees) getJavacTrees(CompilationTask.class, task);
+        return (DocTrees) Trees.instance(task);
     }
 
     /**
--- a/langtools/src/share/classes/com/sun/source/util/JavacTask.java	Mon Dec 17 14:54:42 2012 +0000
+++ b/langtools/src/share/classes/com/sun/source/util/JavacTask.java	Mon Dec 17 07:47:05 2012 -0800
@@ -139,6 +139,7 @@
      * @see com.sun.source.util.Trees#getTypeMirror
      */
     public abstract TypeMirror getTypeMirror(Iterable<? extends Tree> path);
+
     /**
      * Get a utility object for dealing with program elements.
      */
--- a/langtools/src/share/classes/com/sun/source/util/TreePath.java	Mon Dec 17 14:54:42 2012 +0000
+++ b/langtools/src/share/classes/com/sun/source/util/TreePath.java	Mon Dec 17 07:47:05 2012 -0800
@@ -60,14 +60,20 @@
                 this.path = path;
             }
         }
+
         class PathFinder extends TreePathScanner<TreePath,Tree> {
             public TreePath scan(Tree tree, Tree target) {
-                if (tree == target)
+                if (tree == target) {
                     throw new Result(new TreePath(getCurrentPath(), target));
+                }
                 return super.scan(tree, target);
             }
         }
 
+        if (path.getLeaf() == target) {
+            return path;
+        }
+
         try {
             new PathFinder().scan(path, target);
         } catch (Result result) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/doclint/Checker.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,754 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.doclint;
+
+import java.util.regex.Matcher;
+import com.sun.source.doctree.LinkTree;
+import java.net.URI;
+import java.util.regex.Pattern;
+import java.io.IOException;
+import com.sun.tools.javac.tree.DocPretty;
+import java.io.StringWriter;
+import java.util.Deque;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Name;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.tools.Diagnostic.Kind;
+
+import com.sun.source.doctree.AttributeTree;
+import com.sun.source.doctree.AuthorTree;
+import com.sun.source.doctree.DocCommentTree;
+import com.sun.source.doctree.DocTree;
+import com.sun.source.doctree.EndElementTree;
+import com.sun.source.doctree.EntityTree;
+import com.sun.source.doctree.ErroneousTree;
+import com.sun.source.doctree.IdentifierTree;
+import com.sun.source.doctree.InheritDocTree;
+import com.sun.source.doctree.ParamTree;
+import com.sun.source.doctree.ReferenceTree;
+import com.sun.source.doctree.ReturnTree;
+import com.sun.source.doctree.SerialDataTree;
+import com.sun.source.doctree.SerialFieldTree;
+import com.sun.source.doctree.SinceTree;
+import com.sun.source.doctree.StartElementTree;
+import com.sun.source.doctree.TextTree;
+import com.sun.source.doctree.ThrowsTree;
+import com.sun.source.doctree.VersionTree;
+import com.sun.source.util.DocTreeScanner;
+import com.sun.source.util.TreePath;
+import com.sun.tools.doclint.HtmlTag.AttrKind;
+import java.net.URISyntaxException;
+import static com.sun.tools.doclint.Messages.Group.*;
+
+
+/**
+ * Validate a doc comment.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own
+ * risk.  This code and its internal interfaces are subject to change
+ * or deletion without notice.</b></p>
+ */
+public class Checker extends DocTreeScanner<Void, Void> {
+    final Env env;
+
+    Set<Element> foundParams = new HashSet<Element>();
+    Set<TypeMirror> foundThrows = new HashSet<TypeMirror>();
+    Set<String> foundAnchors = new HashSet<String>();
+    boolean foundInheritDoc = false;
+    boolean foundReturn = false;
+
+    enum Flag {
+        TABLE_HAS_CAPTION,
+        HAS_ELEMENT,
+        HAS_TEXT
+    }
+
+    static class TagStackItem {
+        final DocTree tree; // typically, but not always, StartElementTree
+        final HtmlTag tag;
+        final Set<HtmlTag.Attr> attrs;
+        final Set<Flag> flags;
+        TagStackItem(DocTree tree, HtmlTag tag) {
+            this.tree = tree;
+            this.tag = tag;
+            attrs = EnumSet.noneOf(HtmlTag.Attr.class);
+            flags = EnumSet.noneOf(Flag.class);
+        }
+        @Override
+        public String toString() {
+            return String.valueOf(tag);
+        }
+    }
+
+    private Deque<TagStackItem> tagStack; // TODO: maybe want to record starting tree as well
+    private HtmlTag currHeaderTag;
+
+    // <editor-fold defaultstate="collapsed" desc="Top level">
+
+    Checker(Env env) {
+        env.getClass();
+        this.env = env;
+        tagStack = new LinkedList<TagStackItem>();
+    }
+
+    public Void scan(DocCommentTree tree, TreePath p) {
+        env.setCurrent(p, tree);
+
+        boolean isOverridingMethod = !env.currOverriddenMethods.isEmpty();
+
+        if (tree == null) {
+            if (!isSynthetic() && !isOverridingMethod)
+                reportMissing("dc.missing.comment");
+            return null;
+        }
+
+        tagStack.clear();
+        currHeaderTag = null;
+
+        foundParams.clear();
+        foundThrows.clear();
+        foundInheritDoc = false;
+        foundReturn = false;
+
+        scan(tree, (Void) null);
+
+        if (!isOverridingMethod) {
+            switch (env.currElement.getKind()) {
+                case METHOD:
+                case CONSTRUCTOR: {
+                    ExecutableElement ee = (ExecutableElement) env.currElement;
+                    checkParamsDocumented(ee.getTypeParameters());
+                    checkParamsDocumented(ee.getParameters());
+                    switch (ee.getReturnType().getKind()) {
+                        case VOID:
+                        case NONE:
+                            break;
+                        default:
+                            if (!foundReturn
+                                    && !foundInheritDoc
+                                    && !env.types.isSameType(ee.getReturnType(), env.java_lang_Void)) {
+                                reportMissing("dc.missing.return");
+                            }
+                    }
+                    checkThrowsDocumented(ee.getThrownTypes());
+                }
+            }
+        }
+
+        return null;
+    }
+
+    private void reportMissing(String code, Object... args) {
+        env.messages.report(MISSING, Kind.WARNING, env.currPath.getLeaf(), code, args);
+    }
+
+    @Override
+    public Void visitDocComment(DocCommentTree tree, Void ignore) {
+        super.visitDocComment(tree, ignore);
+        for (TagStackItem tsi: tagStack) {
+            if (tsi.tree.getKind() == DocTree.Kind.START_ELEMENT
+                    && tsi.tag.endKind == HtmlTag.EndKind.REQUIRED) {
+                StartElementTree t = (StartElementTree) tsi.tree;
+                env.messages.error(HTML, t, "dc.tag.not.closed", t.getName());
+            }
+        }
+        return null;
+    }
+    // </editor-fold>
+
+    // <editor-fold defaultstate="collapsed" desc="Text and entities.">
+
+    @Override
+    public Void visitText(TextTree tree, Void ignore) {
+        if (!tree.getBody().trim().isEmpty()) {
+            markEnclosingTag(Flag.HAS_TEXT);
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitEntity(EntityTree tree, Void ignore) {
+        markEnclosingTag(Flag.HAS_TEXT);
+        String name = tree.getName().toString();
+        if (name.startsWith("#")) {
+            int v = name.toLowerCase().startsWith("#x")
+                    ? Integer.parseInt(name.substring(2), 16)
+                    : Integer.parseInt(name.substring(1), 10);
+            if (!Entity.isValid(v)) {
+                env.messages.error(HTML, tree, "dc.entity.invalid", name);
+            }
+        } else if (!Entity.isValid(name)) {
+            env.messages.error(HTML, tree, "dc.entity.invalid", name);
+        }
+        return null;
+    }
+
+    // </editor-fold>
+
+    // <editor-fold defaultstate="collapsed" desc="HTML elements">
+
+    @Override
+    public Void visitStartElement(StartElementTree tree, Void ignore) {
+        markEnclosingTag(Flag.HAS_ELEMENT);
+        final Name treeName = tree.getName();
+        final HtmlTag t = HtmlTag.get(treeName);
+        if (t == null) {
+            env.messages.error(HTML, tree, "dc.tag.unknown", treeName);
+        } else {
+            // tag specific checks
+            switch (t) {
+                // check for out of sequence headers, such as <h1>...</h1>  <h3>...</h3>
+                case H1: case H2: case H3: case H4: case H5: case H6:
+                    checkHeader(tree, t);
+                    break;
+                // <p> inside <pre>
+                case P:
+                    TagStackItem top = tagStack.peek();
+                    if (top != null && top.tag == HtmlTag.PRE)
+                        env.messages.warning(HTML, tree, "dc.tag.p.in.pre");
+                    break;
+            }
+
+            // check that only block tags and inline tags are used,
+            // and that blocks tags are not used within inline tags
+            switch (t.blockType) {
+                case INLINE:
+                    break;
+                case BLOCK:
+                    TagStackItem top = tagStack.peek();
+                    if (top != null && top.tag != null && top.tag.blockType == HtmlTag.BlockType.INLINE) {
+                        switch (top.tree.getKind()) {
+                            case START_ELEMENT: {
+                                Name name = ((StartElementTree) top.tree).getName();
+                                env.messages.error(HTML, tree, "dc.tag.not.allowed.inline.element",
+                                        treeName, name);
+                                break;
+                            }
+                            case LINK:
+                            case LINK_PLAIN: {
+                                String name = top.tree.getKind().tagName;
+                                env.messages.error(HTML, tree, "dc.tag.not.allowed.inline.tag",
+                                        treeName, name);
+                                break;
+                            }
+                            default:
+                                env.messages.error(HTML, tree, "dc.tag.not.allowed.inline.other",
+                                        treeName);
+                        }
+                    }
+                    break;
+                case OTHER:
+                    env.messages.error(HTML, tree, "dc.tag.not.allowed", treeName);
+                    break;
+                default:
+                    throw new AssertionError();
+            }
+
+            if (t.flags.contains(HtmlTag.Flag.NO_NEST)) {
+                for (TagStackItem i: tagStack) {
+                    if (t == i.tag) {
+                        env.messages.warning(HTML, tree, "dc.tag.nested.not.allowed", treeName);
+                        break;
+                    }
+                }
+            }
+        }
+
+        // check for self closing tags, such as <a id="name"/>
+        if (tree.isSelfClosing()) {
+            env.messages.error(HTML, tree, "dc.tag.self.closing", treeName);
+        }
+
+        try {
+            TagStackItem parent = tagStack.peek();
+            TagStackItem top = new TagStackItem(tree, t);
+            tagStack.push(top);
+
+            super.visitStartElement(tree, ignore);
+
+            // handle attributes that may or may not have been found in start element
+            if (t != null) {
+                switch (t) {
+                    case CAPTION:
+                        if (parent != null && parent.tag == HtmlTag.TABLE)
+                            parent.flags.add(Flag.TABLE_HAS_CAPTION);
+                        break;
+
+                    case IMG:
+                        if (!top.attrs.contains(HtmlTag.Attr.ALT))
+                            env.messages.error(ACCESSIBILITY, tree, "dc.no.alt.attr.for.image");
+                        break;
+                }
+            }
+
+            return null;
+        } finally {
+
+            if (t == null || t.endKind == HtmlTag.EndKind.NONE)
+                tagStack.pop();
+        }
+    }
+
+    private void checkHeader(StartElementTree tree, HtmlTag tag) {
+        // verify the new tag
+        if (getHeaderLevel(tag) > getHeaderLevel(currHeaderTag) + 1) {
+            if (currHeaderTag == null) {
+                env.messages.error(ACCESSIBILITY, tree, "dc.tag.header.sequence.1", tag);
+            } else {
+                env.messages.error(ACCESSIBILITY, tree, "dc.tag.header.sequence.2",
+                    tag, currHeaderTag);
+            }
+        }
+
+        currHeaderTag = tag;
+    }
+
+    private int getHeaderLevel(HtmlTag tag) {
+        if (tag == null)
+            return 0;
+        switch (tag) {
+            case H1: return 1;
+            case H2: return 2;
+            case H3: return 3;
+            case H4: return 4;
+            case H5: return 5;
+            case H6: return 6;
+            default: throw new IllegalArgumentException();
+        }
+    }
+
+    @Override
+    public Void visitEndElement(EndElementTree tree, Void ignore) {
+        final Name treeName = tree.getName();
+        final HtmlTag t = HtmlTag.get(treeName);
+        if (t == null) {
+            env.messages.error(HTML, tree, "dc.tag.unknown", treeName);
+        } else if (t.endKind == HtmlTag.EndKind.NONE) {
+            env.messages.error(HTML, tree, "dc.tag.end.not.permitted", treeName);
+        } else if (tagStack.isEmpty()) {
+            env.messages.error(HTML, tree, "dc.tag.end.unexpected", treeName);
+        } else {
+            while (!tagStack.isEmpty()) {
+                TagStackItem top = tagStack.peek();
+                if (t == top.tag) {
+                    switch (t) {
+                        case TABLE:
+                            if (!top.attrs.contains(HtmlTag.Attr.SUMMARY)
+                                    && !top.flags.contains(Flag.TABLE_HAS_CAPTION)) {
+                                env.messages.error(ACCESSIBILITY, tree,
+                                        "dc.no.summary.or.caption.for.table");
+                            }
+                    }
+                    if (t.flags.contains(HtmlTag.Flag.EXPECT_CONTENT)
+                            && !top.flags.contains(Flag.HAS_TEXT)
+                            && !top.flags.contains(Flag.HAS_ELEMENT)) {
+                        env.messages.warning(HTML, tree, "dc.tag.empty", treeName);
+                    }
+                    if (t.flags.contains(HtmlTag.Flag.NO_TEXT)
+                            && top.flags.contains(Flag.HAS_TEXT)) {
+                        env.messages.error(HTML, tree, "dc.text.not.allowed", treeName);
+                    }
+                    tagStack.pop();
+                    break;
+                } else if (top.tag == null || top.tag.endKind != HtmlTag.EndKind.REQUIRED) {
+                    tagStack.pop();
+                } else {
+                    boolean found = false;
+                    for (TagStackItem si: tagStack) {
+                        if (si.tag == t) {
+                            found = true;
+                            break;
+                        }
+                    }
+                    if (found && top.tree.getKind() == DocTree.Kind.START_ELEMENT) {
+                        env.messages.error(HTML, top.tree, "dc.tag.start.unmatched",
+                                ((StartElementTree) top.tree).getName());
+                        tagStack.pop();
+                    } else {
+                        env.messages.error(HTML, tree, "dc.tag.end.unexpected", treeName);
+                        break;
+                    }
+                }
+            }
+        }
+
+        return super.visitEndElement(tree, ignore);
+    }
+    // </editor-fold>
+
+    // <editor-fold defaultstate="collapsed" desc="HTML attributes">
+
+    @Override @SuppressWarnings("fallthrough")
+    public Void visitAttribute(AttributeTree tree, Void ignore) {
+        HtmlTag currTag = tagStack.peek().tag;
+        if (currTag != null) {
+            Name name = tree.getName();
+            HtmlTag.Attr attr = currTag.getAttr(name);
+            if (attr != null) {
+                boolean first = tagStack.peek().attrs.add(attr);
+                if (!first)
+                    env.messages.error(HTML, tree, "dc.attr.repeated", name);
+            }
+            AttrKind k = currTag.getAttrKind(name);
+            switch (k) {
+                case OK:
+                    break;
+
+                case INVALID:
+                    env.messages.error(HTML, tree, "dc.attr.unknown", name);
+                    break;
+
+                case OBSOLETE:
+                    env.messages.warning(ACCESSIBILITY, tree, "dc.attr.obsolete", name);
+                    break;
+
+                case USE_CSS:
+                    env.messages.warning(ACCESSIBILITY, tree, "dc.attr.obsolete.use.css", name);
+                    break;
+            }
+
+            if (attr != null) {
+                switch (attr) {
+                    case NAME:
+                        if (currTag != HtmlTag.A) {
+                            break;
+                        }
+                    // fallthrough
+                    case ID:
+                        String value = getAttrValue(tree);
+                        if (!validName.matcher(value).matches()) {
+                            env.messages.error(HTML, tree, "dc.invalid.anchor", value);
+                        }
+                        if (!foundAnchors.add(value)) {
+                            env.messages.error(HTML, tree, "dc.anchor.already.defined", value);
+                        }
+                        break;
+
+                    case HREF:
+                        if (currTag == HtmlTag.A) {
+                            String v = getAttrValue(tree);
+                            if (v == null || v.isEmpty()) {
+                                env.messages.error(HTML, tree, "dc.attr.lacks.value");
+                            } else {
+                                Matcher m = docRoot.matcher(v);
+                                if (m.matches()) {
+                                    String rest = m.group(2);
+                                    if (!rest.isEmpty())
+                                        checkURI(tree, rest);
+                                } else {
+                                    checkURI(tree, v);
+                                }
+                            }
+                        }
+                        break;
+                }
+            }
+        }
+
+        // TODO: basic check on value
+
+        return super.visitAttribute(tree, ignore);
+    }
+
+    // http://www.w3.org/TR/html401/types.html#type-name
+    private static final Pattern validName = Pattern.compile("[A-Za-z][A-Za-z0-9-_:.]*");
+
+    // pattern to remove leading {@docRoot}/?
+    private static final Pattern docRoot = Pattern.compile("(?i)(\\{@docRoot *\\}/?)?(.*)");
+
+    private String getAttrValue(AttributeTree tree) {
+        if (tree.getValue() == null)
+            return null;
+
+        StringWriter sw = new StringWriter();
+        try {
+            new DocPretty(sw).print(tree.getValue());
+        } catch (IOException e) {
+            // cannot happen
+        }
+        // ignore potential use of entities for now
+        return sw.toString();
+    }
+
+    private void checkURI(AttributeTree tree, String uri) {
+        try {
+            URI u = new URI(uri);
+        } catch (URISyntaxException e) {
+            env.messages.error(HTML, tree, "dc.invalid.uri", uri);
+        }
+    }
+    // </editor-fold>
+
+    // <editor-fold defaultstate="collapsed" desc="javadoc tags">
+
+    @Override
+    public Void visitAuthor(AuthorTree tree, Void ignore) {
+        warnIfEmpty(tree, tree.getName());
+        return super.visitAuthor(tree, ignore);
+    }
+
+    @Override
+    public Void visitInheritDoc(InheritDocTree tree, Void ignore) {
+        // TODO: verify on overridden method
+        foundInheritDoc = true;
+        return super.visitInheritDoc(tree, ignore);
+    }
+
+    @Override
+    public Void visitLink(LinkTree tree, Void ignore) {
+        // simulate inline context on tag stack
+        HtmlTag t = (tree.getKind() == DocTree.Kind.LINK)
+                ? HtmlTag.CODE : HtmlTag.SPAN;
+        tagStack.push(new TagStackItem(tree, t));
+        try {
+            return super.visitLink(tree, ignore);
+        } finally {
+            tagStack.pop();
+        }
+    }
+
+    @Override
+    public Void visitParam(ParamTree tree, Void ignore) {
+        boolean typaram = tree.isTypeParameter();
+        IdentifierTree nameTree = tree.getName();
+        Element e = env.currElement;
+        switch (e.getKind()) {
+            case METHOD: case CONSTRUCTOR: {
+                ExecutableElement ee = (ExecutableElement) e;
+                checkParamDeclared(nameTree, typaram ? ee.getTypeParameters() : ee.getParameters());
+                break;
+            }
+
+            case CLASS: case INTERFACE: {
+                TypeElement te = (TypeElement) e;
+                if (typaram) {
+                    checkParamDeclared(nameTree, te.getTypeParameters());
+                } else {
+                    env.messages.error(REFERENCE, tree, "dc.invalid.param");
+                }
+                break;
+            }
+
+            default:
+                env.messages.error(REFERENCE, tree, "dc.invalid.param");
+                break;
+        }
+        warnIfEmpty(tree, tree.getDescription());
+        return super.visitParam(tree, ignore);
+    }
+    // where
+    private void checkParamDeclared(IdentifierTree nameTree, List<? extends Element> list) {
+        Name name = nameTree.getName();
+        boolean found = false;
+        for (Element e: list) {
+            if (name.equals(e.getSimpleName())) {
+                foundParams.add(e);
+                found = true;
+            }
+        }
+        if (!found)
+            env.messages.error(REFERENCE, nameTree, "dc.param.name.not.found");
+    }
+
+    private void checkParamsDocumented(List<? extends Element> list) {
+        if (foundInheritDoc)
+            return;
+
+        for (Element e: list) {
+            if (!foundParams.contains(e)) {
+                CharSequence paramName = (e.getKind() == ElementKind.TYPE_PARAMETER)
+                        ? "<" + e.getSimpleName() + ">"
+                        : e.getSimpleName();
+                reportMissing("dc.missing.param", paramName);
+            }
+        }
+    }
+
+    @Override
+    public Void visitReference(ReferenceTree tree, Void ignore) {
+        Element e = env.trees.getElement(env.currPath, tree);
+        if (e == null)
+            env.messages.error(REFERENCE, tree, "dc.ref.not.found");
+        return super.visitReference(tree, ignore);
+    }
+
+    @Override
+    public Void visitReturn(ReturnTree tree, Void ignore) {
+        Element e = env.trees.getElement(env.currPath);
+        if (e.getKind() != ElementKind.METHOD
+                || ((ExecutableElement) e).getReturnType().getKind() == TypeKind.VOID)
+            env.messages.error(REFERENCE, tree, "dc.invalid.return");
+        foundReturn = true;
+        warnIfEmpty(tree, tree.getDescription());
+        return super.visitReturn(tree, ignore);
+    }
+
+    @Override
+    public Void visitSerialData(SerialDataTree tree, Void ignore) {
+        warnIfEmpty(tree, tree.getDescription());
+        return super.visitSerialData(tree, ignore);
+    }
+
+    @Override
+    public Void visitSerialField(SerialFieldTree tree, Void ignore) {
+        warnIfEmpty(tree, tree.getDescription());
+        return super.visitSerialField(tree, ignore);
+    }
+
+    @Override
+    public Void visitSince(SinceTree tree, Void ignore) {
+        warnIfEmpty(tree, tree.getBody());
+        return super.visitSince(tree, ignore);
+    }
+
+    @Override
+    public Void visitThrows(ThrowsTree tree, Void ignore) {
+        ReferenceTree exName = tree.getExceptionName();
+        Element ex = env.trees.getElement(env.currPath, exName);
+        if (ex == null) {
+            env.messages.error(REFERENCE, tree, "dc.ref.not.found");
+        } else if (ex.asType().getKind() == TypeKind.DECLARED
+                && env.types.isAssignable(ex.asType(), env.java_lang_Throwable)) {
+            switch (env.currElement.getKind()) {
+                case CONSTRUCTOR:
+                case METHOD:
+                    if (isCheckedException(ex.asType())) {
+                        ExecutableElement ee = (ExecutableElement) env.currElement;
+                        checkThrowsDeclared(exName, ex.asType(), ee.getThrownTypes());
+                    }
+                    break;
+                default:
+                    env.messages.error(REFERENCE, tree, "dc.invalid.throws");
+            }
+        } else {
+            env.messages.error(REFERENCE, tree, "dc.invalid.throws");
+        }
+        warnIfEmpty(tree, tree.getDescription());
+        return scan(tree.getDescription(), ignore);
+    }
+
+    private void checkThrowsDeclared(ReferenceTree tree, TypeMirror t, List<? extends TypeMirror> list) {
+        boolean found = false;
+        for (TypeMirror tl : list) {
+            if (env.types.isAssignable(t, tl)) {
+                foundThrows.add(tl);
+                found = true;
+            }
+        }
+        if (!found)
+            env.messages.error(REFERENCE, tree, "dc.exception.not.thrown", t);
+    }
+
+    private void checkThrowsDocumented(List<? extends TypeMirror> list) {
+        if (foundInheritDoc)
+            return;
+
+        for (TypeMirror tl: list) {
+            if (isCheckedException(tl) && !foundThrows.contains(tl))
+                reportMissing("dc.missing.throws", tl);
+        }
+    }
+
+    @Override
+    public Void visitVersion(VersionTree tree, Void ignore) {
+        warnIfEmpty(tree, tree.getBody());
+        return super.visitVersion(tree, ignore);
+    }
+
+    @Override
+    public Void visitErroneous(ErroneousTree tree, Void ignore) {
+        env.messages.error(SYNTAX, tree, null, tree.getDiagnostic().getMessage(null));
+        return null;
+    }
+    // </editor-fold>
+
+    // <editor-fold defaultstate="collapsed" desc="Utility methods">
+
+    private boolean isCheckedException(TypeMirror t) {
+        return !(env.types.isAssignable(t, env.java_lang_Error)
+                || env.types.isAssignable(t, env.java_lang_RuntimeException));
+    }
+
+    private boolean isSynthetic() {
+        switch (env.currElement.getKind()) {
+            case CONSTRUCTOR:
+                // A synthetic default constructor has the same pos as the
+                // enclosing class
+                TreePath p = env.currPath;
+                return env.getPos(p) == env.getPos(p.getParentPath());
+        }
+        return false;
+    }
+
+    void markEnclosingTag(Flag flag) {
+        TagStackItem top = tagStack.peek();
+        if (top != null)
+            top.flags.add(flag);
+    }
+
+    String toString(TreePath p) {
+        StringBuilder sb = new StringBuilder("TreePath[");
+        toString(p, sb);
+        sb.append("]");
+        return sb.toString();
+    }
+
+    void toString(TreePath p, StringBuilder sb) {
+        TreePath parent = p.getParentPath();
+        if (parent != null) {
+            toString(parent, sb);
+            sb.append(",");
+        }
+       sb.append(p.getLeaf().getKind()).append(":").append(env.getPos(p)).append(":S").append(env.getStartPos(p));
+    }
+
+    void warnIfEmpty(DocTree tree, List<? extends DocTree> list) {
+        for (DocTree d: list) {
+            switch (d.getKind()) {
+                case TEXT:
+                    if (!((TextTree) d).getBody().trim().isEmpty())
+                        return;
+                    break;
+                default:
+                    return;
+            }
+        }
+        env.messages.warning(SYNTAX, tree, "dc.empty", tree.getKind().tagName);
+    }
+    // </editor-fold>
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/doclint/DocLint.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.doclint;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.lang.model.element.Name;
+import javax.tools.StandardLocation;
+
+import com.sun.source.doctree.DocCommentTree;
+import com.sun.source.tree.ClassTree;
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.tree.MethodTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.tree.VariableTree;
+import com.sun.source.util.JavacTask;
+import com.sun.source.util.Plugin;
+import com.sun.source.util.TaskEvent;
+import com.sun.source.util.TaskListener;
+import com.sun.source.util.TreePath;
+import com.sun.source.util.TreePathScanner;
+import com.sun.tools.javac.api.JavacTaskImpl;
+import com.sun.tools.javac.api.JavacTool;
+import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.main.JavaCompiler;
+import com.sun.tools.javac.util.Context;
+
+/**
+ * Multi-function entry point for the doc check utility.
+ *
+ * This class can be invoked in the following ways:
+ * <ul>
+ * <li>From the command line
+ * <li>From javac, as a plugin
+ * <li>Directly, via a simple API
+ * </ul>
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own
+ * risk.  This code and its internal interfaces are subject to change
+ * or deletion without notice.</b></p>
+ */
+public class DocLint implements Plugin {
+
+    public static final String XMSGS_OPTION = "-Xmsgs";
+    public static final String XMSGS_CUSTOM_PREFIX = "-Xmsgs:";
+    private static final String STATS = "-stats";
+
+    // <editor-fold defaultstate="collapsed" desc="Command-line entry point">
+    public static void main(String... args) {
+        try {
+            new DocLint().run(args);
+        } catch (BadArgs e) {
+            System.err.println(e.getMessage());
+            System.exit(1);
+        } catch (IOException e) {
+            System.err.println(e);
+            System.exit(2);
+        }
+    }
+
+    // </editor-fold>
+
+    // <editor-fold defaultstate="collapsed" desc="Simple API">
+
+    public static class BadArgs extends Exception {
+        private static final long serialVersionUID = 0;
+        BadArgs(String code, Object... args) {
+            this.code = code;
+            this.args = args;
+        }
+
+        final String code;
+        final Object[] args;
+    }
+
+    /**
+     * Simple API entry point.
+     */
+    public void run(String... args) throws BadArgs, IOException {
+        PrintWriter out = new PrintWriter(System.out);
+        try {
+            run(out, args);
+        } finally {
+            out.flush();
+        }
+    }
+
+    public void run(PrintWriter out, String... args) throws BadArgs, IOException {
+        env = new Env();
+        processArgs(args);
+
+        if (needHelp)
+            showHelp(out);
+
+        if (javacFiles.isEmpty()) {
+            if (!needHelp)
+                System.out.println("no files given");
+        }
+
+        JavacTool tool = JavacTool.create();
+
+        JavacFileManager fm = new JavacFileManager(new Context(), false, null);
+        fm.setSymbolFileEnabled(false);
+        fm.setLocation(StandardLocation.PLATFORM_CLASS_PATH, javacBootClassPath);
+        fm.setLocation(StandardLocation.CLASS_PATH, javacClassPath);
+        fm.setLocation(StandardLocation.SOURCE_PATH, javacSourcePath);
+
+        JavacTask task = tool.getTask(out, fm, null, javacOpts, null,
+                fm.getJavaFileObjectsFromFiles(javacFiles));
+        Iterable<? extends CompilationUnitTree> units = task.parse();
+        ((JavacTaskImpl) task).enter();
+
+        env.init(task);
+        checker = new Checker(env);
+
+        DeclScanner ds = new DeclScanner() {
+            @Override
+            void visitDecl(Tree tree, Name name) {
+                TreePath p = getCurrentPath();
+                DocCommentTree dc = env.trees.getDocCommentTree(p);
+
+                checker.scan(dc, p);
+            }
+        };
+
+        ds.scan(units, null);
+
+        reportStats(out);
+
+        Context ctx = ((JavacTaskImpl) task).getContext();
+        JavaCompiler c = JavaCompiler.instance(ctx);
+        c.printCount("error", c.errorCount());
+        c.printCount("warn", c.warningCount());
+    }
+
+    void processArgs(String... args) throws BadArgs {
+        javacOpts = new ArrayList<String>();
+        javacFiles = new ArrayList<File>();
+
+        if (args.length == 0)
+            needHelp = true;
+
+        for (int i = 0; i < args.length; i++) {
+            String arg = args[i];
+            if (arg.matches("-Xmax(errs|warns)") && i + 1 < args.length) {
+                if (args[++i].matches("[0-9]+")) {
+                    javacOpts.add(arg);
+                    javacOpts.add(args[i]);
+                } else {
+                    throw new BadArgs("dc.bad.value.for.option", arg, args[i]);
+                }
+            } else if (arg.equals(STATS)) {
+                env.messages.setStatsEnabled(true);
+            } else if (arg.matches("-bootclasspath") && i + 1 < args.length) {
+                javacBootClassPath = splitPath(args[++i]);
+            } else if (arg.matches("-classpath") && i + 1 < args.length) {
+                javacClassPath = splitPath(args[++i]);
+            } else if (arg.matches("-sourcepath") && i + 1 < args.length) {
+                javacSourcePath = splitPath(args[++i]);
+            } else if (arg.equals(XMSGS_OPTION)) {
+                env.messages.setOptions(null);
+            } else if (arg.startsWith(XMSGS_CUSTOM_PREFIX)) {
+                env.messages.setOptions(arg.substring(arg.indexOf(":") + 1));
+            } else if (arg.equals("-h") || arg.equals("-help") || arg.equals("--help")
+                    || arg.equals("-?") || arg.equals("-usage")) {
+                needHelp = true;
+            } else if (arg.startsWith("-")) {
+                throw new BadArgs("dc.bad.option", arg);
+            } else {
+                while (i < args.length)
+                    javacFiles.add(new File(args[i++]));
+            }
+        }
+    }
+
+    void showHelp(PrintWriter out) {
+        out.println("Usage:");
+        out.println("    doclint [options] source-files...");
+        out.println("");
+        out.println("Options:");
+        out.println("  -Xmsgs  ");
+        out.println("    Same as -Xmsgs:all");
+        out.println("  -Xmsgs:values");
+        out.println("    Specify categories of issues to be checked, where 'values'");
+        out.println("    is a comma-separated list of any of the following:");
+        out.println("      reference      show places where comments contain incorrect");
+        out.println("                     references to Java source code elements");
+        out.println("      syntax         show basic syntax errors within comments");
+        out.println("      html           show issues with HTML tags and attributes");
+        out.println("      accessibility  show issues for accessibility");
+        out.println("      missing        show issues with missing documentation");
+        out.println("      all            all of the above");
+        out.println("    Precede a value with '-' to negate it");
+        out.println("    Categories may be qualified by one of:");
+        out.println("      /public /protected /package /private");
+        out.println("    For positive categories (not beginning with '-')");
+        out.println("    the qualifier applies to that access level and above.");
+        out.println("    For negative categories (beginning with '-')");
+        out.println("    the qualifier applies to that access level and below.");
+        out.println("    If a qualifier is missing, the category applies to");
+        out.println("    all access levels.");
+        out.println("    For example, -Xmsgs:all,-syntax/private");
+        out.println("    This will enable all messages, except syntax errors");
+        out.println("    in the doc comments of private methods.");
+        out.println("    If no -Xmsgs options are provided, the default is");
+        out.println("    equivalent to -Xmsgs:all/protected, meaning that");
+        out.println("    all messages are reported for protected and public");
+        out.println("    declarations only. ");
+        out.println("  -h -help --help -usage -?");
+        out.println("    Show this message.");
+        out.println("");
+        out.println("The following javac options are also supported");
+        out.println("  -bootclasspath, -classpath, -sourcepath, -Xmaxerrs, -Xmaxwarns");
+        out.println("");
+        out.println("To run doclint on part of a project, put the compiled classes for your");
+        out.println("project on the classpath (or bootclasspath), then specify the source files");
+        out.println("to be checked on the command line.");
+    }
+
+    List<File> splitPath(String path) {
+        List<File> files = new ArrayList<File>();
+        for (String f: path.split(File.separator)) {
+            if (f.length() > 0)
+                files.add(new File(f));
+        }
+        return files;
+    }
+
+    List<File> javacBootClassPath;
+    List<File> javacClassPath;
+    List<File> javacSourcePath;
+    List<String> javacOpts;
+    List<File> javacFiles;
+    boolean needHelp = false;
+
+    // </editor-fold>
+
+    // <editor-fold defaultstate="collapsed" desc="javac Plugin">
+
+    @Override
+    public String getName() {
+        return "doclint";
+    }
+
+    @Override
+    public void call(JavacTask task, String... args) {
+        init(task, args, true);
+    }
+
+    // </editor-fold>
+
+    // <editor-fold defaultstate="collapsed" desc="Embedding API">
+
+    public void init(JavacTask task, String[] args, boolean addTaskListener) {
+        env = new Env();
+        for (int i = 0; i < args.length; i++) {
+            String arg = args[i];
+            if (arg.equals(XMSGS_OPTION)) {
+                env.messages.setOptions(null);
+            } else if (arg.startsWith(XMSGS_CUSTOM_PREFIX)) {
+                env.messages.setOptions(arg.substring(arg.indexOf(":") + 1));
+            } else
+                throw new IllegalArgumentException(arg);
+        }
+        env.init(task);
+
+        checker = new Checker(env);
+
+        if (addTaskListener) {
+            final DeclScanner ds = new DeclScanner() {
+                @Override
+                void visitDecl(Tree tree, Name name) {
+                    TreePath p = getCurrentPath();
+                    DocCommentTree dc = env.trees.getDocCommentTree(p);
+
+                    checker.scan(dc, p);
+                }
+            };
+
+            TaskListener tl = new TaskListener() {
+                @Override
+                public void started(TaskEvent e) {
+                    return;
+                }
+
+                @Override
+                public void finished(TaskEvent e) {
+                    switch (e.getKind()) {
+                        case ENTER:
+                            ds.scan(e.getCompilationUnit(), null);
+                    }
+                }
+            };
+
+            task.addTaskListener(tl);
+        }
+    }
+
+    public void scan(TreePath p) {
+        DocCommentTree dc = env.trees.getDocCommentTree(p);
+        checker.scan(dc, p);
+    }
+
+    public void reportStats(PrintWriter out) {
+        env.messages.reportStats(out);
+    }
+
+    // </editor-fold>
+
+    Env env;
+    Checker checker;
+
+    public static boolean isValidOption(String opt) {
+        if (opt.equals(XMSGS_OPTION))
+           return true;
+        if (opt.startsWith(XMSGS_CUSTOM_PREFIX))
+           return Messages.Options.isValidOptions(opt.substring(XMSGS_CUSTOM_PREFIX.length()));
+        return false;
+    }
+
+    // <editor-fold defaultstate="collapsed" desc="DeclScanner">
+
+    static abstract class DeclScanner extends TreePathScanner<Void, Void> {
+        abstract void visitDecl(Tree tree, Name name);
+
+        @Override
+        public Void visitClass(ClassTree tree, Void ignore) {
+            visitDecl(tree, tree.getSimpleName());
+            return super.visitClass(tree, ignore);
+        }
+
+        @Override
+        public Void visitMethod(MethodTree tree, Void ignore) {
+            visitDecl(tree, tree.getName());
+            //return super.visitMethod(tree, ignore);
+            return null;
+        }
+
+        @Override
+        public Void visitVariable(VariableTree tree, Void ignore) {
+            visitDecl(tree, tree.getName());
+            return super.visitVariable(tree, ignore);
+        }
+    }
+
+    // </editor-fold>
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/doclint/Entity.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.doclint;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Table of entities defined in HTML 4.01.
+ *
+ * <p> Derived from
+ * <a href="http://www.w3.org/TR/html4/sgml/entities.html">Character entity references in HTML 4</a>.
+ *
+ * The name of the member follows the name of the entity,
+ * except when it clashes with a keyword, in which case
+ * it is prefixed by '_'.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own
+ * risk.  This code and its internal interfaces are subject to change
+ * or deletion without notice.</b></p>
+ */
+enum Entity {
+    nbsp(160),
+    iexcl(161),
+    cent(162),
+    pound(163),
+    curren(164),
+    yen(165),
+    brvbar(166),
+    sect(167),
+    uml(168),
+    copy(169),
+    ordf(170),
+    laquo(171),
+    not(172),
+    shy(173),
+    reg(174),
+    macr(175),
+    deg(176),
+    plusmn(177),
+    sup2(178),
+    sup3(179),
+    acute(180),
+    micro(181),
+    para(182),
+    middot(183),
+    cedil(184),
+    sup1(185),
+    ordm(186),
+    raquo(187),
+    frac14(188),
+    frac12(189),
+    frac34(190),
+    iquest(191),
+    Agrave(192),
+    Aacute(193),
+    Acirc(194),
+    Atilde(195),
+    Auml(196),
+    Aring(197),
+    AElig(198),
+    Ccedil(199),
+    Egrave(200),
+    Eacute(201),
+    Ecirc(202),
+    Euml(203),
+    Igrave(204),
+    Iacute(205),
+    Icirc(206),
+    Iuml(207),
+    ETH(208),
+    Ntilde(209),
+    Ograve(210),
+    Oacute(211),
+    Ocirc(212),
+    Otilde(213),
+    Ouml(214),
+    times(215),
+    Oslash(216),
+    Ugrave(217),
+    Uacute(218),
+    Ucirc(219),
+    Uuml(220),
+    Yacute(221),
+    THORN(222),
+    szlig(223),
+    agrave(224),
+    aacute(225),
+    acirc(226),
+    atilde(227),
+    auml(228),
+    aring(229),
+    aelig(230),
+    ccedil(231),
+    egrave(232),
+    eacute(233),
+    ecirc(234),
+    euml(235),
+    igrave(236),
+    iacute(237),
+    icirc(238),
+    iuml(239),
+    eth(240),
+    ntilde(241),
+    ograve(242),
+    oacute(243),
+    ocirc(244),
+    otilde(245),
+    ouml(246),
+    divide(247),
+    oslash(248),
+    ugrave(249),
+    uacute(250),
+    ucirc(251),
+    uuml(252),
+    yacute(253),
+    thorn(254),
+    yuml(255),
+    fnof(402),
+    Alpha(913),
+    Beta(914),
+    Gamma(915),
+    Delta(916),
+    Epsilon(917),
+    Zeta(918),
+    Eta(919),
+    Theta(920),
+    Iota(921),
+    Kappa(922),
+    Lambda(923),
+    Mu(924),
+    Nu(925),
+    Xi(926),
+    Omicron(927),
+    Pi(928),
+    Rho(929),
+    Sigma(931),
+    Tau(932),
+    Upsilon(933),
+    Phi(934),
+    Chi(935),
+    Psi(936),
+    Omega(937),
+    alpha(945),
+    beta(946),
+    gamma(947),
+    delta(948),
+    epsilon(949),
+    zeta(950),
+    eta(951),
+    theta(952),
+    iota(953),
+    kappa(954),
+    lambda(955),
+    mu(956),
+    nu(957),
+    xi(958),
+    omicron(959),
+    pi(960),
+    rho(961),
+    sigmaf(962),
+    sigma(963),
+    tau(964),
+    upsilon(965),
+    phi(966),
+    chi(967),
+    psi(968),
+    omega(969),
+    thetasym(977),
+    upsih(978),
+    piv(982),
+    bull(8226),
+    hellip(8230),
+    prime(8242),
+    Prime(8243),
+    oline(8254),
+    frasl(8260),
+    weierp(8472),
+    image(8465),
+    real(8476),
+    trade(8482),
+    alefsym(8501),
+    larr(8592),
+    uarr(8593),
+    rarr(8594),
+    darr(8595),
+    harr(8596),
+    crarr(8629),
+    lArr(8656),
+    uArr(8657),
+    rArr(8658),
+    dArr(8659),
+    hArr(8660),
+    forall(8704),
+    part(8706),
+    exist(8707),
+    empty(8709),
+    nabla(8711),
+    isin(8712),
+    notin(8713),
+    ni(8715),
+    prod(8719),
+    sum(8721),
+    minus(8722),
+    lowast(8727),
+    radic(8730),
+    prop(8733),
+    infin(8734),
+    ang(8736),
+    and(8743),
+    or(8744),
+    cap(8745),
+    cup(8746),
+    _int(8747),
+    there4(8756),
+    sim(8764),
+    cong(8773),
+    asymp(8776),
+    ne(8800),
+    equiv(8801),
+    le(8804),
+    ge(8805),
+    sub(8834),
+    sup(8835),
+    nsub(8836),
+    sube(8838),
+    supe(8839),
+    oplus(8853),
+    otimes(8855),
+    perp(8869),
+    sdot(8901),
+    lceil(8968),
+    rceil(8969),
+    lfloor(8970),
+    rfloor(8971),
+    lang(9001),
+    rang(9002),
+    loz(9674),
+    spades(9824),
+    clubs(9827),
+    hearts(9829),
+    diams(9830),
+    quot(34),
+    amp(38),
+    lt(60),
+    gt(62),
+    OElig(338),
+    oelig(339),
+    Scaron(352),
+    scaron(353),
+    Yuml(376),
+    circ(710),
+    tilde(732),
+    ensp(8194),
+    emsp(8195),
+    thinsp(8201),
+    zwnj(8204),
+    zwj(8205),
+    lrm(8206),
+    rlm(8207),
+    ndash(8211),
+    mdash(8212),
+    lsquo(8216),
+    rsquo(8217),
+    sbquo(8218),
+    ldquo(8220),
+    rdquo(8221),
+    bdquo(8222),
+    dagger(8224),
+    Dagger(8225),
+    permil(8240),
+    lsaquo(8249),
+    rsaquo(8250),
+    euro(8364);
+
+    int code;
+
+    private Entity(int code) {
+        this.code = code;
+    }
+
+    static boolean isValid(String name) {
+        return names.containsKey(name);
+    }
+
+    static boolean isValid(int code) {
+        // allow numeric codes for standard ANSI characters
+        return codes.containsKey(code) || ( 32 <= code && code < 2127);
+    }
+
+    private static final Map<String,Entity> names = new HashMap<String,Entity>();
+    private static final Map<Integer,Entity> codes = new HashMap<Integer,Entity>();
+    static {
+        for (Entity e: values()) {
+            String name = e.name();
+            int code = e.code;
+            if (name.startsWith("_")) name = name.substring(1);
+            names.put(name, e);
+            codes.put(code, e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/doclint/Env.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.doclint;
+
+
+import java.util.Set;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
+
+import com.sun.source.doctree.DocCommentTree;
+import com.sun.source.util.DocTrees;
+import com.sun.source.util.JavacTask;
+import com.sun.source.util.SourcePositions;
+import com.sun.source.util.TreePath;
+import com.sun.tools.javac.model.JavacTypes;
+import com.sun.tools.javac.tree.JCTree;
+
+/**
+ * Utility container for current execution environment,
+ * providing the current declaration and its doc comment.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own
+ * risk.  This code and its internal interfaces are subject to change
+ * or deletion without notice.</b></p>
+ */
+public class Env {
+    /**
+     * Access kinds for declarations.
+     */
+    public enum AccessKind {
+        PRIVATE,
+        PACKAGE,
+        PROTECTED,
+        PUBLIC;
+
+        static boolean accepts(String opt) {
+            for (AccessKind g: values())
+                if (opt.equals(g.name().toLowerCase())) return true;
+            return false;
+        }
+
+        static AccessKind of(Set<Modifier> mods) {
+            if (mods.contains(Modifier.PUBLIC))
+                return AccessKind.PUBLIC;
+            else if (mods.contains(Modifier.PROTECTED))
+                return AccessKind.PROTECTED;
+            else if (mods.contains(Modifier.PRIVATE))
+                return AccessKind.PRIVATE;
+            else
+                return AccessKind.PACKAGE;
+        }
+    };
+
+    /** Message handler. */
+    final Messages messages;
+
+    // Utility classes
+    DocTrees trees;
+    Elements elements;
+    Types types;
+
+    // Types used when analysing doc comments.
+    TypeMirror java_lang_Error;
+    TypeMirror java_lang_RuntimeException;
+    TypeMirror java_lang_Throwable;
+    TypeMirror java_lang_Void;
+
+    /** The path for the declaration containing the comment currently being analyzed. */
+    TreePath currPath;
+    /** The element for the declaration containing the comment currently being analyzed. */
+    Element currElement;
+    /** The comment current being analyzed. */
+    DocCommentTree currDocComment;
+    /**
+     * The access kind of the declaration containing the comment currently being analyzed.
+     * This is the minimum (most restrictive) access kind of the declaration iteself
+     * and that of its containers. For example, a public method in a private class is
+     * noted as private.
+     */
+    AccessKind currAccess;
+    /** The set of methods, if any, that the current declaration overrides. */
+    Set<? extends ExecutableElement> currOverriddenMethods;
+
+    Env() {
+        messages = new Messages(this);
+    }
+
+    void init(JavacTask task) {
+        init(DocTrees.instance(task), task.getElements(), task.getTypes());
+    }
+
+    void init(DocTrees trees, Elements elements, Types types) {
+        this.trees = trees;
+        this.elements = elements;
+        this.types = types;
+        java_lang_Error = elements.getTypeElement("java.lang.Error").asType();
+        java_lang_RuntimeException = elements.getTypeElement("java.lang.RuntimeException").asType();
+        java_lang_Throwable = elements.getTypeElement("java.lang.Throwable").asType();
+        java_lang_Void = elements.getTypeElement("java.lang.Void").asType();
+    }
+
+    /** Set the current declaration and its doc comment. */
+    void setCurrent(TreePath path, DocCommentTree comment) {
+        currPath = path;
+        currDocComment = comment;
+        currElement = trees.getElement(currPath);
+        currOverriddenMethods = ((JavacTypes) types).getOverriddenMethods(currElement);
+
+        AccessKind ak = null;
+        for (TreePath p = path; p != null; p = p.getParentPath()) {
+            Element e = trees.getElement(p);
+            if (e != null) {
+                ak = min(ak, AccessKind.of(e.getModifiers()));
+            }
+        }
+        currAccess = ak;
+    }
+
+    AccessKind getAccessKind() {
+        return currAccess;
+    }
+
+    long getPos(TreePath p) {
+        return ((JCTree) p.getLeaf()).pos;
+    }
+
+    long getStartPos(TreePath p) {
+        SourcePositions sp = trees.getSourcePositions();
+        return sp.getStartPosition(p.getCompilationUnit(), p.getLeaf());
+    }
+
+    private <T extends Comparable<T>> T min(T item1, T item2) {
+        return (item1 == null) ? item2
+                : (item2 == null) ? item1
+                : item1.compareTo(item2) <= 0 ? item1 : item2;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/doclint/HtmlTag.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.doclint;
+
+import java.util.Set;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.lang.model.element.Name;
+
+import static com.sun.tools.doclint.HtmlTag.Attr.*;
+
+/**
+ * Enum representing HTML tags.
+ *
+ * The intent of this class is to embody the semantics of W3C HTML 4.01
+ * to the extent supported/used by javadoc.
+ *
+ * This is derivative of com.sun.tools.doclets.formats.html.markup.HtmlTag.
+ * Eventually, these two should be merged back together, and possibly made
+ * public.
+ *
+ * @see <a href="http://www.w3.org/TR/REC-html40/">HTML 4.01 Specification</a>
+ * @author Bhavesh Patel
+ * @author Jonathan Gibbons (revised)
+ */
+public enum HtmlTag {
+    A(BlockType.INLINE, EndKind.REQUIRED,
+            attrs(AttrKind.OK, HREF, TARGET, NAME)),
+
+    B(BlockType.INLINE, EndKind.REQUIRED,
+            EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
+
+    BLOCKQUOTE,
+
+    BODY(BlockType.OTHER, EndKind.REQUIRED),
+
+    BR(BlockType.INLINE, EndKind.NONE,
+            attrs(AttrKind.USE_CSS, CLEAR)),
+
+    CAPTION(EnumSet.of(Flag.EXPECT_CONTENT)),
+
+    CENTER,
+
+    CITE(BlockType.INLINE, EndKind.REQUIRED,
+            EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
+
+    CODE(BlockType.INLINE, EndKind.REQUIRED,
+            EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
+
+    DD(BlockType.BLOCK, EndKind.OPTIONAL,
+            EnumSet.of(Flag.EXPECT_CONTENT)),
+
+    DIV,
+
+    DL(BlockType.BLOCK, EndKind.REQUIRED,
+            EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_TEXT),
+            attrs(AttrKind.USE_CSS, COMPACT)),
+
+    DT(BlockType.BLOCK, EndKind.OPTIONAL,
+            EnumSet.of(Flag.EXPECT_CONTENT)),
+
+    EM(BlockType.INLINE, EndKind.REQUIRED,
+            EnumSet.of(Flag.NO_NEST)),
+
+    FONT(BlockType.INLINE, EndKind.REQUIRED, // tag itself is deprecated
+            EnumSet.of(Flag.EXPECT_CONTENT),
+            attrs(AttrKind.USE_CSS, SIZE, COLOR, FACE)),
+
+    FRAME(BlockType.OTHER, EndKind.NONE),
+
+    FRAMESET(BlockType.OTHER, EndKind.REQUIRED),
+
+    H1,
+    H2,
+    H3,
+    H4,
+    H5,
+    H6,
+
+    HEAD(BlockType.OTHER, EndKind.REQUIRED),
+
+    HR(BlockType.BLOCK, EndKind.NONE),
+
+    HTML(BlockType.OTHER, EndKind.REQUIRED),
+
+    I(BlockType.INLINE, EndKind.REQUIRED,
+            EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
+
+    IMG(BlockType.INLINE, EndKind.NONE,
+            attrs(AttrKind.OK, SRC, ALT, HEIGHT, WIDTH),
+            attrs(AttrKind.OBSOLETE, NAME),
+            attrs(AttrKind.USE_CSS, ALIGN, HSPACE, VSPACE, BORDER)),
+
+    LI(BlockType.BLOCK, EndKind.OPTIONAL),
+
+    LINK(BlockType.OTHER, EndKind.NONE),
+
+    MENU,
+
+    META(BlockType.OTHER, EndKind.NONE),
+
+    NOFRAMES(BlockType.OTHER, EndKind.REQUIRED),
+
+    NOSCRIPT(BlockType.OTHER, EndKind.REQUIRED),
+
+    OL(BlockType.BLOCK, EndKind.REQUIRED,
+            EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_TEXT),
+            attrs(AttrKind.USE_CSS, START, TYPE)),
+
+    P(BlockType.BLOCK, EndKind.OPTIONAL,
+            EnumSet.of(Flag.EXPECT_CONTENT),
+            attrs(AttrKind.USE_CSS, ALIGN)),
+
+    PRE(EnumSet.of(Flag.EXPECT_CONTENT)),
+
+    SCRIPT(BlockType.OTHER, EndKind.REQUIRED),
+
+    SMALL(BlockType.INLINE, EndKind.REQUIRED),
+
+    SPAN(BlockType.INLINE, EndKind.REQUIRED,
+            EnumSet.of(Flag.EXPECT_CONTENT)),
+
+    STRONG(BlockType.INLINE, EndKind.REQUIRED,
+            EnumSet.of(Flag.EXPECT_CONTENT)),
+
+    SUB(BlockType.INLINE, EndKind.REQUIRED,
+            EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
+
+    SUP(BlockType.INLINE, EndKind.REQUIRED,
+            EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
+
+    TABLE(BlockType.BLOCK, EndKind.REQUIRED,
+            EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_TEXT),
+            attrs(AttrKind.OK, SUMMARY, Attr.FRAME, RULES, BORDER,
+                CELLPADDING, CELLSPACING),
+            attrs(AttrKind.USE_CSS, ALIGN, WIDTH, BGCOLOR)),
+
+    TBODY(BlockType.BLOCK, EndKind.REQUIRED,
+            EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_TEXT),
+            attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)),
+
+    TD(BlockType.BLOCK, EndKind.OPTIONAL,
+            attrs(AttrKind.OK, COLSPAN, ROWSPAN, HEADERS, SCOPE, ABBR, AXIS,
+                ALIGN, CHAR, CHAROFF, VALIGN),
+            attrs(AttrKind.USE_CSS, WIDTH, BGCOLOR, HEIGHT, NOWRAP)),
+
+    TFOOT(BlockType.BLOCK, EndKind.REQUIRED,
+            attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)),
+
+    TH(BlockType.BLOCK, EndKind.OPTIONAL,
+            attrs(AttrKind.OK, COLSPAN, ROWSPAN, HEADERS, SCOPE, ABBR, AXIS,
+                ALIGN, CHAR, CHAROFF, VALIGN),
+            attrs(AttrKind.USE_CSS, WIDTH, BGCOLOR, HEIGHT, NOWRAP)),
+
+    THEAD(BlockType.BLOCK, EndKind.REQUIRED,
+            attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)),
+
+    TITLE(BlockType.OTHER, EndKind.REQUIRED),
+
+    TR(BlockType.BLOCK, EndKind.OPTIONAL,
+            EnumSet.of(Flag.NO_TEXT),
+            attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN),
+            attrs(AttrKind.USE_CSS, BGCOLOR)),
+
+    TT(BlockType.INLINE, EndKind.REQUIRED,
+            EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
+
+    U(BlockType.INLINE, EndKind.REQUIRED,
+            EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
+
+    UL(BlockType.BLOCK, EndKind.REQUIRED,
+            EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_TEXT),
+            attrs(AttrKind.USE_CSS, COMPACT, TYPE)),
+
+    VAR(BlockType.INLINE, EndKind.REQUIRED);
+
+    /**
+     * Enum representing the type of HTML element.
+     */
+    public static enum BlockType {
+        BLOCK,
+        INLINE,
+        OTHER;
+    }
+
+    /**
+     * Enum representing HTML end tag requirement.
+     */
+    public static enum EndKind {
+        NONE,
+        OPTIONAL,
+        REQUIRED;
+    }
+
+    public static enum Flag {
+        EXPECT_CONTENT,
+        NO_NEST,
+        NO_TEXT
+    }
+
+    public static enum Attr {
+        ABBR,
+        ALIGN,
+        ALT,
+        AXIS,
+        BGCOLOR,
+        BORDER,
+        CELLSPACING,
+        CELLPADDING,
+        CHAR,
+        CHAROFF,
+        CLEAR,
+        CLASS,
+        COLOR,
+        COLSPAN,
+        COMPACT,
+        FACE,
+        FRAME,
+        HEADERS,
+        HEIGHT,
+        HREF,
+        HSPACE,
+        ID,
+        NAME,
+        NOWRAP,
+        REVERSED,
+        ROWSPAN,
+        RULES,
+        SCOPE,
+        SIZE,
+        SPACE,
+        SRC,
+        START,
+        STYLE,
+        SUMMARY,
+        TARGET,
+        TYPE,
+        VALIGN,
+        VSPACE,
+        WIDTH;
+
+        public String getText() {
+            return name().toLowerCase();
+        }
+
+        static final Map<String,Attr> index = new HashMap<String,Attr>();
+        static {
+            for (Attr t: values()) {
+                index.put(t.name().toLowerCase(), t);
+            }
+        }
+    }
+
+    public static enum AttrKind {
+        INVALID,
+        OBSOLETE,
+        USE_CSS,
+        OK
+    }
+
+    // This class exists to avoid warnings from using parameterized vararg type
+    // Map<Attr,AttrKind> in signature of HtmlTag constructor.
+    private static class AttrMap extends EnumMap<Attr,AttrKind>  {
+        private static final long serialVersionUID = 0;
+        AttrMap() {
+            super(Attr.class);
+        }
+    }
+
+
+    public final BlockType blockType;
+    public final EndKind endKind;
+    public final Set<Flag> flags;
+    private final Map<Attr,AttrKind> attrs;
+
+
+    HtmlTag() {
+        this(BlockType.BLOCK, EndKind.REQUIRED);
+    }
+
+    HtmlTag(Set<Flag> flags) {
+        this(BlockType.BLOCK, EndKind.REQUIRED, flags);
+    }
+
+    HtmlTag(BlockType blockType, EndKind endKind, AttrMap... attrMaps) {
+        this(blockType, endKind, Collections.<Flag>emptySet(), attrMaps);
+    }
+
+    HtmlTag(BlockType blockType, EndKind endKind, Set<Flag> flags, AttrMap... attrMaps) {
+        this.blockType = blockType;
+        this.endKind = endKind;this.flags = flags;
+        this.attrs = new EnumMap<Attr,AttrKind>(Attr.class);
+        for (Map<Attr,AttrKind> m: attrMaps)
+            this.attrs.putAll(m);
+        attrs.put(Attr.CLASS, AttrKind.OK);
+        attrs.put(Attr.ID, AttrKind.OK);
+        attrs.put(Attr.STYLE, AttrKind.OK);
+    }
+
+    public String getText() {
+        return name().toLowerCase();
+    }
+
+    public Attr getAttr(Name attrName) {
+        return Attr.index.get(attrName.toString().toLowerCase());
+    }
+
+    public AttrKind getAttrKind(Name attrName) {
+        AttrKind k = attrs.get(getAttr(attrName)); // null-safe
+        return (k == null) ? AttrKind.INVALID : k;
+    }
+
+    private static AttrMap attrs(AttrKind k, Attr... attrs) {
+        AttrMap map = new AttrMap();
+        for (Attr a: attrs) map.put(a, k);
+        return map;
+    }
+
+    private static final Map<String,HtmlTag> index = new HashMap<String,HtmlTag>();
+    static {
+        for (HtmlTag t: values()) {
+            index.put(t.name().toLowerCase(), t);
+        }
+    }
+
+    static HtmlTag get(Name tagName) {
+        return index.get(tagName.toString().toLowerCase());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/doclint/Messages.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,348 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.doclint;
+
+import java.io.PrintWriter;
+import java.text.MessageFormat;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import javax.tools.Diagnostic;
+
+import com.sun.source.doctree.DocTree;
+import com.sun.source.tree.Tree;
+import com.sun.tools.doclint.Env.AccessKind;
+
+/**
+ * Message reporting for DocLint.
+ *
+ * Options are used to filter out messages based on group and access level.
+ * Support can be enabled for accumulating statistics of different kinds of
+ * messages.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own
+ * risk.  This code and its internal interfaces are subject to change
+ * or deletion without notice.</b></p>
+ */
+public class Messages {
+    /**
+     * Groups used to categorize messages, so that messages in each group
+     * can be enabled or disabled via options.
+     */
+    public enum Group {
+        ACCESSIBILITY,
+        HTML,
+        MISSING,
+        SYNTAX,
+        REFERENCE;
+
+        String optName() { return name().toLowerCase(); }
+        String notOptName() { return "-" + optName(); }
+
+        static boolean accepts(String opt) {
+            for (Group g: values())
+                if (opt.equals(g.optName())) return true;
+            return false;
+        }
+    };
+
+    private final Options options;
+    private final Stats stats;
+
+    ResourceBundle bundle;
+    Env env;
+
+    Messages(Env env) {
+        this.env = env;
+        String name = getClass().getPackage().getName() + ".resources.doclint";
+        bundle = ResourceBundle.getBundle(name, Locale.ENGLISH);
+
+        stats = new Stats(bundle);
+        options = new Options(stats);
+    }
+
+    void error(Group group, DocTree tree, String code, Object... args) {
+        report(group, Diagnostic.Kind.ERROR, tree, code, args);
+    }
+
+    void warning(Group group, DocTree tree, String code, Object... args) {
+        report(group, Diagnostic.Kind.WARNING, tree, code, args);
+    }
+
+    void setOptions(String opts) {
+        options.setOptions(opts);
+    }
+
+    void setStatsEnabled(boolean b) {
+        stats.setEnabled(b);
+    }
+
+    void reportStats(PrintWriter out) {
+        stats.report(out);
+    }
+
+    protected void report(Group group, Diagnostic.Kind dkind, DocTree tree, String code, Object... args) {
+        if (options.isEnabled(group, env.currAccess)) {
+            String msg = (code == null) ? (String) args[0] : localize(code, args);
+            env.trees.printMessage(dkind, msg, tree,
+                    env.currDocComment, env.currPath.getCompilationUnit());
+
+            stats.record(group, dkind, code);
+        }
+    }
+
+    protected void report(Group group, Diagnostic.Kind dkind, Tree tree, String code, Object... args) {
+        if (options.isEnabled(group, env.currAccess)) {
+            String msg = localize(code, args);
+            env.trees.printMessage(dkind, msg, tree, env.currPath.getCompilationUnit());
+
+            stats.record(group, dkind, code);
+        }
+    }
+
+    String localize(String code, Object... args) {
+        String msg = bundle.getString(code);
+        if (msg == null) {
+            StringBuilder sb = new StringBuilder();
+            sb.append("message file broken: code=").append(code);
+            if (args.length > 0) {
+                sb.append(" arguments={0}");
+                for (int i = 1; i < args.length; i++) {
+                    sb.append(", {").append(i).append("}");
+                }
+            }
+            msg = sb.toString();
+        }
+        return MessageFormat.format(msg, args);
+    }
+
+    // <editor-fold defaultstate="collapsed" desc="Options">
+
+    /**
+     * Handler for (sub)options specific to message handling.
+     */
+    static class Options {
+        Map<String, Env.AccessKind> map = new HashMap<String, Env.AccessKind>();
+        private final Stats stats;
+
+        static boolean isValidOptions(String opts) {
+            for (String opt: opts.split(",")) {
+                if (!isValidOption(opt.trim().toLowerCase()))
+                    return false;
+            }
+            return true;
+        }
+
+        private static boolean isValidOption(String opt) {
+            if (opt.equals("none") || opt.equals(Stats.OPT))
+                return true;
+
+            int begin = opt.startsWith("-") ? 1 : 0;
+            int sep = opt.indexOf("/");
+            String grp = opt.substring(begin, (sep != -1) ? sep : opt.length());
+            return ((begin == 0 && grp.equals("all")) || Group.accepts(grp))
+                    && ((sep == -1) || AccessKind.accepts(opt.substring(sep + 1)));
+        }
+
+        Options(Stats stats) {
+            this.stats = stats;
+        }
+
+        /** Determine if a message group is enabled for a particular access level. */
+        boolean isEnabled(Group g, Env.AccessKind access) {
+            if (map.isEmpty())
+                map.put("all", Env.AccessKind.PROTECTED);
+
+            Env.AccessKind ak = map.get(g.optName());
+            if (ak != null && access.compareTo(ak) >= 0)
+                return true;
+
+            ak = map.get(ALL);
+            if (ak != null && access.compareTo(ak) >= 0) {
+                ak = map.get(g.notOptName());
+                if (ak == null || access.compareTo(ak) > 0) // note >, not >=
+                    return true;
+            }
+
+            return false;
+        }
+
+        void setOptions(String opts) {
+            if (opts == null)
+                setOption(ALL, Env.AccessKind.PRIVATE);
+            else {
+                for (String opt: opts.split(","))
+                    setOption(opt.trim().toLowerCase());
+            }
+        }
+
+        private void setOption(String arg) throws IllegalArgumentException {
+            if (arg.equals(Stats.OPT)) {
+                stats.setEnabled(true);
+                return;
+            }
+
+            int sep = arg.indexOf("/");
+            if (sep > 0) {
+                Env.AccessKind ak = Env.AccessKind.valueOf(arg.substring(sep + 1).toUpperCase());
+                setOption(arg.substring(0, sep), ak);
+            } else {
+                setOption(arg, null);
+            }
+        }
+
+        private void setOption(String opt, Env.AccessKind ak) {
+            map.put(opt, (ak != null) ? ak
+                    : opt.startsWith("-") ? Env.AccessKind.PUBLIC : Env.AccessKind.PRIVATE);
+        }
+
+        private static final String ALL = "all";
+    }
+
+    // </editor-fold>
+
+    // <editor-fold defaultstate="collapsed" desc="Statistics">
+
+    /**
+     * Optionally record statistics of different kinds of message.
+     */
+    static class Stats {
+        public static final String OPT = "stats";
+        public static final String NO_CODE = "";
+        final ResourceBundle bundle;
+
+        // tables only initialized if enabled
+        int[] groupCounts;
+        int[] dkindCounts;
+        Map<String, Integer> codeCounts;
+
+        Stats(ResourceBundle bundle) {
+            this.bundle = bundle;
+        }
+
+        void setEnabled(boolean b) {
+            if (b) {
+                groupCounts = new int[Messages.Group.values().length];
+                dkindCounts = new int[Diagnostic.Kind.values().length];
+                codeCounts = new HashMap<String, Integer>();
+            } else {
+                groupCounts = null;
+                dkindCounts = null;
+                codeCounts = null;
+            }
+        }
+
+        void record(Messages.Group g, Diagnostic.Kind dkind, String code) {
+            if (codeCounts == null) {
+                return;
+            }
+            groupCounts[g.ordinal()]++;
+            dkindCounts[dkind.ordinal()]++;
+            if (code == null) {
+                code = NO_CODE;
+            }
+            Integer i = codeCounts.get(code);
+            codeCounts.put(code, (i == null) ? 1 : i + 1);
+        }
+
+        void report(PrintWriter out) {
+            if (codeCounts == null) {
+                return;
+            }
+            out.println("By group...");
+            Table groupTable = new Table();
+            for (Messages.Group g : Messages.Group.values()) {
+                groupTable.put(g.optName(), groupCounts[g.ordinal()]);
+            }
+            groupTable.print(out);
+            out.println();
+            out.println("By diagnostic kind...");
+            Table dkindTable = new Table();
+            for (Diagnostic.Kind k : Diagnostic.Kind.values()) {
+                dkindTable.put(k.toString().toLowerCase(), dkindCounts[k.ordinal()]);
+            }
+            dkindTable.print(out);
+            out.println();
+            out.println("By message kind...");
+            Table codeTable = new Table();
+            for (Map.Entry<String, Integer> e : codeCounts.entrySet()) {
+                String code = e.getKey();
+                String msg;
+                try {
+                    msg = code.equals(NO_CODE) ? "OTHER" : bundle.getString(code);
+                } catch (MissingResourceException ex) {
+                    msg = code;
+                }
+                codeTable.put(msg, e.getValue());
+            }
+            codeTable.print(out);
+        }
+
+        /**
+         * A table of (int, String) sorted by decreasing int.
+         */
+        private static class Table {
+
+            private static final Comparator<Integer> DECREASING = new Comparator<Integer>() {
+
+                public int compare(Integer o1, Integer o2) {
+                    return o2.compareTo(o1);
+                }
+            };
+            private final TreeMap<Integer, Set<String>> map = new TreeMap<Integer, Set<String>>(DECREASING);
+
+            void put(String label, int n) {
+                if (n == 0) {
+                    return;
+                }
+                Set<String> labels = map.get(n);
+                if (labels == null) {
+                    map.put(n, labels = new TreeSet<String>());
+                }
+                labels.add(label);
+            }
+
+            void print(PrintWriter out) {
+                for (Map.Entry<Integer, Set<String>> e : map.entrySet()) {
+                    int count = e.getKey();
+                    Set<String> labels = e.getValue();
+                    for (String label : labels) {
+                        out.println(String.format("%6d: %s", count, label));
+                    }
+                }
+            }
+        }
+    }
+    // </editor-fold>
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/doclint/resources/doclint.properties	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,65 @@
+#
+# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+dc.anchor.already.defined = anchor already defined: {0}
+dc.attr.lacks.value = attribute lacks value
+dc.attr.obsolete = attribute obsolete: {0}
+dc.attr.obsolete.use.css = attribute obsolete, use CSS instead: {0}
+dc.attr.repeated = repeated attribute: {0}
+dc.attr.unknown = unknown attribute: {0}
+dc.bad.option = bad option: {0}
+dc.bad.value.for.option = bad value for option: {0} {1}
+dc.empty = no description for @{0}
+dc.entity.invalid = invalid entity &{0};
+dc.exception.not.thrown = exception not thrown: {0}
+dc.invalid.anchor = invalid name for anchor: "{0}"
+dc.invalid.param = invalid use of @param
+dc.invalid.return = invalid use of @return
+dc.invalid.throws = invalid use of @throws
+dc.invalid.uri = invalid uri: "{0}"
+dc.missing.comment = no comment
+dc.missing.param = no @param for {0}
+dc.missing.return = no @return
+dc.missing.throws = no @throws for {0}
+dc.no.alt.attr.for.image = no "alt" attribute for image
+dc.no.summary.or.caption.for.table=no summary or caption for table
+dc.param.name.not.found = @param name not found
+dc.ref.not.found = reference not found
+dc.tag.empty = empty <{0}> tag
+dc.tag.end.not.permitted = invalid end tag: </{0}>
+dc.tag.end.unexpected = unexpected end tag: </{0}>
+dc.tag.header.sequence.1 = header used out of sequence: <{0}>
+dc.tag.header.sequence.2 = header used out of sequence: <{0}>
+dc.tag.nested.not.allowed=nested tag not allowed: <{0}>
+dc.tag.not.allowed = element not allowed in documentation comments: <{0}>
+dc.tag.not.allowed.inline.element = block element not allowed within inline element <{1}>: {0}
+dc.tag.not.allowed.inline.tag = block element not allowed within @{1}: {0}
+dc.tag.not.allowed.inline.other = block element not allowed here: {0}
+dc.tag.not.closed= element not closed: {0}
+dc.tag.p.in.pre= unexpected use of <p> inside <pre> element
+dc.tag.self.closing = self-closing element not allowed
+dc.tag.start.unmatched = end tag missing: </{0}>
+dc.tag.unknown = unknown tag: {0}
+dc.text.not.allowed = text not allowed in <{0}> element
--- a/langtools/src/share/classes/com/sun/tools/javac/api/BasicJavacTask.java	Mon Dec 17 14:54:42 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/api/BasicJavacTask.java	Mon Dec 17 07:47:05 2012 -0800
@@ -57,6 +57,13 @@
     protected Context context;
     private TaskListener taskListener;
 
+    public static JavacTask instance(Context context) {
+        JavacTask instance = context.get(JavacTask.class);
+        if (instance == null)
+            instance = new BasicJavacTask(context, true);
+        return instance;
+    }
+
     public BasicJavacTask(Context c, boolean register) {
         context = c;
         if (register)
--- a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java	Mon Dec 17 14:54:42 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java	Mon Dec 17 07:47:05 2012 -0800
@@ -65,7 +65,6 @@
  * @author Jonathan Gibbons
  */
 public class JavacTaskImpl extends BasicJavacTask {
-    private ClientCodeWrapper ccw;
     private Main compilerMain;
     private JavaCompiler compiler;
     private Locale locale;
@@ -85,7 +84,6 @@
                 Context context,
                 List<JavaFileObject> fileObjects) {
         super(null, false);
-        this.ccw = ClientCodeWrapper.instance(context);
         this.compilerMain = compilerMain;
         this.args = args;
         this.classNames = classNames;
--- a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java	Mon Dec 17 14:54:42 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java	Mon Dec 17 07:47:05 2012 -0800
@@ -84,6 +84,7 @@
 import com.sun.tools.javac.tree.TreeCopier;
 import com.sun.tools.javac.tree.TreeInfo;
 import com.sun.tools.javac.tree.TreeMaker;
+import com.sun.tools.javac.util.Abort;
 import com.sun.tools.javac.util.Assert;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.JCDiagnostic;
@@ -236,19 +237,26 @@
     public Element getElement(TreePath path) {
         JCTree tree = (JCTree) path.getLeaf();
         Symbol sym = TreeInfo.symbolFor(tree);
-        if (sym == null && TreeInfo.isDeclaration(tree)) {
-            for (TreePath p = path; p != null; p = p.getParentPath()) {
-                JCTree t = (JCTree) p.getLeaf();
-                if (t.hasTag(JCTree.Tag.CLASSDEF)) {
-                    JCClassDecl ct = (JCClassDecl) t;
-                    if (ct.sym != null) {
-                        if ((ct.sym.flags_field & Flags.UNATTRIBUTED) != 0) {
-                            attr.attribClass(ct.pos(), ct.sym);
-                            sym = TreeInfo.symbolFor(tree);
+        if (sym == null) {
+            if (TreeInfo.isDeclaration(tree)) {
+                for (TreePath p = path; p != null; p = p.getParentPath()) {
+                    JCTree t = (JCTree) p.getLeaf();
+                    if (t.hasTag(JCTree.Tag.CLASSDEF)) {
+                        JCClassDecl ct = (JCClassDecl) t;
+                        if (ct.sym != null) {
+                            if ((ct.sym.flags_field & Flags.UNATTRIBUTED) != 0) {
+                                attr.attribClass(ct.pos(), ct.sym);
+                                sym = TreeInfo.symbolFor(tree);
+                            }
+                            break;
                         }
-                        break;
                     }
                 }
+            } else if (tree.hasTag(Tag.TOPLEVEL)) {
+                JCCompilationUnit cu = (JCCompilationUnit) tree;
+                if (cu.sourcefile.isNameCompatible("package-info", JavaFileObject.Kind.SOURCE)) {
+                    sym = cu.packge;
+                }
             }
         }
         return sym;
@@ -332,6 +340,8 @@
             } else {
                 return msym;
             }
+        } catch (Abort e) { // may be thrown by Check.completionError in case of bad class file
+            return null;
         } finally {
             log.popDiagnosticHandler(deferredDiagnosticHandler);
         }
--- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Mon Dec 17 14:54:42 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Mon Dec 17 07:47:05 2012 -0800
@@ -1675,7 +1675,7 @@
 
     /** Print numbers of errors and warnings.
      */
-    protected void printCount(String kind, int count) {
+    public void printCount(String kind, int count) {
         if (count != 0) {
             String key;
             if (count == 1)
--- a/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java	Mon Dec 17 14:54:42 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java	Mon Dec 17 07:47:05 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,11 +25,16 @@
 
 package com.sun.tools.javac.model;
 
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
-import java.util.EnumSet;
+
 import javax.lang.model.element.*;
 import javax.lang.model.type.*;
+
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.util.*;
@@ -301,4 +306,31 @@
             throw new IllegalArgumentException(o.toString());
         return clazz.cast(o);
     }
+
+    public Set<MethodSymbol> getOverriddenMethods(Element elem) {
+        if (elem.getKind() != ElementKind.METHOD
+                || elem.getModifiers().contains(Modifier.STATIC)
+                || elem.getModifiers().contains(Modifier.PRIVATE))
+            return Collections.emptySet();
+
+        if (!(elem instanceof MethodSymbol))
+            throw new IllegalArgumentException();
+
+        MethodSymbol m = (MethodSymbol) elem;
+        ClassSymbol origin = (ClassSymbol) m.owner;
+
+        Set<MethodSymbol> results = new LinkedHashSet<MethodSymbol>();
+        for (Type t : types.closure(origin.type)) {
+            if (t != origin.type) {
+                ClassSymbol c = (ClassSymbol) t.tsym;
+                for (Scope.Entry e = c.members().lookup(m.name); e.scope != null; e = e.next()) {
+                    if (e.sym.kind == Kinds.MTH && m.overrides(e.sym, origin, types, true)) {
+                        results.add((MethodSymbol) e.sym);
+                    }
+                }
+            }
+        }
+
+        return results;
+    }
 }
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/DocCommentParser.java	Mon Dec 17 14:54:42 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/DocCommentParser.java	Mon Dec 17 07:47:05 2012 -0800
@@ -25,15 +25,12 @@
 
 package com.sun.tools.javac.parser;
 
-import com.sun.tools.javac.util.Filter;
 import java.text.BreakIterator;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.LinkedList;
 import java.util.Locale;
 import java.util.Map;
-import java.util.Queue;
 import java.util.Set;
 
 import com.sun.source.doctree.AttributeTree.ValueKind;
@@ -52,7 +49,6 @@
 import com.sun.tools.javac.tree.DocTreeMaker;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.util.DiagnosticSource;
-import com.sun.tools.javac.util.JCDiagnostic;
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.ListBuffer;
 import com.sun.tools.javac.util.Log;
@@ -736,7 +732,9 @@
             nextChar();
             return m.at(p).Entity(names.fromChars(buf, namep, bp - namep - 1));
         } else {
-            String code = checkSemi ? "dc.missing.semicolon" : "dc.bad.entity";
+            String code = checkSemi
+                    ? "dc.missing.semicolon"
+                    : "dc.bad.entity";
             return erroneous(code, p);
         }
     }
@@ -888,8 +886,10 @@
     }
 
     protected void addPendingText(ListBuffer<DCTree> list, int textEnd) {
-        if (textStart != -1 && textStart <= textEnd) {
-            list.add(m.at(textStart).Text(newString(textStart, textEnd + 1)));
+        if (textStart != -1) {
+            if (textStart <= textEnd) {
+                list.add(m.at(textStart).Text(newString(textStart, textEnd + 1)));
+            }
             textStart = -1;
         }
     }
@@ -1196,6 +1196,16 @@
                                 return m.at(pos).See(html);
                             break;
 
+                        case '@':
+                            if (newline)
+                                throw new ParseException("dc.no.content");
+                            break;
+
+                        case EOI:
+                            if (bp == buf.length - 1)
+                                throw new ParseException("dc.no.content");
+                            break;
+
                         default:
                             if (isJavaIdentifierStart(ch) || ch == '#') {
                                 DCReference ref = reference(true);
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Dec 17 14:54:42 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Dec 17 07:47:05 2012 -0800
@@ -2364,6 +2364,9 @@
 compiler.err.dc.missing.semicolon=\
     semicolon missing
 
+compiler.err.dc.no.content=\
+    no content
+
 compiler.err.dc.no.tag.name=\
     no tag name after '@'
 
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/DCTree.java	Mon Dec 17 14:54:42 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/DCTree.java	Mon Dec 17 07:47:05 2012 -0800
@@ -36,6 +36,8 @@
 import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.Name;
+import java.io.IOException;
+import java.io.StringWriter;
 import javax.tools.JavaFileObject;
 
 /**
@@ -65,6 +67,21 @@
         return new SimpleDiagnosticPosition(dc.comment.getSourcePos(pos));
     }
 
+    /** Convert a tree to a pretty-printed string. */
+    @Override
+    public String toString() {
+        StringWriter s = new StringWriter();
+        try {
+            new DocPretty(s).print(this);
+        }
+        catch (IOException e) {
+            // should never happen, because StringWriter is defined
+            // never to throw any IOExceptions
+            throw new AssertionError(e);
+        }
+        return s.toString();
+    }
+
     public static class DCDocComment extends DCTree implements DocCommentTree {
         final Comment comment; // required for the implicit source pos table
 
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/DocPretty.java	Mon Dec 17 14:54:42 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/DocPretty.java	Mon Dec 17 07:47:05 2012 -0800
@@ -81,7 +81,7 @@
     /**
      * Print list.
      */
-    protected void print(List<? extends DocTree> list) throws IOException {
+    public void print(List<? extends DocTree> list) throws IOException {
         for (DocTree t: list) {
             print(t);
         }
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Mon Dec 17 14:54:42 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Mon Dec 17 07:47:05 2012 -0800
@@ -26,6 +26,7 @@
 package com.sun.tools.javac.tree;
 
 
+
 import com.sun.source.tree.Tree;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.comp.AttrContext;
@@ -330,6 +331,13 @@
         return (docComments == null) ? null : docComments.getCommentText(tree);
     }
 
+    public static DCTree.DCDocComment getCommentTree(Env<?> env, JCTree tree) {
+        DocCommentTable docComments = (tree.hasTag(JCTree.Tag.TOPLEVEL))
+                ? ((JCCompilationUnit) tree).docComments
+                : env.toplevel.docComments;
+        return (docComments == null) ? null : docComments.getCommentTree(tree);
+    }
+
     /** The position of the first statement in a block, or the position of
      *  the block itself if it is empty.
      */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/AccessTest.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,63 @@
+/*
+ * @test /nodynamiccopyright/
+ * @build DocLintTester
+ * @run main DocLintTester -ref AccessTest.protected.out AccessTest.java
+ * @run main DocLintTester -Xmsgs -ref AccessTest.private.out AccessTest.java
+ * @run main DocLintTester -Xmsgs:syntax -ref AccessTest.private.out AccessTest.java
+ * @run main DocLintTester -Xmsgs:syntax/public -ref AccessTest.public.out AccessTest.java
+ * @run main DocLintTester -Xmsgs:syntax/protected -ref AccessTest.protected.out AccessTest.java
+ * @run main DocLintTester -Xmsgs:syntax/package -ref AccessTest.package.out AccessTest.java
+ * @run main DocLintTester -Xmsgs:syntax/private -ref AccessTest.private.out AccessTest.java
+ * @run main DocLintTester -Xmsgs:all,-syntax AccessTest.java
+ * @run main DocLintTester -Xmsgs:all,-syntax/public AccessTest.java
+ * @run main DocLintTester -Xmsgs:all,-syntax/protected -ref AccessTest.public.out AccessTest.java
+ * @run main DocLintTester -Xmsgs:all,-syntax/package -ref AccessTest.protected.out AccessTest.java
+ * @run main DocLintTester -Xmsgs:all,-syntax/private -ref AccessTest.package.out AccessTest.java
+ */
+
+/** */
+public class AccessTest {
+    /**
+     * public a < b
+     */
+    public void public_syntax_error() { }
+
+    /**
+     * protected a < b
+     */
+    protected void protected_syntax_error() { }
+
+    /**
+     * package-private a < b
+     */
+    void syntax_error() { }
+
+    /**
+     * private a < b
+     */
+    private void private_syntax_error() { }
+}
+
+/** */
+class AccessTest2 {
+    /**
+     * public a < b
+     */
+    public void public_syntax_error() { }
+
+    /**
+     * protected a < b
+     */
+    protected void protected_syntax_error() { }
+
+    /**
+     * package-private a < b
+     */
+    void syntax_error() { }
+
+    /**
+     * private a < b
+     */
+    private void private_syntax_error() { }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/AccessTest.package.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,20 @@
+AccessTest.java:21: error: malformed HTML
+     * public a < b
+                ^
+AccessTest.java:26: error: malformed HTML
+     * protected a < b
+                   ^
+AccessTest.java:31: error: malformed HTML
+     * package-private a < b
+                         ^
+AccessTest.java:44: error: malformed HTML
+     * public a < b
+                ^
+AccessTest.java:49: error: malformed HTML
+     * protected a < b
+                   ^
+AccessTest.java:54: error: malformed HTML
+     * package-private a < b
+                         ^
+6 errors
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/AccessTest.private.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,27 @@
+AccessTest.java:21: error: malformed HTML
+     * public a < b
+                ^
+AccessTest.java:26: error: malformed HTML
+     * protected a < b
+                   ^
+AccessTest.java:31: error: malformed HTML
+     * package-private a < b
+                         ^
+AccessTest.java:36: error: malformed HTML
+     * private a < b
+                 ^
+AccessTest.java:44: error: malformed HTML
+     * public a < b
+                ^
+AccessTest.java:49: error: malformed HTML
+     * protected a < b
+                   ^
+AccessTest.java:54: error: malformed HTML
+     * package-private a < b
+                         ^
+AccessTest.java:59: error: malformed HTML
+     * private a < b
+                 ^
+8 errors
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/AccessTest.protected.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,8 @@
+AccessTest.java:21: error: malformed HTML
+     * public a < b
+                ^
+AccessTest.java:26: error: malformed HTML
+     * protected a < b
+                   ^
+2 errors
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/AccessTest.public.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,5 @@
+AccessTest.java:21: error: malformed HTML
+     * public a < b
+                ^
+1 error
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/AccessibilityTest.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,42 @@
+/*
+ * @test /nodynamiccopyright/
+ * @build DocLintTester
+ * @run main DocLintTester -Xmsgs:-accessibility AccessibilityTest.java
+ * @run main DocLintTester -ref AccessibilityTest.out AccessibilityTest.java
+ */
+
+/** */
+public class AccessibilityTest {
+
+    /**
+     * <h2> ... </h2>
+     */
+    public void missing_h1() { }
+
+    /**
+     * <h1> ... </h1>
+     * <h3> ... </h3>
+     */
+    public void missing_h2() { }
+
+    /**
+     * <img src="x.jpg">
+     */
+    public void missing_alt() { }
+
+    /**
+     * <table summary="ok"><tr><th>head<tr><td>data</table>
+     */
+    public void table_with_summary() { }
+
+    /**
+     * <table><caption>ok</caption><tr><th>head<tr><td>data</table>
+     */
+    public void table_with_caption() { }
+
+    /**
+     * <table><tr><th>head<tr><td>data</table>
+     */
+    public void table_without_summary_and_caption() { }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/AccessibilityTest.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,13 @@
+AccessibilityTest.java:12: error: header used out of sequence: <H2>
+     * <h2> ... </h2>
+       ^
+AccessibilityTest.java:18: error: header used out of sequence: <H3>
+     * <h3> ... </h3>
+       ^
+AccessibilityTest.java:23: error: no "alt" attribute for image
+     * <img src="x.jpg">
+       ^
+AccessibilityTest.java:38: error: no summary or caption for table
+     * <table><tr><th>head<tr><td>data</table>
+                                      ^
+4 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/DocLintTester.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.sun.tools.doclint.DocLint;
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+public class DocLintTester {
+
+    public static void main(String... args) throws Exception {
+        new DocLintTester().run(args);
+    }
+
+    public void run(String... args) throws Exception {
+        String testSrc = System.getProperty("test.src");
+
+        File refFile = null;
+        List<String> opts = new ArrayList<String>();
+        List<File> files = new ArrayList<File>();
+        for (int i = 0; i < args.length; i++) {
+            String arg = args[i];
+            if (arg.equals("-ref")) {
+                refFile = new File(testSrc, args[++i]);
+            } else if (arg.startsWith("-Xmsgs")) {
+                opts.add(arg);
+            } else
+                files.add(new File(testSrc, arg));
+        }
+
+        check(opts, files, refFile);
+
+        if (errors > 0)
+            throw new Exception(errors + " errors occurred");
+    }
+
+    void check(List<String> opts, List<File> files, File refFile) throws Exception {
+        List<String> args = new ArrayList<String>();
+        args.addAll(opts);
+        for (File file: files)
+            args.add(file.getPath());
+
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        new DocLint().run(pw, args.toArray(new String[args.size()]));
+        pw.flush();
+        String out = normalizeNewlines(removeFileNames(sw.toString())).trim();
+        if (out != null)
+            System.err.println("Output:\n" + out);
+
+        if (refFile == null) {
+            if (!out.isEmpty())
+                error("unexpected output");
+        } else {
+            String expect = readFile(refFile);
+            if (!expect.equals(out)) {
+                error("expected output not found");
+                System.err.println("EXPECT>>" + expect + "<<");
+                System.err.println(" FOUND>>" + out    + "<<");
+            }
+        }
+    }
+
+    String readFile(File file) throws IOException {
+        StringBuilder sb = new StringBuilder();
+        Reader in = new BufferedReader(new FileReader(file));
+        try {
+            char[] buf = new char[1024];
+            int n;
+            while ((n = in.read(buf)) != -1)
+                sb.append(buf, 0, n);
+        } finally {
+            in.close();
+        }
+        return sb.toString().trim();
+    }
+
+    private static final Pattern dirFileLine = Pattern.compile(
+            "(?m)"                          // multi-line mode
+            + "^([^: ]+?)"                  // directory part of file name
+            + "([A-Za-z0-9.]+:[0-9]+:)");   // file name and line number
+
+    String removeFileNames(String s) {
+        Matcher m = dirFileLine.matcher(s);
+        StringBuffer sb = new StringBuffer();
+        while (m.find()) {
+            m.appendReplacement(sb, "$2");
+        }
+        m.appendTail(sb);
+        return sb.toString();
+    }
+
+    private static final String nl = System.getProperty("line.separator");
+    String normalizeNewlines(String s) {
+        return (nl.equals("\n") ? s : s.replace(nl, "\n"));
+    }
+
+
+    void error(String msg) {
+        System.err.println("Error: " + msg);
+        errors++;
+    }
+
+    int errors;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/EmptyAuthorTest.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,10 @@
+/*
+ * @test /nodynamiccopyright/
+ * @build DocLintTester
+ * @run main DocLintTester -Xmsgs:-syntax EmptyAuthorTest.java
+ * @run main DocLintTester -Xmsgs:syntax -ref EmptyAuthorTest.out EmptyAuthorTest.java
+ */
+
+/** @author */
+public class EmptyAuthorTest {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/EmptyAuthorTest.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,5 @@
+EmptyAuthorTest.java:8: warning: no description for @author
+/** @author */
+    ^
+1 warning
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/EmptyExceptionTest.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,12 @@
+/*
+ * @test /nodynamiccopyright/
+ * @build DocLintTester
+ * @run main DocLintTester -Xmsgs:-syntax EmptyExceptionTest.java
+ * @run main DocLintTester -Xmsgs:syntax -ref EmptyExceptionTest.out EmptyExceptionTest.java
+ */
+
+/** . */
+public class EmptyExceptionTest {
+    /** @exception NullPointerException */
+    int emptyException() throws NullPointerException { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/EmptyExceptionTest.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,4 @@
+EmptyExceptionTest.java:10: warning: no description for @exception
+    /** @exception NullPointerException */
+        ^
+1 warning
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/EmptyParamTest.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,12 @@
+/*
+ * @test /nodynamiccopyright/
+ * @build DocLintTester
+ * @run main DocLintTester -Xmsgs:-syntax EmptyParamTest.java
+ * @run main DocLintTester -Xmsgs:syntax -ref EmptyParamTest.out EmptyParamTest.java
+ */
+
+/** . */
+public class EmptyParamTest {
+    /** @param i */
+    int emptyParam(int i) { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/EmptyParamTest.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,5 @@
+EmptyParamTest.java:10: warning: no description for @param
+    /** @param i */
+        ^
+1 warning
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/EmptyReturnTest.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,12 @@
+/*
+ * @test /nodynamiccopyright/
+ * @build DocLintTester
+ * @run main DocLintTester -Xmsgs:-syntax EmptyReturnTest.java
+ * @run main DocLintTester -Xmsgs:syntax -ref EmptyReturnTest.out EmptyReturnTest.java
+ */
+
+/** . */
+public class EmptyReturnTest {
+    /** @return */
+    int emptyReturn() { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/EmptyReturnTest.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,5 @@
+EmptyReturnTest.java:10: warning: no description for @return
+    /** @return */
+        ^
+1 warning
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/EmptySerialDataTest.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,15 @@
+/*
+ * @test /nodynamiccopyright/
+ * @build DocLintTester
+ * @run main DocLintTester -Xmsgs:-syntax EmptySerialDataTest.java
+ * @run main DocLintTester -Xmsgs:syntax -ref EmptySerialDataTest.out EmptySerialDataTest.java
+ */
+
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+/** . */
+public class EmptySerialDataTest implements Serializable {
+    /** @serialData */
+    private void writeObject(ObjectOutputStream s) { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/EmptySerialDataTest.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,5 @@
+EmptySerialDataTest.java:13: warning: no description for @serialData
+    /** @serialData */
+        ^
+1 warning
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/EmptySerialFieldTest.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,20 @@
+/*
+ * @test /nodynamiccopyright/
+ * @build DocLintTester
+ * @run main DocLintTester -Xmsgs:-syntax EmptySerialFieldTest.java
+ * @run main DocLintTester -Xmsgs:syntax -ref EmptySerialFieldTest.out EmptySerialFieldTest.java
+ */
+
+import java.io.ObjectStreamField;
+import java.io.Serializable;
+
+/** . */
+public class EmptySerialFieldTest implements Serializable {
+
+    /**
+     * @serialField empty    String
+     */
+    private static final ObjectStreamField[] serialPersistentFields = {
+        new ObjectStreamField("empty", String.class),
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/EmptySerialFieldTest.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,5 @@
+EmptySerialFieldTest.java:15: warning: no description for @serialField
+     * @serialField empty    String
+       ^
+1 warning
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/EmptySinceTest.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,12 @@
+/*
+ * @test /nodynamiccopyright/
+ * @build DocLintTester
+ * @run main DocLintTester -Xmsgs:-syntax EmptySinceTest.java
+ * @run main DocLintTester -Xmsgs:syntax -ref EmptySinceTest.out EmptySinceTest.java
+ */
+
+/** . */
+public class EmptySinceTest {
+    /** @since */
+    int emptySince() { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/EmptySinceTest.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,5 @@
+EmptySinceTest.java:10: warning: no description for @since
+    /** @since */
+        ^
+1 warning
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/EmptyVersionTest.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,12 @@
+/*
+ * @test /nodynamiccopyright/
+ * @build DocLintTester
+ * @run main DocLintTester -Xmsgs:-syntax EmptyVersionTest.java
+ * @run main DocLintTester -Xmsgs:syntax -ref EmptyVersionTest.out EmptyVersionTest.java
+ */
+
+/** . */
+public class EmptyVersionTest {
+    /** @version */
+    int missingVersion() { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/EmptyVersionTest.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,4 @@
+EmptyVersionTest.java:10: warning: no description for @version
+    /** @version */
+        ^
+1 warning
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/HtmlAttrsTest.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,25 @@
+/*
+ * @test /nodynamiccopyright/
+ * @build DocLintTester
+ * @run main DocLintTester -Xmsgs:-html HtmlAttrsTest.java
+ * @run main DocLintTester -ref HtmlAttrsTest.out HtmlAttrsTest.java
+ */
+
+/** */
+public class HtmlAttrsTest {
+    /**
+     * <p xyz>
+     */
+    public void unknown() { }
+
+    /**
+     * <img name="x" alt="alt">
+     */
+    public void obsolete() { }
+
+    /**
+     * <font size="3"> text </font>
+     */
+    public void obsolete_use_css() { }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/HtmlAttrsTest.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,12 @@
+HtmlAttrsTest.java:11: error: unknown attribute: xyz
+     * <p xyz>
+          ^
+HtmlAttrsTest.java:16: warning: attribute obsolete: name
+     * <img name="x" alt="alt">
+            ^
+HtmlAttrsTest.java:21: warning: attribute obsolete, use CSS instead: size
+     * <font size="3"> text </font>
+             ^
+1 error
+2 warnings
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/HtmlTagsTest.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,56 @@
+/*
+ * @test /nodynamiccopyright/
+ * @build DocLintTester
+ * @run main DocLintTester -Xmsgs:-html HtmlTagsTest.java
+ * @run main DocLintTester -ref HtmlTagsTest.out HtmlTagsTest.java
+ */
+
+/** */
+public class HtmlTagsTest {
+    /**
+     * <xyz> ... </xyz>
+     */
+    public void unknownTag1() { }
+
+    /**
+     * <div> <xyz> </div>
+     */
+    public void unknownTag2() { }
+
+    /**
+     * <br/>
+     */
+    public void selfClosingTag() { }
+
+    /**
+     * <html>
+     */
+    public void not_allowed() { }
+
+    /**
+     * <span> <p> </span>
+     */
+    public void not_allowed_inline() { }
+
+    /**
+     * {@link java.lang.String <p> }
+     * {@link java.lang.String <p> }
+     */
+    public void not_allowed_inline_2() { }
+
+    /**
+     * <img src="any.jpg" alt="alt"> </img>
+     */
+    public void end_not_allowed() { }
+
+    /**
+     * <i> <b> </i>
+     */
+    public void start_not_matched() { }
+
+    /**
+     * <i> </b> </i>
+     */
+    public void end_unexpected() { }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/HtmlTagsTest.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,38 @@
+HtmlTagsTest.java:11: error: unknown tag: xyz
+     * <xyz> ... </xyz>
+       ^
+HtmlTagsTest.java:11: error: unknown tag: xyz
+     * <xyz> ... </xyz>
+                 ^
+HtmlTagsTest.java:16: error: unknown tag: xyz
+     * <div> <xyz> </div>
+             ^
+HtmlTagsTest.java:21: error: self-closing element not allowed
+     * <br/>
+       ^
+HtmlTagsTest.java:26: error: element not allowed in documentation comments: <html>
+     * <html>
+       ^
+HtmlTagsTest.java:31: error: block element not allowed within inline element <span>: p
+     * <span> <p> </span>
+              ^
+HtmlTagsTest.java:36: error: block element not allowed within @link: p
+     * {@link java.lang.String <p> }
+                               ^
+HtmlTagsTest.java:37: error: block element not allowed within @link: p
+     * {@link java.lang.String <p> }
+                               ^
+HtmlTagsTest.java:42: error: invalid end tag: </img>
+     * <img src="any.jpg" alt="alt"> </img>
+                                     ^
+HtmlTagsTest.java:47: error: end tag missing: </b>
+     * <i> <b> </i>
+           ^
+HtmlTagsTest.java:52: error: unexpected end tag: </b>
+     * <i> </b> </i>
+           ^
+HtmlTagsTest.java:52: warning: empty <i> tag
+     * <i> </b> </i>
+                ^
+11 errors
+1 warning
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/MissingCommentTest.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,14 @@
+/*
+ * @test /nodynamiccopyright/
+ * @build DocLintTester
+ * @run main DocLintTester -Xmsgs:-missing MissingCommentTest.java
+ * @run main DocLintTester -Xmsgs:missing -ref MissingCommentTest.out MissingCommentTest.java
+ */
+
+public class MissingCommentTest {
+    MissingCommentTest() { }
+
+    int missingComment;
+
+    void missingComment() { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/MissingCommentTest.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,14 @@
+MissingCommentTest.java:8: warning: no comment
+public class MissingCommentTest {
+       ^
+MissingCommentTest.java:9: warning: no comment
+    MissingCommentTest() { }
+    ^
+MissingCommentTest.java:11: warning: no comment
+    int missingComment;
+        ^
+MissingCommentTest.java:13: warning: no comment
+    void missingComment() { }
+         ^
+4 warnings
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/MissingParamsTest.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,21 @@
+/*
+ * @test /nodynamiccopyright/
+ * @build DocLintTester
+ * @run main DocLintTester -Xmsgs:-missing MissingParamsTest.java
+ * @run main DocLintTester -Xmsgs:missing -ref MissingParamsTest.out MissingParamsTest.java
+ */
+
+/** . */
+public class MissingParamsTest {
+    /** */
+    MissingParamsTest(int param) { }
+
+    /** */
+    <T> MissingParamsTest() { }
+
+    /** */
+    void missingParam(int param) { }
+
+    /** */
+    <T> void missingTyparam() { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/MissingParamsTest.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,14 @@
+MissingParamsTest.java:11: warning: no @param for param
+    MissingParamsTest(int param) { }
+    ^
+MissingParamsTest.java:14: warning: no @param for <T>
+    <T> MissingParamsTest() { }
+        ^
+MissingParamsTest.java:17: warning: no @param for param
+    void missingParam(int param) { }
+         ^
+MissingParamsTest.java:20: warning: no @param for <T>
+    <T> void missingTyparam() { }
+             ^
+4 warnings
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/MissingReturnTest.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,21 @@
+/*
+ * @test /nodynamiccopyright/
+ * @build DocLintTester
+ * @run main DocLintTester -Xmsgs:-missing MissingReturnTest.java
+ * @run main DocLintTester -Xmsgs:missing -ref MissingReturnTest.out MissingReturnTest.java
+ */
+
+/** . */
+public class MissingReturnTest {
+    /** no return allowed */
+    MissingReturnTest() { }
+
+    /** no return allowed */
+    void return_void() { }
+
+    /** no return required */
+    Void return_Void() { }
+
+    /** */
+    int missingReturn() { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/MissingReturnTest.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,5 @@
+MissingReturnTest.java:20: warning: no @return
+    int missingReturn() { }
+        ^
+1 warning
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/MissingThrowsTest.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,12 @@
+/*
+ * @test /nodynamiccopyright/
+ * @build DocLintTester
+ * @run main DocLintTester -Xmsgs:-missing MissingThrowsTest.java
+ * @run main DocLintTester -Xmsgs:missing -ref MissingThrowsTest.out MissingThrowsTest.java
+ */
+
+/** */
+public class MissingThrowsTest {
+    /** */
+    void missingThrows() throws Exception { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/MissingThrowsTest.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,4 @@
+MissingThrowsTest.java:11: warning: no @throws for java.lang.Exception
+    void missingThrows() throws Exception { }
+         ^
+1 warning
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/OptionTest.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,94 @@
+
+import com.sun.tools.doclint.DocLint;
+
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ */
+public class OptionTest {
+    public static void main(String... args) throws Exception {
+        new OptionTest().run();
+    }
+
+    String[] positiveTests = {
+        "-Xmsgs",
+        "-Xmsgs:all",
+        "-Xmsgs:none",
+        "-Xmsgs:accessibility",
+        "-Xmsgs:html",
+        "-Xmsgs:missing",
+        "-Xmsgs:reference",
+        "-Xmsgs:syntax",
+        "-Xmsgs:html/public",
+        "-Xmsgs:html/protected",
+        "-Xmsgs:html/package",
+        "-Xmsgs:html/private",
+        "-Xmsgs:-html/public",
+        "-Xmsgs:-html/protected",
+        "-Xmsgs:-html/package",
+        "-Xmsgs:-html/private",
+        "-Xmsgs:html,syntax",
+        "-Xmsgs:html,-syntax",
+        "-Xmsgs:-html,syntax",
+        "-Xmsgs:-html,-syntax",
+        "-Xmsgs:html/public,syntax",
+        "-Xmsgs:html,syntax/public",
+        "-Xmsgs:-html/public,syntax/public"
+    };
+
+    String[] negativeTests = {
+        "-typo",
+        "-Xmsgs:-all",
+        "-Xmsgs:-none",
+        "-Xmsgs:typo",
+        "-Xmsgs:html/typo",
+        "-Xmsgs:html/public,typo",
+        "-Xmsgs:html/public,syntax/typo",
+    };
+
+    void run() throws Exception {
+        test(positiveTests, true);
+        test(negativeTests, false);
+
+        if (errors > 0)
+            throw new Exception(errors + " errors occurred");
+    }
+
+    void test(String[] tests, boolean expect) {
+        for (String test: tests) {
+            System.err.println("test: " + test);
+            boolean found = DocLint.isValidOption(test);
+            if (found != expect)
+                error("Unexpected result: " + found + ",expected: " + expect);
+        }
+    }
+
+    void error(String msg) {
+        System.err.println("Error: " + msg);
+        errors++;
+    }
+
+    int errors;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/OverridesTest.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @build DocLintTester
+ * @run main DocLintTester -Xmsgs:all OverridesTest.java
+ */
+
+/*
+ * This is a test that missing comments on methods may be inherited
+ * from overridden methods. As such, there should be no errors due
+ * to missing comments (or any other types of error) in this test.
+ */
+
+/** An interface. */
+interface I1 {
+    /**
+     * A method
+     * @param p a param
+     * @throws Exception an exception
+     * @return an int
+     */
+    int m(int p) throws Exception;
+}
+
+/** An extending interface. */
+interface I2 extends I1 { }
+
+/** An abstract class. */
+abstract class C1 {
+    /**
+     * A method
+     * @param p a param
+     * @throws Exception an exception
+     * @return an int
+     */
+    int m(int p) throws Exception;
+}
+
+/** An implementing class. */
+class C2 implements I1 {
+    int m(int  p) throws Exception { return p; }
+}
+
+/** An extending class. */
+class C3 extends C1 {
+    int m(int  p) throws Exception { return p; }
+}
+
+/** An extending and implementing class. */
+class C4 extends C1 implements I1 {
+    int m(int  p) throws Exception { return p; }
+}
+
+/** An implementing class using inheritdoc. */
+class C5 implements I1 {
+    /** {@inheritDoc} */
+    int m(int  p) throws Exception { return p; }
+}
+
+/** An implementing class with incomplete documentation. */
+class C6 implements I1 {
+    /** Overriding method */
+    int m(int  p) throws Exception { return p; }
+}
+
+/** A class implementing an inherited interface. */
+class C7 implements I2 {
+    int m(int  p) throws Exception { return p; }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/ReferenceTest.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,50 @@
+/*
+ * @test /nodynamiccopyright/
+ * @build DocLintTester
+ * @run main DocLintTester -Xmsgs:-reference ReferenceTest.java
+ * @run main DocLintTester -ref ReferenceTest.out ReferenceTest.java
+ */
+
+/** */
+public class ReferenceTest {
+    /**
+     * @param x description
+     */
+    public int invalid_param;
+
+    /**
+     * @param x description
+     */
+    public class InvalidParam { }
+
+    /**
+     * @param x description
+     */
+    public void param_name_not_found(int a) { }
+
+    /**
+     * @param <X> description
+     */
+    public class typaram_name_not_found { }
+
+    /**
+     * @see Object#tooStrong()
+     */
+    public void ref_not_found() { }
+
+    /**
+     * @return x description
+     */
+    public int invalid_return;
+
+    /**
+     * @return x description
+     */
+    public void invalid_return();
+
+    /**
+     * @throws Exception description
+     */
+    public void exception_not_thrown() { }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/ReferenceTest.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,30 @@
+ReferenceTest.java:11: error: invalid use of @param
+     * @param x description
+       ^
+ReferenceTest.java:16: error: invalid use of @param
+     * @param x description
+       ^
+ReferenceTest.java:21: error: @param name not found
+     * @param x description
+              ^
+ReferenceTest.java:23: warning: no @param for a
+    public void param_name_not_found(int a) { }
+                ^
+ReferenceTest.java:26: error: @param name not found
+     * @param <X> description
+               ^
+ReferenceTest.java:31: error: reference not found
+     * @see Object#tooStrong()
+            ^
+ReferenceTest.java:36: error: invalid use of @return
+     * @return x description
+       ^
+ReferenceTest.java:41: error: invalid use of @return
+     * @return x description
+       ^
+ReferenceTest.java:46: error: exception not thrown: java.lang.Exception
+     * @throws Exception description
+               ^
+8 errors
+1 warning
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/RunTest.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8000103
+ * @summary Create doclint utility
+ */
+
+import com.sun.tools.doclint.DocLint;
+import com.sun.tools.doclint.DocLint.BadArgs;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/** javadoc error on toplevel:  a & b. */
+public class RunTest {
+    /** javadoc error on member: a < b */
+    public static void main(String... args) throws Exception {
+        new RunTest().run();
+    }
+
+
+    File testSrc = new File(System.getProperty("test.src"));
+    File thisFile = new File(testSrc, RunTest.class.getSimpleName() + ".java");
+
+    void run() throws Exception {
+        for (Method m: getClass().getDeclaredMethods()) {
+            Annotation a = m.getAnnotation(Test.class);
+            if (a != null) {
+                System.err.println("test: " + m.getName());
+                try {
+                    StringWriter sw = new StringWriter();
+                    PrintWriter pw = new PrintWriter(sw);;
+                    m.invoke(this, new Object[] { pw });
+                    String out = sw.toString();
+                    System.err.println(">>> " + out.replace("\n", "\n>>> "));
+                    if (!out.contains("a < b"))
+                        error("\"a < b\" not found");
+                    if (!out.contains("a & b"))
+                        error("\"a & b\" not found");
+                } catch (InvocationTargetException e) {
+                    Throwable cause = e.getCause();
+                    throw (cause instanceof Exception) ? ((Exception) cause) : e;
+                }
+                System.err.println();
+            }
+        }
+
+        if (errors > 0)
+            throw new Exception(errors + " errors occurred");
+    }
+
+
+    void error(String msg) {
+        System.err.println("Error: " + msg);
+        errors++;
+    }
+
+    int errors;
+
+    /** Marker annotation for test cases. */
+    @Retention(RetentionPolicy.RUNTIME)
+    @interface Test { }
+
+    @Test
+    void testMain(PrintWriter pw) throws BadArgs, IOException {
+        String[] args = { "-Xmsgs", thisFile.getPath() };
+        DocLint d = new DocLint();
+        d.run(pw, args);
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/SyntaxTest.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,15 @@
+/*
+ * @test /nodynamiccopyright/
+ * @build DocLintTester
+ * @run main DocLintTester -Xmsgs:-syntax SyntaxTest.java
+ * @run main DocLintTester -ref SyntaxTest.out SyntaxTest.java
+ */
+
+/** */
+public class SyntaxTest {
+    /**
+     * a < b
+     */
+    public void syntax_error() { }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/SyntaxTest.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,5 @@
+SyntaxTest.java:11: error: malformed HTML
+     * a < b
+         ^
+1 error
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/SyntheticTest.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @build DocLintTester
+ * @run main DocLintTester -Xmsgs:all SyntheticTest.java
+ */
+
+/**
+ * This is a test that messages are not generated for synthesized elements
+ * such as default constructors and enum methods.
+ */
+public class SyntheticTest {
+    // No explicit constructor implies a default constructor
+
+    /** enum E */
+    enum E {
+        /** enum member E1 */
+        E1,
+        /** enum member E2 */
+        E2,
+        /** enum member E3 */
+        E3
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/ValidTest.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @build DocLintTester
+ * @run main DocLintTester ValidTest.java
+ */
+
+class ValidTest {
+    /**
+     * &lt; &gt; &amp; &#40;
+     */
+    void entities() { }
+
+    /**
+     * <h1> ... </h1>
+     * <h2> ... </h2>
+     * <h3> ... </h3>
+     * <h4> ... </h4>
+     * <h5> ... </h5>
+     * <h6> ... </h6>
+     */
+    void all_headers() { }
+
+    /**
+     * <h1> ... </h1>
+     * <h2> ... </h2>
+     * <h3> ... </h3>
+     * <h1> ... </h1>
+     * <h2> ... </h2>
+     * <h3> ... </h3>
+     * <h2> ... </h2>
+     */
+    void header_series() { }
+
+    /**
+     * <div> <p>   </div>
+     */
+    void autoclose_tags() { }
+
+    /**
+     * @param x
+     */
+    void method_param(int x) { }
+
+    /**
+     * @param <T>
+     */
+    <T> T method_typaram(T t) { return t; }
+
+    /**
+     * @param <T>
+     */
+    class ClassTyparam<T> { }
+
+    /**
+     * @param <T>
+     */
+    interface InterfaceTyparam<T> { }
+
+    /**
+     * @return x
+     */
+    int return_int() { return 0; }
+
+    /**
+     * @exception Exception
+     */
+    void throws_Exception1() throws Exception { }
+
+    /**
+     * @throws Exception
+     */
+    void throws_Exception2() throws Exception { }
+
+    class X {
+        /**
+         * @param x
+         */
+        X(int x) { } // constructor parameter
+
+        /**
+         * @param <T>
+         */
+        <T> X(T t) { } // constructor type parameter
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/AnchorAlreadyDefined.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,15 @@
+/*
+ * @test /nodynamiccopyright/
+ * @library ..
+ * @build DocLintTester
+ * @run main DocLintTester -ref AnchorAlreadyDefined.out AnchorAlreadyDefined.java
+ */
+
+// tidy: Warning: <.*> anchor ".*" already defined
+
+/**
+ * <a name="here">valid</a>
+ * <a name="here">duplicate</a>
+ * <h1 id="here">duplicate</h1>
+ */
+public class AnchorAlreadyDefined { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/AnchorAlreadyDefined.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,7 @@
+AnchorAlreadyDefined.java:12: error: anchor already defined: here
+ * <a name="here">duplicate</a>
+      ^
+AnchorAlreadyDefined.java:13: error: anchor already defined: here
+ * <h1 id="here">duplicate</h1>
+       ^
+2 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/BadEnd.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,14 @@
+/*
+ * @test /nodynamiccopyright/
+ * @library ..
+ * @build DocLintTester
+ * @run main DocLintTester -ref BadEnd.out BadEnd.java
+ */
+
+// tidy: Warning: <.*> is probably intended as </.*>
+
+/**
+ * <a name="here"> text <a>
+ * <code> text <code>
+ */
+public class BadEnd { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/BadEnd.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,17 @@
+BadEnd.java:12: warning: nested tag not allowed: <code>
+ * <code> text <code>
+               ^
+BadEnd.java:12: error: element not closed: code
+ * <code> text <code>
+               ^
+BadEnd.java:12: error: element not closed: code
+ * <code> text <code>
+   ^
+BadEnd.java:11: error: element not closed: a
+ * <a name="here"> text <a>
+                        ^
+BadEnd.java:11: error: element not closed: a
+ * <a name="here"> text <a>
+   ^
+4 errors
+1 warning
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/InsertImplicit.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,14 @@
+/*
+ * @test /nodynamiccopyright/
+ * @library ..
+ * @build DocLintTester
+ * @run main DocLintTester -ref InsertImplicit.out InsertImplicit.java
+ */
+
+// tidy: Warning: inserting implicit <.*>
+
+/**
+ * </p>
+ * <i> <blockquote> abc </blockquote> </i>
+ */
+public class InsertImplicit { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/InsertImplicit.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,7 @@
+InsertImplicit.java:11: error: unexpected end tag: </p>
+ * </p>
+   ^
+InsertImplicit.java:12: error: block element not allowed within inline element <i>: blockquote
+ * <i> <blockquote> abc </blockquote> </i>
+       ^
+2 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/InvalidEntity.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,20 @@
+/*
+ * @test /nodynamiccopyright/
+ * @library ..
+ * @build DocLintTester
+ * @run main DocLintTester -ref InvalidEntity.out InvalidEntity.java
+ */
+
+// tidy: Warning: replacing invalid numeric character reference .*
+
+// See
+// http://www.w3.org/TR/html4/sgml/entities.html
+// http://stackoverflow.com/questions/631406/what-is-the-difference-between-em-dash-151-and-8212
+
+/**
+ * &#01;
+ * &#x01;
+ * &splodge;
+ *
+ */
+public class InvalidEntity { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/InvalidEntity.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,10 @@
+InvalidEntity.java:15: error: invalid entity &#01;
+ * &#01;
+   ^
+InvalidEntity.java:16: error: invalid entity &#x01;
+ * &#x01;
+   ^
+InvalidEntity.java:17: error: invalid entity &splodge;
+ * &splodge;
+   ^
+3 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/InvalidName.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,16 @@
+/*
+ * @test /nodynamiccopyright/
+ * @library ..
+ * @build DocLintTester
+ * @run main DocLintTester -ref InvalidName.out InvalidName.java
+ */
+
+// tidy: Warning: <a> cannot copy name attribute to id
+
+/**
+ * <a name="abc">valid</a>
+ * <a name="abc123">valid</a>
+ * <a name="a.1:2-3_4">valid</a>
+ * <a name="foo()">invalid</a>
+ */
+public class InvalidName { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/InvalidName.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,4 @@
+InvalidName.java:14: error: invalid name for anchor: "foo()"
+ * <a name="foo()">invalid</a>
+      ^
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/InvalidTag.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,13 @@
+/*
+ * @test /nodynamiccopyright/
+ * @library ..
+ * @build DocLintTester
+ * @run main DocLintTester -ref InvalidTag.out InvalidTag.java
+ */
+
+// tidy: Error: <.*> is not recognized!
+
+/**
+ * List<String> list = new ArrayList<>();
+ */
+public class InvalidTag { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/InvalidTag.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,10 @@
+InvalidTag.java:11: error: unknown tag: String
+ * List<String> list = new ArrayList<>();
+       ^
+InvalidTag.java:11: error: malformed HTML
+ * List<String> list = new ArrayList<>();
+                                    ^
+InvalidTag.java:11: error: bad use of '>'
+ * List<String> list = new ArrayList<>();
+                                     ^
+3 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/InvalidURI.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,19 @@
+/*
+ * @test /nodynamiccopyright/
+ * @library ..
+ * @build DocLintTester
+ * @run main DocLintTester -ref InvalidURI.out InvalidURI.java
+ */
+
+// tidy: Warning: <a> escaping malformed URI reference
+// tidy: Warning: <.*> attribute ".*" lacks value
+
+/**
+ * <a href="abc">valid</a>
+ * <a href="abc%20def">valid</a>
+ * <a href="abc def">invalid</a>
+ * <a href>no value</a>
+ * <a href= >no value</a>
+ * <a href="" >no value</a>
+ */
+public class InvalidURI { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/InvalidURI.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,13 @@
+InvalidURI.java:14: error: invalid uri: "abc def"
+ * <a href="abc def">invalid</a>
+      ^
+InvalidURI.java:15: error: attribute lacks value
+ * <a href>no value</a>
+      ^
+InvalidURI.java:16: error: attribute lacks value
+ * <a href= >no value</a>
+      ^
+InvalidURI.java:17: error: attribute lacks value
+ * <a href="" >no value</a>
+      ^
+4 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/MissingGT.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,14 @@
+/*
+ * @test /nodynamiccopyright/
+ * @library ..
+ * @build DocLintTester
+ * @run main DocLintTester -ref MissingGT.out MissingGT.java
+ */
+
+// tidy: Warning: <.*> missing '>' for end of tag
+
+/**
+ * <img src="image.gif"
+ * <i>  text </i>
+ */
+public class MissingGT { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/MissingGT.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,4 @@
+MissingGT.java:11: error: malformed HTML
+ * <img src="image.gif"
+   ^
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/MissingTag.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,15 @@
+/*
+ * @test /nodynamiccopyright/
+ * @library ..
+ * @build DocLintTester
+ * @run main DocLintTester -ref MissingTag.out MissingTag.java
+ */
+
+// tidy: Warning: missing <.*>
+// tidy: Warning: missing </.*> before </.*>
+
+/**
+ * </p>
+ * <h1> <b> text </h1>
+ */
+public class MissingTag { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/MissingTag.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,7 @@
+MissingTag.java:12: error: unexpected end tag: </p>
+ * </p>
+   ^
+MissingTag.java:13: error: end tag missing: </b>
+ * <h1> <b> text </h1>
+        ^
+2 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/NestedTag.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,14 @@
+/*
+ * @test /nodynamiccopyright/
+ * @library ..
+ * @build DocLintTester
+ * @run main DocLintTester -ref NestedTag.out NestedTag.java
+ */
+
+// tidy: Warning: nested emphasis <.*>
+
+/**
+ * <b><b> text </b></b>
+ * {@link java.lang.String <code>String</code>}
+ */
+public class NestedTag { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/NestedTag.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,7 @@
+NestedTag.java:11: warning: nested tag not allowed: <b>
+ * <b><b> text </b></b>
+      ^
+NestedTag.java:12: warning: nested tag not allowed: <code>
+ * {@link java.lang.String <code>String</code>}
+                           ^
+2 warnings
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/ParaInPre.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,18 @@
+/*
+ * @test /nodynamiccopyright/
+ * @library ..
+ * @build DocLintTester
+ * @run main DocLintTester -ref ParaInPre.out ParaInPre.java
+ */
+
+// tidy: Warning: replacing <p> by <br>
+// tidy: Warning: using <br> in place of <p>
+
+/**
+ * <pre>
+ *     text
+ *     <p>
+ *     more text
+ * </pre>
+ */
+public class ParaInPre { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/ParaInPre.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,4 @@
+ParaInPre.java:14: warning: unexpected use of <p> inside <pre> element
+ *     <p>
+       ^
+1 warning
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/README.txt	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,21 @@
+The utilities in this directory can be used to determine
+common issues in javadoc comments by running the standard
+"tidy" program on the output of javadoc, and analysing
+the messages that are reported.
+
+tidy.sh is a script that will run the "tidy" program on
+the files in a directory, writing the results to a new
+directroy.
+
+tidystats.Main is a Java program that can analyze the 
+files produced by the tidy.sh script to generate a 
+summary report about the warnings that were found.
+
+
+The tests is this directory are focussed on verifying
+that doclint detects issues in javadoc comments that will
+give rise to issues detected by "tidy" in the output
+generated by javadoc. 
+
+For more information on the "tidy" program, see the HTML Tidy
+Library Project page at http://tidy.sourceforge.net/.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/RepeatedAttr.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,13 @@
+/*
+ * @test /nodynamiccopyright/
+ * @library ..
+ * @build DocLintTester
+ * @run main DocLintTester -ref RepeatedAttr.out RepeatedAttr.java
+ */
+
+// tidy: Warning: <.*> dropping value ".*" for repeated attribute ".*"
+
+/**
+ * <img src="image.gif" alt alt="summary">
+ */
+public class RepeatedAttr { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/RepeatedAttr.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,4 @@
+RepeatedAttr.java:11: error: repeated attribute: alt
+ * <img src="image.gif" alt alt="summary">
+                            ^
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/TextNotAllowed.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,24 @@
+/*
+ * @test /nodynamiccopyright/
+ * @library ..
+ * @build DocLintTester
+ * @run main DocLintTester -ref TextNotAllowed.out TextNotAllowed.java
+ */
+
+// tidy: Warning: plain text isn't allowed in <.*> elements
+
+/**
+ * <table summary=description> abc </table>
+ * <table summary=description> <tbody> abc </tbody> </table>
+ * <table summary=description> <tr> abc </tr> </table>
+ *
+ * <dl> abc </dl>
+ * <ol> abc </ol>
+ * <ul> abc </ul>
+ *
+ * <ul>
+ *     <li> item
+ *     <li> item
+ * </ul>
+ */
+public class TextNotAllowed { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/TextNotAllowed.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,19 @@
+TextNotAllowed.java:11: error: text not allowed in <table> element
+ * <table summary=description> abc </table>
+                                   ^
+TextNotAllowed.java:12: error: text not allowed in <tbody> element
+ * <table summary=description> <tbody> abc </tbody> </table>
+                                           ^
+TextNotAllowed.java:13: error: text not allowed in <tr> element
+ * <table summary=description> <tr> abc </tr> </table>
+                                        ^
+TextNotAllowed.java:15: error: text not allowed in <dl> element
+ * <dl> abc </dl>
+            ^
+TextNotAllowed.java:16: error: text not allowed in <ol> element
+ * <ol> abc </ol>
+            ^
+TextNotAllowed.java:17: error: text not allowed in <ul> element
+ * <ul> abc </ul>
+            ^
+6 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/TrimmingEmptyTag.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,27 @@
+/*
+ * @test /nodynamiccopyright/
+ * @library ..
+ * @build DocLintTester
+ * @run main DocLintTester -ref TrimmingEmptyTag.out TrimmingEmptyTag.java
+ */
+
+// tidy: Warning: trimming empty <.*>
+
+/**
+ * <b></b>
+ * <table summary=description></table>
+ * <table><caption></caption></table>
+ * <code></code>
+ * <dl></dl>
+ * <dl><dt></dt><dd></dd></dl>
+ * <font></font>
+ * <i></i>
+ * <ol></ol>
+ * <p></p>
+ * <pre></pre>
+ * <span></span>
+ * <tt></tt>
+ * <ul></ul>
+ * <ul><li></li></ul>
+ */
+public class TrimmingEmptyTag { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/TrimmingEmptyTag.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,46 @@
+TrimmingEmptyTag.java:11: warning: empty <b> tag
+ * <b></b>
+      ^
+TrimmingEmptyTag.java:12: warning: empty <table> tag
+ * <table summary=description></table>
+                              ^
+TrimmingEmptyTag.java:13: warning: empty <caption> tag
+ * <table><caption></caption></table>
+                   ^
+TrimmingEmptyTag.java:14: warning: empty <code> tag
+ * <code></code>
+         ^
+TrimmingEmptyTag.java:15: warning: empty <dl> tag
+ * <dl></dl>
+       ^
+TrimmingEmptyTag.java:16: warning: empty <dt> tag
+ * <dl><dt></dt><dd></dd></dl>
+           ^
+TrimmingEmptyTag.java:16: warning: empty <dd> tag
+ * <dl><dt></dt><dd></dd></dl>
+                    ^
+TrimmingEmptyTag.java:17: warning: empty <font> tag
+ * <font></font>
+         ^
+TrimmingEmptyTag.java:18: warning: empty <i> tag
+ * <i></i>
+      ^
+TrimmingEmptyTag.java:19: warning: empty <ol> tag
+ * <ol></ol>
+       ^
+TrimmingEmptyTag.java:20: warning: empty <p> tag
+ * <p></p>
+      ^
+TrimmingEmptyTag.java:21: warning: empty <pre> tag
+ * <pre></pre>
+        ^
+TrimmingEmptyTag.java:22: warning: empty <span> tag
+ * <span></span>
+         ^
+TrimmingEmptyTag.java:23: warning: empty <tt> tag
+ * <tt></tt>
+       ^
+TrimmingEmptyTag.java:24: warning: empty <ul> tag
+ * <ul></ul>
+       ^
+15 warnings
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/UnescapedOrUnknownEntity.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,17 @@
+/*
+ * @test /nodynamiccopyright/
+ * @library ..
+ * @build DocLintTester
+ * @run main DocLintTester -ref UnescapedOrUnknownEntity.out UnescapedOrUnknownEntity.java
+ */
+
+// tidy: Warning: unescaped & or unknown entity ".*"
+// tidy: Warning: unescaped & which should be written as &amp;
+// tidy: Warning: entity ".*" doesn't end in ';'
+
+/**
+ * L&F
+ * Drag&Drop
+ * if (a & b);
+ */
+public class UnescapedOrUnknownEntity { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/UnescapedOrUnknownEntity.out	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,11 @@
+UnescapedOrUnknownEntity.java:13: error: semicolon missing
+ * L&F
+    ^
+UnescapedOrUnknownEntity.java:14: error: semicolon missing
+ * Drag&Drop
+       ^
+UnescapedOrUnknownEntity.java:15: error: bad HTML entity
+ * if (a & b);
+         ^
+3 errors
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/util/Main.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,182 @@
+package tidystats;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class Main {
+    public static void main(String... args) throws IOException {
+        new Main().run(args);
+    }
+
+    void run(String... args) throws IOException {
+        FileSystem fs = FileSystems.getDefault();
+        List<Path> paths = new ArrayList<>();
+
+        int i;
+        for (i = 0; i < args.length; i++) {
+            String arg = args[i];
+            if (arg.startsWith("-"))
+                throw new IllegalArgumentException(arg);
+            else
+                break;
+        }
+
+        for ( ; i < args.length; i++) {
+            Path p = fs.getPath(args[i]);
+            paths.add(p);
+        }
+
+        for (Path p: paths) {
+            scan(p);
+        }
+
+        print("%6d files read", files);
+        print("%6d files had no errors or warnings", ok);
+        print("%6d files reported \"Not all warnings/errors were shown.\"", overflow);
+        print("%6d errors found", errs);
+        print("%6d warnings found", warns);
+        print("%6d recommendations to use CSS", css);
+        print("");
+
+        Map<Integer, Set<String>> sortedCounts = new TreeMap<>(
+                new Comparator<Integer>() {
+                    @Override
+                    public int compare(Integer o1, Integer o2) {
+                        return o2.compareTo(o1);
+                    }
+                });
+
+        for (Map.Entry<Pattern, Integer> e: counts.entrySet()) {
+            Pattern p = e.getKey();
+            Integer n = e.getValue();
+            Set<String> set = sortedCounts.get(n);
+            if (set == null)
+                sortedCounts.put(n, (set = new TreeSet<>()));
+            set.add(p.toString());
+        }
+
+        for (Map.Entry<Integer, Set<String>> e: sortedCounts.entrySet()) {
+            for (String p: e.getValue()) {
+                if (p.startsWith(".*")) p = p.substring(2);
+                print("%6d: %s", e.getKey(), p);
+            }
+        }
+    }
+
+    void scan(Path p) throws IOException {
+        if (Files.isDirectory(p)) {
+            for (Path c: Files.newDirectoryStream(p)) {
+                scan(c);
+            }
+        } else if (isTidyFile(p)) {
+            scan(Files.readAllLines(p, Charset.defaultCharset()));
+        }
+    }
+
+    boolean isTidyFile(Path p) {
+        return Files.isRegularFile(p) && p.getFileName().toString().endsWith(".tidy");
+    }
+
+    void scan(List<String> lines) {
+        Matcher m;
+        files++;
+        for (String line: lines) {
+            if (okPattern.matcher(line).matches()) {
+                ok++;
+            } else if ((m = countPattern.matcher(line)).matches()) {
+                warns += Integer.valueOf(m.group(1));
+                errs += Integer.valueOf(m.group(2));
+                if (m.group(3) != null)
+                    overflow++;
+            } else if ((m = guardPattern.matcher(line)).matches()) {
+                boolean found = false;
+                for (Pattern p: patterns) {
+                    if ((m = p.matcher(line)).matches()) {
+                        found = true;
+                        count(p);
+                        break;
+                    }
+                }
+                if (!found)
+                    System.err.println("Unrecognized line: " + line);
+            } else if (cssPattern.matcher(line).matches()) {
+                css++;
+            }
+        }
+    }
+
+    Map<Pattern, Integer> counts = new HashMap<>();
+    void count(Pattern p) {
+        Integer i = counts.get(p);
+        counts.put(p, (i == null) ? 1 : i + 1);
+    }
+
+    void print(String format, Object... args) {
+        System.out.println(String.format(format, args));
+    }
+
+    Pattern okPattern = Pattern.compile("No warnings or errors were found.");
+    Pattern countPattern = Pattern.compile("([0-9]+) warnings, ([0-9]+) errors were found!.*?(Not all warnings/errors were shown.)?");
+    Pattern cssPattern = Pattern.compile("You are recommended to use CSS.*");
+    Pattern guardPattern = Pattern.compile("line [0-9]+ column [0-9]+ - (Error|Warning):.*");
+
+    Pattern[] patterns = {
+        Pattern.compile(".*Error: <.*> is not recognized!"),
+        Pattern.compile(".*Error: missing quote mark for attribute value"),
+        Pattern.compile(".*Warning: <.*> anchor \".*\" already defined"),
+        Pattern.compile(".*Warning: <.*> attribute \".*\" has invalid value \".*\""),
+        Pattern.compile(".*Warning: <.*> attribute \".*\" lacks value"),
+        Pattern.compile(".*Warning: <.*> attribute \".*\" lacks value"),
+        Pattern.compile(".*Warning: <.*> attribute with missing trailing quote mark"),
+        Pattern.compile(".*Warning: <.*> dropping value \".*\" for repeated attribute \".*\""),
+        Pattern.compile(".*Warning: <.*> inserting \".*\" attribute"),
+        Pattern.compile(".*Warning: <.*> is probably intended as </.*>"),
+        Pattern.compile(".*Warning: <.*> isn't allowed in <.*> elements"),
+        Pattern.compile(".*Warning: <.*> lacks \".*\" attribute"),
+        Pattern.compile(".*Warning: <.*> missing '>' for end of tag"),
+        Pattern.compile(".*Warning: <.*> proprietary attribute \".*\""),
+        Pattern.compile(".*Warning: <.*> unexpected or duplicate quote mark"),
+        Pattern.compile(".*Warning: <a> cannot copy name attribute to id"),
+        Pattern.compile(".*Warning: <a> escaping malformed URI reference"),
+        Pattern.compile(".*Warning: <blockquote> proprietary attribute \"pre\""),
+        Pattern.compile(".*Warning: discarding unexpected <.*>"),
+        Pattern.compile(".*Warning: discarding unexpected </.*>"),
+        Pattern.compile(".*Warning: entity \".*\" doesn't end in ';'"),
+        Pattern.compile(".*Warning: inserting implicit <.*>"),
+        Pattern.compile(".*Warning: inserting missing 'title' element"),
+        Pattern.compile(".*Warning: missing <!DOCTYPE> declaration"),
+        Pattern.compile(".*Warning: missing <.*>"),
+        Pattern.compile(".*Warning: missing </.*> before <.*>"),
+        Pattern.compile(".*Warning: nested emphasis <.*>"),
+        Pattern.compile(".*Warning: plain text isn't allowed in <.*> elements"),
+        Pattern.compile(".*Warning: replacing <p> by <br>"),
+        Pattern.compile(".*Warning: replacing invalid numeric character reference .*"),
+        Pattern.compile(".*Warning: replacing unexpected .* by </.*>"),
+        Pattern.compile(".*Warning: trimming empty <.*>"),
+        Pattern.compile(".*Warning: unescaped & or unknown entity \".*\""),
+        Pattern.compile(".*Warning: unescaped & which should be written as &amp;"),
+        Pattern.compile(".*Warning: using <br> in place of <p>")
+    };
+
+    int files;
+    int ok;
+    int warns;
+    int errs;
+    int css;
+    int overflow;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/tidy/util/tidy.sh	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,52 @@
+#!/bin/sh
+#
+# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# Run the "tidy" program over the files in a directory.
+#
+# Usage:
+#   sh tidy.sh <dir>
+#
+# The "tidy" program will be run on each HTML file in <dir>,
+# and the output placed in the corresponding location in a new
+# directory <dir>.tidy.  The console output from running "tidy" will
+# be saved in a corresponding file with an additional .tidy extension.
+#
+# Non-HTML files will be copied without modification from <dir> to
+# <dir>.tidy, so that relative links within the directory tree are
+# unaffected.
+
+dir=$1
+odir=$dir.tidy
+
+( cd $dir ; find . -type f ) | \
+    while read file ; do
+        mkdir -p $odir/$(dirname $file)
+        case $file in
+            *.html )
+                cat $dir/$file | tidy 1>$odir/$file 2>$odir/$file.tidy
+                ;;
+            * ) cp $dir/$file $odir/$file
+                ;;
+        esac
+    done
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/NoContent.java	Mon Dec 17 07:47:05 2012 -0800
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.err.dc.no.content
+// key: compiler.note.note
+// key: compiler.note.proc.messager
+// run: backdoor
+// options: -processor DocCommentProcessor -proc:only
+
+/** @see */
+class NoContent {
+}
+