8132096: Augment the Compiler Tree API to support the new Simplified Doclet API
authorksrini
Wed, 28 Oct 2015 10:41:30 -0700
changeset 33424 e6bd5406e2cf
parent 33373 4a0312f2894b
child 33425 dce6b447e07a
8132096: Augment the Compiler Tree API to support the new Simplified Doclet API Reviewed-by: jjg, jlahoda
langtools/src/jdk.compiler/share/classes/com/sun/source/util/DocTrees.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java
langtools/test/tools/javac/doctree/DocCommentTester.java
langtools/test/tools/javac/doctree/FirstSentenceTest.java
langtools/test/tools/javac/doctree/dcapi/DocCommentTreeApiTester.java
langtools/test/tools/javac/doctree/dcapi/OverviewTest.java
langtools/test/tools/javac/doctree/dcapi/overview0.html
langtools/test/tools/javac/doctree/dcapi/overview1.html
langtools/test/tools/javac/doctree/dcapi/overview2.html
langtools/test/tools/javac/doctree/dcapi/overview3.html
langtools/test/tools/javac/doctree/dcapi/overview4.html
langtools/test/tools/javac/doctree/dcapi/overview5.html
langtools/test/tools/javac/doctree/dcapi/overview6.html
langtools/test/tools/javac/doctree/dcapi/package.html
langtools/test/tools/javac/doctree/dcapi/pkg/Anchor.java
langtools/test/tools/javac/doctree/dcapi/pkg/package.html
langtools/test/tools/javac/tree/NoPrivateTypesExported.java
--- a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/DocTrees.java	Wed Jul 05 20:56:54 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/DocTrees.java	Wed Oct 28 10:41:30 2015 -0700
@@ -25,11 +25,14 @@
 
 package com.sun.source.util;
 
+import java.io.IOException;
+import java.text.BreakIterator;
 import java.util.List;
 
 import javax.annotation.processing.ProcessingEnvironment;
 import javax.lang.model.element.Element;
 import javax.tools.Diagnostic;
+import javax.tools.FileObject;
 import javax.tools.JavaCompiler.CompilationTask;
 
 import com.sun.source.doctree.DocCommentTree;
@@ -65,6 +68,16 @@
     }
 
     /**
+     * Returns the break iterator used to compute the first sentence of
+     * documentation comments.
+     * Returns {@code null} if none has been specified.
+     * @return the break iterator
+     *
+     * @since 1.9
+     */
+    public abstract BreakIterator getBreakIterator();
+
+    /**
      * Returns the doc comment tree, if any, for the Tree node identified by a given TreePath.
      * Returns {@code null} if no doc comment was found.
      * @param path the path for the tree node
@@ -73,6 +86,47 @@
     public abstract DocCommentTree getDocCommentTree(TreePath path);
 
     /**
+     * Returns the doc comment tree of the given element.
+     * Returns {@code null} if no doc comment was found.
+     * @param e an element whose documentation is required
+     * @return the doc comment tree
+     *
+     * @since 1.9
+     */
+    public abstract DocCommentTree getDocCommentTree(Element e);
+
+    /**
+     * Returns the doc comment tree of the given file. The file must be
+     * an HTML file, in which case the doc comment tree represents the
+     * contents of the <body> tag, and any enclosing tags are ignored.
+     * Returns {@code null} if no doc comment was found.
+     * Future releases may support additional file types.
+     *
+     * @param fileObject the content container
+     * @return the doc comment tree
+     *
+     * @since 1.9
+     */
+    public abstract DocCommentTree getDocCommentTree(FileObject fileObject);
+
+    /**
+     * Returns the doc comment tree of the given file whose path is
+     * specified relative to the given element. The file must be an HTML
+     * file, in which case the doc comment tree represents the contents
+     * of the <body> tag, and any enclosing tags are ignored.
+     * Returns {@code null} if no doc comment was found.
+     * Future releases may support additional file types.
+     *
+     * @param e an element whose path is used as a reference
+     * @param relativePath the relative path from the Element
+     * @return the doc comment tree
+     * @throws java.io.IOException if an exception occurs
+     *
+     * @since 1.9
+     */
+    public abstract DocCommentTree getDocCommentTree(Element e, String relativePath) throws IOException;
+
+    /**
      * Returns the language model element referred to by the leaf node of the given
      * {@link DocTreePath}, or {@code null} if unknown.
      * @param path the path for the tree node
@@ -112,4 +166,14 @@
             com.sun.source.doctree.DocTree t,
             com.sun.source.doctree.DocCommentTree c,
             com.sun.source.tree.CompilationUnitTree root);
+
+    /**
+     * Sets the break iterator to compute the first sentence of
+     * documentation comments.
+     * @param breakiterator a break iterator or {@code null} to specify the default
+     *                      sentence breaker
+     *
+     * @since 1.9
+     */
+    public abstract void setBreakIterator(BreakIterator breakiterator);
 }
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java	Wed Jul 05 20:56:54 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java	Wed Oct 28 10:41:30 2015 -0700
@@ -25,8 +25,13 @@
 
 package com.sun.tools.javac.api;
 
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.text.BreakIterator;
 import java.util.HashSet;
 import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import javax.annotation.processing.ProcessingEnvironment;
 import javax.lang.model.element.AnnotationMirror;
@@ -34,13 +39,22 @@
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ElementKind;
 import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.NestingKind;
+import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.DeclaredType;
 import javax.lang.model.type.TypeKind;
 import javax.lang.model.type.TypeMirror;
 import javax.tools.Diagnostic;
+import javax.tools.FileObject;
+import javax.tools.ForwardingFileObject;
+import javax.tools.ForwardingJavaFileObject;
 import javax.tools.JavaCompiler;
+import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
+import javax.tools.StandardLocation;
 
 import com.sun.source.doctree.DocCommentTree;
 import com.sun.source.doctree.DocTree;
@@ -74,7 +88,12 @@
 import com.sun.tools.javac.comp.Env;
 import com.sun.tools.javac.comp.MemberEnter;
 import com.sun.tools.javac.comp.Resolve;
+import com.sun.tools.javac.file.BaseFileManager;
 import com.sun.tools.javac.model.JavacElements;
+import com.sun.tools.javac.parser.DocCommentParser;
+import com.sun.tools.javac.parser.ParserFactory;
+import com.sun.tools.javac.parser.Tokens.Comment;
+import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
 import com.sun.tools.javac.processing.JavacProcessingEnvironment;
 import com.sun.tools.javac.tree.DCTree;
 import com.sun.tools.javac.tree.DCTree.DCBlockTag;
@@ -104,6 +123,7 @@
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.DefinedBy;
 import com.sun.tools.javac.util.DefinedBy.Api;
+import com.sun.tools.javac.util.DiagnosticSource;
 import com.sun.tools.javac.util.JCDiagnostic;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
 import com.sun.tools.javac.util.List;
@@ -141,6 +161,9 @@
     private Names names;
     private Types types;
     private DocTreeMaker doctreeMaker;
+    private BreakIterator breakIterator;
+    private JavaFileManager fileManager;
+    private ParserFactory parser;
 
     // called reflectively from Trees.instance(CompilationTask task)
     public static JavacTrees instance(JavaCompiler.CompilationTask task) {
@@ -164,6 +187,7 @@
     }
 
     protected JavacTrees(Context context) {
+        this.breakIterator = null;
         context.put(JavacTrees.class, this);
         init(context);
     }
@@ -183,31 +207,37 @@
         names = Names.instance(context);
         types = Types.instance(context);
         doctreeMaker = DocTreeMaker.instance(context);
-
+        parser = ParserFactory.instance(context);
+        fileManager = context.get(JavaFileManager.class);
         JavacTask t = context.get(JavacTask.class);
         if (t instanceof JavacTaskImpl)
             javacTaskImpl = (JavacTaskImpl) t;
     }
 
-    @DefinedBy(Api.COMPILER_TREE)
+    @Override @DefinedBy(Api.COMPILER_TREE)
+    public BreakIterator getBreakIterator() {
+        return breakIterator;
+    }
+
+    @Override @DefinedBy(Api.COMPILER_TREE)
     public DocSourcePositions getSourcePositions() {
         return new DocSourcePositions() {
-                @DefinedBy(Api.COMPILER_TREE)
+                @Override @DefinedBy(Api.COMPILER_TREE)
                 public long getStartPosition(CompilationUnitTree file, Tree tree) {
                     return TreeInfo.getStartPos((JCTree) tree);
                 }
 
-                @DefinedBy(Api.COMPILER_TREE)
+                @Override @DefinedBy(Api.COMPILER_TREE)
                 public long getEndPosition(CompilationUnitTree file, Tree tree) {
                     EndPosTable endPosTable = ((JCCompilationUnit) file).endPositions;
                     return TreeInfo.getEndPos((JCTree) tree, endPosTable);
                 }
 
-                @DefinedBy(Api.COMPILER_TREE)
+                @Override @DefinedBy(Api.COMPILER_TREE)
                 public long getStartPosition(CompilationUnitTree file, DocCommentTree comment, DocTree tree) {
                     return ((DCTree) tree).getSourcePosition((DCDocComment) comment);
                 }
-                @SuppressWarnings("fallthrough") @DefinedBy(Api.COMPILER_TREE)
+                @Override  @DefinedBy(Api.COMPILER_TREE) @SuppressWarnings("fallthrough")
                 public long getEndPosition(CompilationUnitTree file, DocCommentTree comment, DocTree tree) {
                     DCDocComment dcComment = (DCDocComment) comment;
                     if (tree instanceof DCEndPosTree) {
@@ -278,27 +308,27 @@
         return last[0];
     }
 
-    @DefinedBy(Api.COMPILER_TREE)
+    @Override @DefinedBy(Api.COMPILER_TREE)
     public JCClassDecl getTree(TypeElement element) {
         return (JCClassDecl) getTree((Element) element);
     }
 
-    @DefinedBy(Api.COMPILER_TREE)
+    @Override @DefinedBy(Api.COMPILER_TREE)
     public JCMethodDecl getTree(ExecutableElement method) {
         return (JCMethodDecl) getTree((Element) method);
     }
 
-    @DefinedBy(Api.COMPILER_TREE)
+    @Override @DefinedBy(Api.COMPILER_TREE)
     public JCTree getTree(Element element) {
         return getTree(element, null);
     }
 
-    @DefinedBy(Api.COMPILER_TREE)
+    @Override @DefinedBy(Api.COMPILER_TREE)
     public JCTree getTree(Element e, AnnotationMirror a) {
         return getTree(e, a, null);
     }
 
-    @DefinedBy(Api.COMPILER_TREE)
+    @Override @DefinedBy(Api.COMPILER_TREE)
     public JCTree getTree(Element e, AnnotationMirror a, AnnotationValue v) {
         Pair<JCTree, JCCompilationUnit> treeTopLevel = elements.getTreeAndTopLevel(e, a, v);
         if (treeTopLevel == null)
@@ -306,22 +336,22 @@
         return treeTopLevel.fst;
     }
 
-    @DefinedBy(Api.COMPILER_TREE)
+    @Override @DefinedBy(Api.COMPILER_TREE)
     public TreePath getPath(CompilationUnitTree unit, Tree node) {
         return TreePath.getPath(unit, node);
     }
 
-    @DefinedBy(Api.COMPILER_TREE)
+    @Override @DefinedBy(Api.COMPILER_TREE)
     public TreePath getPath(Element e) {
         return getPath(e, null, null);
     }
 
-    @DefinedBy(Api.COMPILER_TREE)
+    @Override @DefinedBy(Api.COMPILER_TREE)
     public TreePath getPath(Element e, AnnotationMirror a) {
         return getPath(e, a, null);
     }
 
-    @DefinedBy(Api.COMPILER_TREE)
+    @Override @DefinedBy(Api.COMPILER_TREE)
     public TreePath getPath(Element e, AnnotationMirror a, AnnotationValue v) {
         final Pair<JCTree, JCCompilationUnit> treeTopLevel = elements.getTreeAndTopLevel(e, a, v);
         if (treeTopLevel == null)
@@ -329,7 +359,7 @@
         return TreePath.getPath(treeTopLevel.snd, treeTopLevel.fst);
     }
 
-    @DefinedBy(Api.COMPILER_TREE)
+    @Override @DefinedBy(Api.COMPILER_TREE)
     public Symbol getElement(TreePath path) {
         JCTree tree = (JCTree) path.getLeaf();
         Symbol sym = TreeInfo.symbolFor(tree);
@@ -479,7 +509,7 @@
 
     /** @see com.sun.tools.javadoc.ClassDocImpl#findField */
     private VarSymbol findField(ClassSymbol tsym, Name fieldName) {
-        return searchField(tsym, fieldName, new HashSet<ClassSymbol>());
+        return searchField(tsym, fieldName, new HashSet<>());
     }
 
     /** @see com.sun.tools.javadoc.ClassDocImpl#searchField */
@@ -543,7 +573,7 @@
 
     /** @see com.sun.tools.javadoc.ClassDocImpl#findMethod */
     private MethodSymbol findMethod(ClassSymbol tsym, Name methodName, List<Type> paramTypes) {
-        return searchMethod(tsym, methodName, paramTypes, new HashSet<ClassSymbol>());
+        return searchMethod(tsym, methodName, paramTypes, new HashSet<>());
     }
 
     /** @see com.sun.tools.javadoc.ClassDocImpl#searchMethod */
@@ -708,19 +738,19 @@
         }
     };
 
-    @DefinedBy(Api.COMPILER_TREE)
+    @Override @DefinedBy(Api.COMPILER_TREE)
     public TypeMirror getTypeMirror(TreePath path) {
         Tree t = path.getLeaf();
         Type ty = ((JCTree)t).type;
         return ty == null ? null : ty.stripMetadataIfNeeded();
     }
 
-    @DefinedBy(Api.COMPILER_TREE)
+    @Override @DefinedBy(Api.COMPILER_TREE)
     public JavacScope getScope(TreePath path) {
         return JavacScope.create(getAttrContext(path));
     }
 
-    @DefinedBy(Api.COMPILER_TREE)
+    @Override @DefinedBy(Api.COMPILER_TREE)
     public String getDocComment(TreePath path) {
         CompilationUnitTree t = path.getCompilationUnit();
         Tree leaf = path.getLeaf();
@@ -733,7 +763,7 @@
         return null;
     }
 
-    @DefinedBy(Api.COMPILER_TREE)
+    @Override @DefinedBy(Api.COMPILER_TREE)
     public DocCommentTree getDocCommentTree(TreePath path) {
         CompilationUnitTree t = path.getCompilationUnit();
         Tree leaf = path.getLeaf();
@@ -746,7 +776,28 @@
         return null;
     }
 
-    @DefinedBy(Api.COMPILER_TREE)
+    @Override @DefinedBy(Api.COMPILER_TREE)
+    public DocCommentTree getDocCommentTree(Element e) {
+        TreePath path = getPath(e);
+        if (path == null) {
+            return null;
+        }
+        return getDocCommentTree(path);
+    }
+
+    @Override @DefinedBy(Api.COMPILER_TREE)
+    public DocCommentTree getDocCommentTree(Element e, String relativeFileName) throws IOException {
+        PackageElement pkg = elements.getPackageOf(e);
+        FileObject fileForInput = fileManager.getFileForInput(StandardLocation.SOURCE_PATH,
+                pkg.getQualifiedName().toString(), relativeFileName);
+
+        if (fileForInput == null) {
+            throw new FileNotFoundException(relativeFileName);
+        }
+        return getDocCommentTree(fileForInput);
+    }
+
+    @Override @DefinedBy(Api.COMPILER_TREE)
     public boolean isAccessible(Scope scope, TypeElement type) {
         if (scope instanceof JavacScope && type instanceof ClassSymbol) {
             Env<AttrContext> env = ((JavacScope) scope).env;
@@ -755,7 +806,7 @@
             return false;
     }
 
-    @DefinedBy(Api.COMPILER_TREE)
+    @Override @DefinedBy(Api.COMPILER_TREE)
     public boolean isAccessible(Scope scope, Element member, DeclaredType type) {
         if (scope instanceof JavacScope
                 && member instanceof Symbol
@@ -862,6 +913,109 @@
         }
     }
 
+    private JavaFileObject asJavaFileObject(FileObject fileObject) {
+        JavaFileObject jfo = null;
+
+        if (fileObject instanceof JavaFileObject) {
+            jfo = (JavaFileObject) fileObject;
+            checkHtmlKind(fileObject, Kind.HTML);
+            return jfo;
+        }
+
+        checkHtmlKind(fileObject);
+        jfo = new HtmlFileObject(fileObject);
+        return jfo;
+    }
+
+    private void checkHtmlKind(FileObject fileObject) {
+        checkHtmlKind(fileObject, BaseFileManager.getKind(fileObject.getName()));
+    }
+
+    private void checkHtmlKind(FileObject fileObject, JavaFileObject.Kind kind) {
+        if (kind != JavaFileObject.Kind.HTML) {
+            throw new IllegalArgumentException("HTML file expected:" + fileObject.getName());
+        }
+    }
+
+    private static class HtmlFileObject extends ForwardingFileObject<FileObject>
+            implements JavaFileObject {
+
+        public HtmlFileObject(FileObject fileObject) {
+            super(fileObject);
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
+        public Kind getKind() {
+            return BaseFileManager.getKind(fileObject.getName());
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
+        public boolean isNameCompatible(String simpleName, Kind kind) {
+            return false;
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
+        public NestingKind getNestingKind() {
+            return null;
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
+        public Modifier getAccessLevel() {
+            return null;
+        }
+    }
+
+    @Override @DefinedBy(Api.COMPILER_TREE)
+    public DocCommentTree getDocCommentTree(FileObject fileObject) {
+        JavaFileObject jfo = asJavaFileObject(fileObject);
+        DiagnosticSource diagSource = new DiagnosticSource(jfo, log);
+
+        final Comment comment = new Comment() {
+            int offset = 0;
+            @Override
+            public String getText() {
+                try {
+                    CharSequence rawDoc = fileObject.getCharContent(true);
+                    Pattern bodyPat =
+                            Pattern.compile("(?is).*?<body\\b[^>]*>(.*)</body\\b.*");
+                    Matcher m = bodyPat.matcher(rawDoc);
+                    if (m.matches()) {
+                        offset = m.end(1);
+                        return m.group(1);
+                    } else {
+                        // Assume doclint will do the right thing.
+                        return "";
+                    }
+                } catch (IOException ignore) {
+                    // do nothing
+                }
+                return "";
+            }
+
+            @Override
+            public int getSourcePos(int index) {
+                return offset + index;
+            }
+
+            @Override
+            public CommentStyle getStyle() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public boolean isDeprecated() {
+                throw new UnsupportedOperationException();
+            }
+        };
+
+        return new DocCommentParser(parser, diagSource, comment).parse();
+    }
+
+    @Override @DefinedBy(Api.COMPILER_TREE)
+    public void setBreakIterator(BreakIterator breakiterator) {
+        this.breakIterator = breakiterator;
+    }
+
     /**
      * Makes a copy of a tree, noting the value resulting from copying a particular leaf.
      **/
@@ -891,7 +1045,7 @@
      * @return TypeMirror corresponding to the original type, replaced by the ErrorType.
      *         noType (type.tag == NONE) is returned if there is no original type.
      */
-    @DefinedBy(Api.COMPILER_TREE)
+    @Override @DefinedBy(Api.COMPILER_TREE)
     public TypeMirror getOriginalType(javax.lang.model.type.ErrorType errorType) {
         if (errorType instanceof com.sun.tools.javac.code.Type.ErrorType) {
             return ((com.sun.tools.javac.code.Type.ErrorType)errorType).getOriginalType();
@@ -909,14 +1063,14 @@
      * @param t    the tree to use as a position hint
      * @param root the compilation unit that contains tree
      */
-    @DefinedBy(Api.COMPILER_TREE)
+    @Override @DefinedBy(Api.COMPILER_TREE)
     public void printMessage(Diagnostic.Kind kind, CharSequence msg,
             com.sun.source.tree.Tree t,
             com.sun.source.tree.CompilationUnitTree root) {
         printMessage(kind, msg, ((JCTree) t).pos(), root);
     }
 
-    @DefinedBy(Api.COMPILER_TREE)
+    @Override @DefinedBy(Api.COMPILER_TREE)
     public void printMessage(Diagnostic.Kind kind, CharSequence msg,
             com.sun.source.doctree.DocTree t,
             com.sun.source.doctree.DocCommentTree c,
@@ -971,4 +1125,30 @@
             return v.type;
         }
     }
+
+    public TreePath makeTreePath(final FileObject fileObject, final int offset) {
+        JavaFileObject jfo = asJavaFileObject(fileObject);
+        JCCompilationUnit jcCompilationUnit = new JCCompilationUnit(List.nil()) {
+            public int getPos() {
+                return offset;
+            }
+
+            public JavaFileObject getSourcefile() {
+                return jfo;
+            }
+
+            @Override @DefinedBy(Api.COMPILER_TREE)
+            public Position.LineMap getLineMap() {
+                try {
+                    CharSequence content = fileObject.getCharContent(true);
+                    String s = content.toString();
+                    return Position.makeLineMap(s.toCharArray(), s.length(), true);
+                } catch (IOException ignore) {}
+                return null;
+            }
+        };
+        jcCompilationUnit.sourcefile = jfo;
+        enter.main(List.of(jcCompilationUnit));
+        return new TreePath(jcCompilationUnit);
+    }
 }
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java	Wed Jul 05 20:56:54 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java	Wed Oct 28 10:41:30 2015 -0700
@@ -30,15 +30,15 @@
 import java.util.Collection;
 import java.util.EnumSet;
 import java.util.ListIterator;
-import java.util.Locale;
 
 import com.sun.source.doctree.AttributeTree.ValueKind;
 import com.sun.source.doctree.DocTree;
 import com.sun.source.doctree.DocTree.Kind;
 import com.sun.source.doctree.EndElementTree;
 import com.sun.source.doctree.StartElementTree;
+import com.sun.source.doctree.TextTree;
 import com.sun.tools.doclint.HtmlTag;
-
+import com.sun.tools.javac.api.JavacTrees;
 import com.sun.tools.javac.parser.Tokens.Comment;
 import com.sun.tools.javac.tree.DCTree.DCAttribute;
 import com.sun.tools.javac.tree.DCTree.DCAuthor;
@@ -75,7 +75,6 @@
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.ListBuffer;
 import com.sun.tools.javac.util.Name;
-import com.sun.tools.javac.util.Options;
 import com.sun.tools.javac.util.Pair;
 import com.sun.tools.javac.util.Position;
 
@@ -97,8 +96,6 @@
     // anywhere but the zero'th position in the first sentence.
     final EnumSet<HtmlTag> sentenceBreakTags;
 
-    private final BreakIterator sentenceBreaker;
-
     /** Get the TreeMaker instance. */
     public static DocTreeMaker instance(Context context) {
         DocTreeMaker instance = context.get(treeMakerKey);
@@ -114,21 +111,16 @@
     /** Access to diag factory for ErroneousTrees. */
     private final JCDiagnostic.Factory diags;
 
+    private final JavacTrees trees;
+
     /** Create a tree maker with NOPOS as initial position.
      */
     protected DocTreeMaker(Context context) {
         context.put(treeMakerKey, this);
         diags = JCDiagnostic.Factory.instance(context);
         this.pos = Position.NOPOS;
+        trees = JavacTrees.instance(context);
         sentenceBreakTags = EnumSet.of(H1, H2, H3, H4, H5, H6, PRE, P);
-        Locale locale = (context.get(Locale.class) != null)
-                ? context.get(Locale.class)
-                : Locale.getDefault();
-        Options options = Options.instance(context);
-        boolean useBreakIterator = options.isSet("breakiterator");
-        sentenceBreaker = (useBreakIterator || !locale.getLanguage().equals(Locale.ENGLISH.getLanguage()))
-                ? BreakIterator.getSentenceInstance(locale)
-                : null;
     }
 
     /** Reassign current position.
@@ -176,10 +168,23 @@
     }
 
     public DCDocComment DocComment(Comment comment, List<DCTree> fullBody, List<DCTree> tags) {
-        final int savepos = pos;
         Pair<List<DCTree>, List<DCTree>> pair = splitBody(fullBody);
         DCDocComment tree = new DCDocComment(comment, fullBody, pair.fst, pair.snd, tags);
-        this.pos = tree.pos = savepos;
+        tree.pos = pos;
+        return tree;
+    }
+
+    /*
+     * Primarily to produce a DocCommenTree when given a
+     * first sentence and a body, this is useful, in cases
+     * where the trees are being synthesized by a tool.
+     */
+    public DCDocComment DocComment(List<DCTree> firstSentence, List<DCTree> body, List<DCTree> tags) {
+        ListBuffer<DCTree> lb = new ListBuffer<>();
+        lb.addAll(firstSentence);
+        lb.addAll(body);
+        List<DCTree> fullBody = lb.toList();
+        DCDocComment tree = new DCDocComment(null, fullBody, firstSentence, body, tags);
         return tree;
     }
 
@@ -341,74 +346,88 @@
 
     /*
      * Breaks up the body tags into the first sentence and its successors.
-     * The first sentence is determined with the presence of a period, block tag,
-     * or a sentence break, as returned by the BreakIterator. Trailing
-     * whitespaces are trimmed.
+     * The first sentence is determined with the presence of a period,
+     * block tag, or a sentence break, as returned by the BreakIterator.
+     * Trailing whitespaces are trimmed.
      */
-    Pair<List<DCTree>, List<DCTree>> splitBody(Collection<? extends DocTree> list) {
-        ListBuffer<DCTree> body = new ListBuffer<>();
-        // split body into first sentence and body
-        ListBuffer<DCTree> fs = new ListBuffer<>();
-        if (list.isEmpty()) {
-            return new Pair<>(fs.toList(), body.toList());
-        }
-        boolean foundFirstSentence = false;
-        ArrayList<DocTree> alist = new ArrayList<>(list);
-        ListIterator<DocTree> itr = alist.listIterator();
-        while (itr.hasNext()) {
-            boolean isFirst = itr.previousIndex() == -1;
-            DocTree dt = itr.next();
-            int spos = ((DCTree)dt).pos;
-            if (foundFirstSentence) {
-                body.add((DCTree) dt);
-                continue;
+    private Pair<List<DCTree>, List<DCTree>> splitBody(Collection<? extends DocTree> list) {
+        // pos is modified as we create trees, therefore
+        // we save the pos and restore it later.
+        final int savedpos = this.pos;
+        try {
+            ListBuffer<DCTree> body = new ListBuffer<>();
+            // split body into first sentence and body
+            ListBuffer<DCTree> fs = new ListBuffer<>();
+            if (list.isEmpty()) {
+                return new Pair<>(fs.toList(), body.toList());
             }
-            switch (dt.getKind()) {
-                case TEXT:
-                    DCText tt = (DCText)dt;
-                    String s = tt.getBody();
-                    int sbreak = getSentenceBreak(s);
-                    if (sbreak > 0) {
-                        s = removeTrailingWhitespace(s.substring(0, sbreak));
-                        DCText text = this.at(spos).Text(s);
-                        fs.add(text);
-                        foundFirstSentence = true;
-                        int nwPos = skipWhiteSpace(tt.getBody(), sbreak);
-                        if (nwPos > 0) {
-                            DCText text2 = this.at(spos + nwPos).Text(tt.getBody().substring(nwPos));
-                            body.add(text2);
-                        }
-                        continue;
-                    } else if (itr.hasNext()) {
-                        // if the next doctree is a break, remove trailing spaces
-                        DocTree next = itr.next();
-                        boolean sbrk = isSentenceBreak(next, false);
-                        if (sbrk) {
-                            s = removeTrailingWhitespace(s);
+            boolean foundFirstSentence = false;
+            ArrayList<DocTree> alist = new ArrayList<>(list);
+            ListIterator<DocTree> itr = alist.listIterator();
+            while (itr.hasNext()) {
+                boolean isFirst = !itr.hasPrevious();
+                DocTree dt = itr.next();
+                int spos = ((DCTree) dt).pos;
+                if (foundFirstSentence) {
+                    body.add((DCTree) dt);
+                    continue;
+                }
+                switch (dt.getKind()) {
+                    case TEXT:
+                        DCText tt = (DCText) dt;
+                        String s = tt.getBody();
+                        DocTree peekedNext = itr.hasNext()
+                                ? alist.get(itr.nextIndex())
+                                : null;
+                        int sbreak = getSentenceBreak(s, peekedNext);
+                        if (sbreak > 0) {
+                            s = removeTrailingWhitespace(s.substring(0, sbreak));
                             DCText text = this.at(spos).Text(s);
                             fs.add(text);
-                            body.add((DCTree)next);
+                            foundFirstSentence = true;
+                            int nwPos = skipWhiteSpace(tt.getBody(), sbreak);
+                            if (nwPos > 0) {
+                                DCText text2 = this.at(spos + nwPos).Text(tt.getBody().substring(nwPos));
+                                body.add(text2);
+                            }
+                            continue;
+                        } else if (itr.hasNext()) {
+                            // if the next doctree is a break, remove trailing spaces
+                            peekedNext = alist.get(itr.nextIndex());
+                            boolean sbrk = isSentenceBreak(peekedNext, false);
+                            if (sbrk) {
+                                DocTree next = itr.next();
+                                s = removeTrailingWhitespace(s);
+                                DCText text = this.at(spos).Text(s);
+                                fs.add(text);
+                                body.add((DCTree) next);
+                                foundFirstSentence = true;
+                                continue;
+                            }
+                        }
+                        break;
+                    default:
+                        if (isSentenceBreak(dt, isFirst)) {
+                            body.add((DCTree) dt);
                             foundFirstSentence = true;
                             continue;
                         }
-                        // reset to previous for further processing
-                        itr.previous();
-                    }
-                    break;
-                default:
-                    if (isSentenceBreak(dt, isFirst)) {
-                        body.add((DCTree)dt);
-                        foundFirstSentence = true;
-                        continue;
-                    }
+                        break;
+                }
+                fs.add((DCTree) dt);
             }
-            fs.add((DCTree)dt);
+            return new Pair<>(fs.toList(), body.toList());
+        } finally {
+            this.pos = savedpos;
         }
-        return new Pair<>(fs.toList(), body.toList());
+    }
+
+    private boolean isTextTree(DocTree tree) {
+        return tree.getKind() == Kind.TEXT;
     }
 
     /*
-     * Computes the first sentence break.
+     * Computes the first sentence break, a simple dot-space algorithm.
      */
     int defaultSentenceBreak(String s) {
         // scan for period followed by whitespace
@@ -437,12 +456,74 @@
         return -1;
     }
 
-    int getSentenceBreak(String s) {
-        if (sentenceBreaker == null) {
+    /*
+     * Computes the first sentence, if using a default breaker,
+     * the break is returned, if not then a -1, indicating that
+     * more doctree elements are required to be examined.
+     *
+     * BreakIterator.next points to the the start of the following sentence,
+     * and does not provide an easy way to disambiguate between "sentence break",
+     * "possible sentence break" and "not a sentence break" at the end of the input.
+     * For example, BreakIterator.next returns the index for the end
+     * of the string for all of these examples,
+     * using vertical bars to delimit the bounds of the example text
+     * |Abc|        (not a valid end of sentence break, if followed by more text)
+     * |Abc.|       (maybe a valid end of sentence break, depending on the following text)
+     * |Abc. |      (maybe a valid end of sentence break, depending on the following text)
+     * |"Abc." |    (maybe a valid end of sentence break, depending on the following text)
+     * |Abc.  |     (definitely a valid end of sentence break)
+     * |"Abc."  |   (definitely a valid end of sentence break)
+     * Therefore, we have to probe further to determine whether
+     * there really is a sentence break or not at the end of this run of text.
+     */
+    int getSentenceBreak(String s, DocTree dt) {
+        BreakIterator breakIterator = trees.getBreakIterator();
+        if (breakIterator == null) {
             return defaultSentenceBreak(s);
         }
-        sentenceBreaker.setText(s);
-        return sentenceBreaker.first();
+        breakIterator.setText(s);
+        final int sbrk = breakIterator.next();
+        // This is the last doctree, found the droid we are looking for
+        if (dt == null) {
+            return sbrk;
+        }
+
+        // If the break is well within the span of the string ie. not
+        // at EOL, then we have a clear break.
+        if (sbrk < s.length() - 1) {
+            return sbrk;
+        }
+
+        if (isTextTree(dt)) {
+            // Two adjacent text trees, a corner case, perhaps
+            // produced by a tool synthesizing a doctree. In
+            // this case, does the break lie within the first span,
+            // then we have the droid, otherwise allow the callers
+            // logic to handle the break in the adjacent doctree.
+            TextTree ttnext = (TextTree) dt;
+            String combined = s + ttnext.getBody();
+            breakIterator.setText(combined);
+            int sbrk2 = breakIterator.next();
+            if (sbrk < sbrk2) {
+                return sbrk;
+            }
+        }
+
+        // Is the adjacent tree a sentence breaker ?
+        if (isSentenceBreak(dt, false)) {
+            return sbrk;
+        }
+
+        // At this point the adjacent tree is either a javadoc tag ({@..),
+        // html tag (<..) or an entity (&..). Perform a litmus test, by
+        // concatenating a sentence, to validate the break earlier identified.
+        String combined = s + "Dummy Sentence.";
+        breakIterator.setText(combined);
+        int sbrk2 = breakIterator.next();
+        if (sbrk2 <= sbrk) {
+            return sbrk2;
+        }
+        return -1; // indeterminate at this time
     }
 
     boolean isSentenceBreak(javax.lang.model.element.Name tagName) {
@@ -476,7 +557,7 @@
     }
 
     String removeTrailingWhitespace(String s) {
-        for (int i = s.length() - 1 ; i > 0 ; i--) {
+        for (int i = s.length() - 1 ; i >= 0 ; i--) {
             char ch = s.charAt(i);
             if (!Character.isWhitespace(ch)) {
                 return s.substring(0, i + 1);
--- a/langtools/test/tools/javac/doctree/DocCommentTester.java	Wed Jul 05 20:56:54 2017 +0200
+++ b/langtools/test/tools/javac/doctree/DocCommentTester.java	Wed Oct 28 10:41:30 2015 -0700
@@ -27,10 +27,14 @@
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.io.Writer;
+import java.text.BreakIterator;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
+import java.util.Locale;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
 import javax.lang.model.element.Name;
 import javax.tools.JavaFileObject;
@@ -55,16 +59,28 @@
 
 public class DocCommentTester {
 
+    public static final String BI_MARKER = "BREAK_ITERATOR";
+    public final boolean useBreakIterator;
+
+    public DocCommentTester(boolean useBreakIterator) {
+        this.useBreakIterator = useBreakIterator;
+    }
     public static void main(String... args) throws Exception {
-        new DocCommentTester().run(args);
+        ArrayList<String> list = new ArrayList(Arrays.asList(args));
+        if (!list.isEmpty() && "-useBreakIterator".equals(list.get(0))) {
+            list.remove(0);
+            new DocCommentTester(true).run(list);
+        } else {
+            new DocCommentTester(false).run(list);
+        }
     }
 
-    public void run(String... args) throws Exception {
+    public void run(List<String> args) throws Exception {
         String testSrc = System.getProperty("test.src");
 
-        List<File> files = new ArrayList<File>();
-        for (String arg: args)
-            files.add(new File(testSrc, arg));
+        List<File> files = args.stream()
+                .map(arg -> new File(testSrc, arg))
+                .collect(Collectors.toList());
 
         JavacTool javac = JavacTool.create();
         StandardJavaFileManager fm = javac.getStandardFileManager(null, null, null);
@@ -74,6 +90,11 @@
         JavacTask t = javac.getTask(null, fm, null, null, null, fos);
         final DocTrees trees = DocTrees.instance(t);
 
+        if (useBreakIterator) {
+            // BreakIterators are locale dependent wrt. behavior
+            trees.setBreakIterator(BreakIterator.getSentenceInstance(Locale.ENGLISH));
+        }
+
         final Checker[] checkers = {
             new ASTChecker(this, trees),
             new PosChecker(this, trees),
@@ -179,9 +200,11 @@
         static final String NEWLINE = System.getProperty("line.separator");
         Printer printer = new Printer();
         String source;
+        DocCommentTester test;
 
         ASTChecker(DocCommentTester test, DocTrees t) {
             test.super(t);
+            this.test = test;
         }
 
         @Override
@@ -200,11 +223,21 @@
             out.flush();
             String found = out.toString().replace(NEWLINE, "\n");
 
-            // Look for the first block comment after the first occurrence of name
-            int start = source.indexOf("\n/*\n", findName(source, name));
+            /*
+             * Look for the first block comment after the first occurrence
+             * of name, noting that, block comments with BI_MARKER may
+             * very well be present.
+             */
+            int start = test.useBreakIterator
+                    ? source.indexOf("\n/*\n" + BI_MARKER + "\n", findName(source, name))
+                    : source.indexOf("\n/*\n", findName(source, name));
             int end = source.indexOf("\n*/\n", start);
-            String expect = source.substring(start + 4, end + 1);
+            int startlen = start + (test.useBreakIterator ? BI_MARKER.length() + 1 : 0) + 4;
+            String expect = source.substring(startlen, end + 1);
             if (!found.equals(expect)) {
+                if (test.useBreakIterator) {
+                    System.err.println("Using BreakIterator");
+                }
                 System.err.println("Expect:\n" + expect);
                 System.err.println("Found:\n" + found);
                 error("AST mismatch for " + name);
--- a/langtools/test/tools/javac/doctree/FirstSentenceTest.java	Wed Jul 05 20:56:54 2017 +0200
+++ b/langtools/test/tools/javac/doctree/FirstSentenceTest.java	Wed Oct 28 10:41:30 2015 -0700
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 7021614 8078320
+ * @bug 7021614 8078320 8132096
  * @summary extend com.sun.source API to support parsing javadoc comments
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
@@ -31,6 +31,7 @@
  *          jdk.compiler/com.sun.tools.javac.util
  * @build DocCommentTester
  * @run main DocCommentTester FirstSentenceTest.java
+ * @run main DocCommentTester -useBreakIterator FirstSentenceTest.java
  */
 
 class FirstSentenceTest {
@@ -43,6 +44,14 @@
   block tags: empty
 ]
 */
+/*
+BREAK_ITERATOR
+DocComment[DOC_COMMENT, pos:-1
+  firstSentence: empty
+  body: empty
+  block tags: empty
+]
+*/
 
     /** abc def ghi */
     void no_terminator() { }
@@ -54,6 +63,15 @@
   block tags: empty
 ]
 */
+/*
+BREAK_ITERATOR
+DocComment[DOC_COMMENT, pos:0
+  firstSentence: 1
+    Text[TEXT, pos:0, abc_def_ghi]
+  body: empty
+  block tags: empty
+]
+*/
 
     /**
      * abc def ghi.
@@ -67,7 +85,15 @@
   block tags: empty
 ]
 */
-
+/*
+BREAK_ITERATOR
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 1
+    Text[TEXT, pos:1, abc_def_ghi.]
+  body: empty
+  block tags: empty
+]
+*/
     /**
      * abc def ghi. jkl mno pqr.
      */
@@ -81,7 +107,15 @@
   block tags: empty
 ]
 */
-
+/*
+BREAK_ITERATOR
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 1
+    Text[TEXT, pos:1, abc_def_ghi._jkl_mno_pqr.]
+  body: empty
+  block tags: empty
+]
+*/
     /**
      * abc def ghi.
      * jkl mno pqr
@@ -96,7 +130,16 @@
   block tags: empty
 ]
 */
-
+/*
+BREAK_ITERATOR
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 1
+    Text[TEXT, pos:1, abc_def_ghi.]
+  body: 1
+    Text[TEXT, pos:15, jkl_mno_pqr]
+  block tags: empty
+]
+*/
     /**
      * abc def ghi
      * <p>jkl mno pqr
@@ -115,7 +158,20 @@
   block tags: empty
 ]
 */
-
+/*
+BREAK_ITERATOR
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 1
+    Text[TEXT, pos:1, abc_def_ghi]
+  body: 2
+    StartElement[START_ELEMENT, pos:14
+      name:p
+      attributes: empty
+    ]
+    Text[TEXT, pos:17, jkl_mno_pqr]
+  block tags: empty
+]
+*/
     /**
      *
      * <p>abc def ghi.
@@ -135,7 +191,20 @@
   block tags: empty
 ]
 */
-
+/*
+BREAK_ITERATOR
+DocComment[DOC_COMMENT, pos:2
+  firstSentence: 2
+    StartElement[START_ELEMENT, pos:2
+      name:p
+      attributes: empty
+    ]
+    Text[TEXT, pos:5, abc_def_ghi.]
+  body: 1
+    Text[TEXT, pos:19, jdl_mno_pqf]
+  block tags: empty
+]
+*/
     /**
      * abc def ghi
      * </p>jkl mno pqr
@@ -151,7 +220,17 @@
   block tags: empty
 ]
 */
-
+/*
+BREAK_ITERATOR
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 1
+    Text[TEXT, pos:1, abc_def_ghi]
+  body: 2
+    EndElement[END_ELEMENT, pos:14, p]
+    Text[TEXT, pos:18, jkl_mno_pqr]
+  block tags: empty
+]
+*/
     /**
      * abc &lt; ghi. jkl mno pqr.
      */
@@ -167,7 +246,17 @@
   block tags: empty
 ]
 */
-
+/*
+BREAK_ITERATOR
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 3
+    Text[TEXT, pos:1, abc_]
+    Entity[ENTITY, pos:5, lt]
+    Text[TEXT, pos:9, _ghi._jkl_mno_pqr.]
+  body: empty
+  block tags: empty
+]
+*/
     /**
      * abc {@code code} ghi. jkl mno pqr.
      */
@@ -183,7 +272,17 @@
   block tags: empty
 ]
 */
-
+/*
+BREAK_ITERATOR
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 3
+    Text[TEXT, pos:1, abc_]
+    Literal[CODE, pos:5, code]
+    Text[TEXT, pos:17, _ghi._jkl_mno_pqr.]
+  body: empty
+  block tags: empty
+]
+*/
     /**
      * abc def ghi
      * @author jjg
@@ -201,7 +300,19 @@
     ]
 ]
 */
-
+/*
+BREAK_ITERATOR
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 1
+    Text[TEXT, pos:1, abc_def_ghi]
+  body: empty
+  block tags: 1
+    Author[AUTHOR, pos:14
+      name: 1
+        Text[TEXT, pos:22, jjg]
+    ]
+]
+*/
     /**
      * @author jjg
      */
@@ -217,6 +328,18 @@
     ]
 ]
 */
+/*
+BREAK_ITERATOR
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: empty
+  body: empty
+  block tags: 1
+    Author[AUTHOR, pos:1
+      name: 1
+        Text[TEXT, pos:9, jjg]
+    ]
+]
+*/
     /**
      * <p> abc def.
      * ghi jkl
@@ -235,6 +358,21 @@
   block tags: empty
 ]
 */
+/*
+BREAK_ITERATOR
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 2
+    StartElement[START_ELEMENT, pos:1
+      name:p
+      attributes: empty
+    ]
+    Text[TEXT, pos:4, _abc_def.]
+  body: 1
+    Text[TEXT, pos:15, ghi_jkl]
+  block tags: empty
+]
+*/
+
     /**
      * abc <p> def. ghi jkl
      */
@@ -252,5 +390,19 @@
   block tags: empty
 ]
 */
+/*
+BREAK_ITERATOR
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 1
+    Text[TEXT, pos:1, abc]
+  body: 2
+    StartElement[START_ELEMENT, pos:5
+      name:p
+      attributes: empty
+    ]
+    Text[TEXT, pos:8, _def._ghi_jkl]
+  block tags: empty
+]
+*/
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/doctree/dcapi/DocCommentTreeApiTester.java	Wed Oct 28 10:41:30 2015 -0700
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2015, 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  8132096
+ * @summary test the APIs  in the DocTree interface
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.file
+ *          jdk.compiler/com.sun.tools.javac.tree
+ *          jdk.compiler/com.sun.tools.javac.util
+ * @compile ../DocCommentTester.java DocCommentTreeApiTester.java
+ * @run main DocCommentTreeApiTester
+ */
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.text.BreakIterator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+
+import javax.lang.model.element.Element;
+import javax.tools.FileObject;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+
+import com.sun.source.doctree.DocTree;
+import com.sun.source.doctree.DocCommentTree;
+import com.sun.source.util.DocTrees;
+import com.sun.source.util.JavacTask;
+import com.sun.tools.javac.api.JavacTool;
+import com.sun.tools.javac.tree.DocPretty;
+
+public class DocCommentTreeApiTester {
+
+    private static final String MARKER_START = "<!-- EXPECT_START";
+    private static final String MARKER_END   = "EXPECT_END -->";
+
+    private static final String testSrc = System.getProperty("test.src", ".");
+
+    private static final JavacTool javac = JavacTool.create();
+
+    private static final DocCommentTester.ASTChecker.Printer printer =
+            new DocCommentTester.ASTChecker.Printer();
+    int pass;
+    int fail;
+
+    public DocCommentTreeApiTester() {
+        pass = 0;
+        fail = 0;
+    }
+
+    public static void main(String... args) throws Exception {
+        DocCommentTreeApiTester test = new DocCommentTreeApiTester();
+        try {
+            // test getting a DocTree from an element
+            test.runElementAndBreakIteratorTests("OverviewTest.java", "OverviewTest test.");
+
+            // test relative paths in a class within a package
+            test.runRelativePathTest("pkg/Anchor.java", "package.html");
+
+            // tests files relative path in an unnamed package
+            test.runRelativePathTest("OverviewTest.java", "overview0.html");
+
+            // test for correct parsing using valid and some invalid html tags
+            for (int i = 0; i < 7; i++) {
+                String hname = "overview" + i + ".html";
+                test.runFileObjectTest(hname);
+            }
+
+        } finally {
+            test.status();
+        }
+    }
+    void status() throws Exception {
+        System.err.println("pass:" + pass + "  fail: " + fail);
+        if (fail > 0) {
+            throw new Exception("Fails");
+        }
+    }
+
+    /**
+     * Tests getting a DocCommentTree from an element, as well
+     * as test if break iterator setter/getter works correctly.
+     *
+     * @param javaFileName a test file to be processed
+     * @param expected the expected output
+     * @throws java.io.IOException
+     */
+    public void runElementAndBreakIteratorTests(String javaFileName, String expected) throws IOException {
+        List<File> javaFiles = new ArrayList<>();
+        javaFiles.add(new File(testSrc, javaFileName));
+
+        List<File> dirs = new ArrayList<>();
+        dirs.add(new File(testSrc));
+
+        try (StandardJavaFileManager fm = javac.getStandardFileManager(null, null, null)) {
+            fm.setLocation(javax.tools.StandardLocation.SOURCE_PATH, dirs);
+            Iterable<? extends JavaFileObject> fos = fm.getJavaFileObjectsFromFiles(javaFiles);
+
+            final JavacTask t = javac.getTask(null, fm, null, null, null, fos);
+            final DocTrees trees = DocTrees.instance(t);
+
+            Iterable<? extends Element> elements = t.analyze();
+
+            Element klass = elements.iterator().next();
+            DocCommentTree dcTree = trees.getDocCommentTree(klass);
+
+            List<? extends DocTree> firstSentence = dcTree.getFirstSentence();
+            StringWriter sw = new StringWriter();
+            DocPretty pretty = new DocPretty(sw);
+            pretty.print(firstSentence);
+            check("getDocCommentTree(Element)", expected, sw.toString());
+
+            BreakIterator bi = BreakIterator.getSentenceInstance(Locale.FRENCH);
+            trees.setBreakIterator(bi);
+            BreakIterator nbi = trees.getBreakIterator();
+            if (bi.equals(nbi)) {
+                pass++;
+                check("getDocCommentTree(Element) with BreakIterator", expected, sw.toString());
+            } else {
+                fail++;
+                System.err.println("BreakIterators don't match");
+            }
+        }
+    }
+    /**
+     * Tests DocTrees.getDocCommentTree(Element e, String relpath) using relative path.
+     *
+     * @param javaFileName the reference java file
+     * @param fileName the relative html file
+     * @throws java.lang.Exception ouch
+     */
+    public void runRelativePathTest(String javaFileName, String fileName) throws Exception  {
+        List<File> javaFiles = new ArrayList<>();
+        javaFiles.add(new File(testSrc, javaFileName));
+
+        List<File> dirs = new ArrayList<>();
+        dirs.add(new File(testSrc));
+
+        try (StandardJavaFileManager fm = javac.getStandardFileManager(null, null, null)) {
+            fm.setLocation(javax.tools.StandardLocation.SOURCE_PATH, dirs);
+            Iterable<? extends JavaFileObject> fos = fm.getJavaFileObjectsFromFiles(javaFiles);
+
+            final JavacTask t = javac.getTask(null, fm, null, null, null, fos);
+            final DocTrees trees = DocTrees.instance(t);
+
+            Iterable<? extends Element> elements = t.analyze();
+
+            Element klass = elements.iterator().next();
+
+            DocCommentTree dcTree = trees.getDocCommentTree(klass, fileName);
+            StringWriter sw = new StringWriter();
+            printer.print(dcTree, sw);
+            String found = sw.toString();
+
+            FileObject htmlFo = fm.getFileForInput(javax.tools.StandardLocation.SOURCE_PATH,
+                    t.getElements().getPackageOf(klass).getQualifiedName().toString(),
+                    fileName);
+
+            String expected = getExpected(htmlFo.openReader(true));
+            astcheck(fileName, expected, found);
+        }
+    }
+
+    /**
+     * Tests DocTrees.getDocCommentTree(FileObject fo).
+     *
+     * @param htmlfileName the file to be parsed
+     * @throws Exception when an error occurs.
+     */
+    public void runFileObjectTest(String htmlfileName) throws Exception {
+        List<File> javaFiles =  Collections.emptyList();
+
+        List<File> otherFiles = new ArrayList<>();
+        otherFiles.add(new File(testSrc, htmlfileName));
+
+        try (StandardJavaFileManager fm = javac.getStandardFileManager(null, null, null)) {
+            Iterable<? extends JavaFileObject> fos = fm.getJavaFileObjectsFromFiles(javaFiles);
+            Iterable<? extends JavaFileObject> others = fm.getJavaFileObjectsFromFiles(otherFiles);
+
+            final JavacTask t = javac.getTask(null, fm, null, null, null, fos);
+            final DocTrees trees = DocTrees.instance(t);
+
+            StringWriter sw = new StringWriter();
+
+            printer.print(trees.getDocCommentTree(others.iterator().next()), sw);
+            String found = sw.toString();
+            String expected = getExpected(otherFiles.iterator().next().toPath());
+            astcheck(otherFiles.toString(), expected, found);
+        }
+    }
+
+    void astcheck(String testinfo, String expected, String found) {
+        System.err.print("ASTChecker: " + testinfo);
+        check0(expected, found);
+    }
+    void check(String testinfo, String expected, String found) {
+        System.err.print(testinfo);
+        check0(expected, found);
+    }
+    void check0(String expected, String found) {
+        if (expected.equals(found)) {
+            pass++;
+            System.err.println(" PASS");
+        } else {
+            fail++;
+            System.err.println(" FAILED");
+            System.err.println("Expect:\n" + expected);
+            System.err.println("Found:\n" + found);
+        }
+    }
+
+    String getExpected(Reader inrdr) throws IOException {
+        BufferedReader rdr = new BufferedReader(inrdr);
+        List<String> lines = new ArrayList<>();
+        String line = rdr.readLine();
+        while (line != null) {
+            lines.add(line);
+            line = rdr.readLine();
+        }
+        return getExpected(lines);
+    }
+
+    String getExpected(Path p) throws IOException {
+        return getExpected(Files.readAllLines(p));
+    }
+
+    String getExpected(List<String> lines) {
+        boolean start = false;
+        StringWriter sw = new StringWriter();
+        PrintWriter out = new PrintWriter(sw);
+        for (String line : lines) {
+            if (!start) {
+                start = line.startsWith(MARKER_START);
+                continue;
+            }
+            if (line.startsWith(MARKER_END)) {
+                out.flush();
+                return sw.toString();
+            }
+            out.println(line);
+        }
+        return out.toString() + "Warning: html comment end not found";
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/doctree/dcapi/OverviewTest.java	Wed Oct 28 10:41:30 2015 -0700
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+/**
+ * OverviewTest test.
+ */
+public class OverviewTest {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/doctree/dcapi/overview0.html	Wed Oct 28 10:41:30 2015 -0700
@@ -0,0 +1,48 @@
+<!--
+ Copyright (c) 2015, 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.
+-->
+<!-- EXPECT_START
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 1
+    Text[TEXT, pos:1, A_simple_well_fo...rmed_html_document]
+  body: 4
+    StartElement[START_ELEMENT, pos:36
+      name:pre
+      attributes: empty
+    ]
+    Text[TEXT, pos:41, overview0.html]
+    StartElement[START_ELEMENT, pos:55
+      name:pre
+      attributes: empty
+    ]
+    Text[TEXT, pos:60, .]
+  block tags: empty
+]
+EXPECT_END -->
+<HTML>
+<HEAD>
+</HEAD>
+<BODY>
+A simple well formed html document <pre>overview0.html<pre>.
+</BODY>
+</HTML>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/doctree/dcapi/overview1.html	Wed Oct 28 10:41:30 2015 -0700
@@ -0,0 +1,47 @@
+<!--
+ Copyright (c) 2015, 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.
+-->
+<!-- EXPECT_START
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 1
+    Text[TEXT, pos:1, Html_document]
+  body: 4
+    StartElement[START_ELEMENT, pos:15
+      name:pre
+      attributes: empty
+    ]
+    Text[TEXT, pos:20, overview1.html]
+    StartElement[START_ELEMENT, pos:34
+      name:pre
+      attributes: empty
+    ]
+    Text[TEXT, pos:39, .|Missing_HTML.]
+  block tags: empty
+]
+EXPECT_END -->
+<HEAD>
+</HEAD>
+<BODY>
+Html document <pre>overview1.html<pre>.
+Missing HTML.
+</BODY>
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/doctree/dcapi/overview2.html	Wed Oct 28 10:41:30 2015 -0700
@@ -0,0 +1,47 @@
+<!--
+ Copyright (c) 2015, 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.
+-->
+<!-- EXPECT_START
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 1
+    Text[TEXT, pos:1, Html_document]
+  body: 4
+    StartElement[START_ELEMENT, pos:15
+      name:pre
+      attributes: empty
+    ]
+    Text[TEXT, pos:20, overview2.html]
+    StartElement[START_ELEMENT, pos:34
+      name:pre
+      attributes: empty
+    ]
+    Text[TEXT, pos:39, .|Missing_HEAD.]
+  block tags: empty
+]
+EXPECT_END -->
+<HTML>
+</HEAD>
+<BODY>
+Html document <pre>overview2.html<pre>.
+Missing HEAD.
+</BODY>
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/doctree/dcapi/overview3.html	Wed Oct 28 10:41:30 2015 -0700
@@ -0,0 +1,47 @@
+<!--
+ Copyright (c) 2015, 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.
+-->
+<!-- EXPECT_START
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 1
+    Text[TEXT, pos:1, Html_document]
+  body: 4
+    StartElement[START_ELEMENT, pos:15
+      name:pre
+      attributes: empty
+    ]
+    Text[TEXT, pos:20, overview3.html]
+    StartElement[START_ELEMENT, pos:34
+      name:pre
+      attributes: empty
+    ]
+    Text[TEXT, pos:39, .|Missing_enclosing_HEAD.]
+  block tags: empty
+]
+EXPECT_END -->
+<HTML>
+<HEAD>
+<BODY>
+Html document <pre>overview3.html<pre>.
+Missing enclosing HEAD.
+</BODY>
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/doctree/dcapi/overview4.html	Wed Oct 28 10:41:30 2015 -0700
@@ -0,0 +1,44 @@
+<!--
+ Copyright (c) 2015, 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.
+-->
+<!-- EXPECT_START
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 1
+    Text[TEXT, pos:1, Html_document]
+  body: 4
+    StartElement[START_ELEMENT, pos:15
+      name:pre
+      attributes: empty
+    ]
+    Text[TEXT, pos:20, overview4.html]
+    StartElement[START_ELEMENT, pos:34
+      name:pre
+      attributes: empty
+    ]
+    Text[TEXT, pos:39, .|Only_BODY]
+  block tags: empty
+]
+EXPECT_END -->
+<BODY>
+Html document <pre>overview4.html<pre>.
+Only BODY
+</BODY>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/doctree/dcapi/overview5.html	Wed Oct 28 10:41:30 2015 -0700
@@ -0,0 +1,47 @@
+<!--
+ Copyright (c) 2015, 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.
+-->
+<!-- EXPECT_START
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 1
+    Text[TEXT, pos:1, Html_document]
+  body: 4
+    StartElement[START_ELEMENT, pos:15
+      name:pre
+      attributes: empty
+    ]
+    Text[TEXT, pos:20, overview5.html]
+    StartElement[START_ELEMENT, pos:34
+      name:pre
+      attributes: empty
+    ]
+    Text[TEXT, pos:39, .|Missing_enclosing_HTML]
+  block tags: empty
+]
+EXPECT_END -->
+<HTML>
+<HEAD>
+</HEAD>
+<BODY>
+Html document <pre>overview5.html<pre>.
+Missing enclosing HTML
+</BODY>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/doctree/dcapi/overview6.html	Wed Oct 28 10:41:30 2015 -0700
@@ -0,0 +1,49 @@
+<!--
+ Copyright (c) 2015, 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.
+-->
+<!-- EXPECT_START
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 1
+    Text[TEXT, pos:1, The_first_correct_body_pair.]
+  body: 4
+    EndElement[END_ELEMENT, pos:30, BODY]
+    Text[TEXT, pos:37, ||]
+    StartElement[START_ELEMENT, pos:39
+      name:BODY
+      attributes: empty
+    ]
+    Text[TEXT, pos:45, |Illegal_second_...body_pair,_the_first_body_should_not_be_ignored.]
+  block tags: empty
+]
+EXPECT_END -->
+<HTML>
+<HEAD>
+</HEAD>
+<BODY>
+The first correct body pair.
+</BODY>
+
+<BODY>
+Illegal second body pair, the first body should not be ignored.
+</BODY>
+</HTML>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/doctree/dcapi/package.html	Wed Oct 28 10:41:30 2015 -0700
@@ -0,0 +1,47 @@
+<!--
+ Copyright (c) 2015, 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.
+-->
+<HTML>
+<HEAD>
+</HEAD>
+<BODY>
+A simple well formed html document <pre>package.html<pre>.
+</BODY>
+</HTML>
+<!-- EXPECT_START
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 1
+    Text[TEXT, pos:1, This_is_a_very_simple]
+  body: 4
+    StartElement[START_ELEMENT, pos:23
+      name:pre
+      attributes: empty
+    ]
+    Text[TEXT, pos:28, _well_formed_html_document_]
+    StartElement[START_ELEMENT, pos:55
+      name:pre
+      attributes: empty
+    ]
+    Text[TEXT, pos:60, _using_some_html_tags.]
+  block tags: empty
+]
+EXPECT_END -->
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/doctree/dcapi/pkg/Anchor.java	Wed Oct 28 10:41:30 2015 -0700
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package pkg;
+
+/**
+ * The anchor class.
+ */
+public class Anchor {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/doctree/dcapi/pkg/package.html	Wed Oct 28 10:41:30 2015 -0700
@@ -0,0 +1,48 @@
+<!--
+ Copyright (c) 2015, 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.
+-->
+<!-- EXPECT_START
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 1
+    Text[TEXT, pos:1, A_simple_well_fo...rmed_html_document]
+  body: 4
+    StartElement[START_ELEMENT, pos:36
+      name:pre
+      attributes: empty
+    ]
+    Text[TEXT, pos:41, package.html]
+    StartElement[START_ELEMENT, pos:53
+      name:pre
+      attributes: empty
+    ]
+    Text[TEXT, pos:58, .|In_package_pkg.]
+  block tags: empty
+]
+EXPECT_END -->
+<HTML>
+<HEAD>
+</HEAD>
+<BODY>
+A simple well formed html document <pre>package.html<pre>.
+In package pkg.
+</BODY>
+</HTML>
--- a/langtools/test/tools/javac/tree/NoPrivateTypesExported.java	Wed Jul 05 20:56:54 2017 +0200
+++ b/langtools/test/tools/javac/tree/NoPrivateTypesExported.java	Wed Oct 28 10:41:30 2015 -0700
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8026180
+ * @bug 8026180 8132096
  * @summary Ensuring javax.lang.model.**, javax.tools.**, javax.annotation.processing.**
  *          and com.sun.source.** don't export inappropriate types.
  * @library /tools/javac/lib
@@ -87,6 +87,7 @@
             "java.lang.",
             "java.net.",
             "java.nio.",
+            "java.text.",
             "java.util.",
             "javax.lang.model.",
             "javax.annotation.processing.SupportedSourceVersion",