langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java
changeset 35346 c0614a805fad
parent 34567 c74f68484156
child 36276 37bd10863a8a
equal deleted inserted replaced
35005:2dc4c11fe488 35346:c0614a805fad
     1 /*
     1 /*
     2  * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    27 
    27 
    28 import java.text.BreakIterator;
    28 import java.text.BreakIterator;
    29 import java.util.ArrayList;
    29 import java.util.ArrayList;
    30 import java.util.Collection;
    30 import java.util.Collection;
    31 import java.util.EnumSet;
    31 import java.util.EnumSet;
       
    32 import java.util.List;
    32 import java.util.ListIterator;
    33 import java.util.ListIterator;
       
    34 
       
    35 import javax.lang.model.element.Name;
       
    36 import javax.tools.Diagnostic;
       
    37 import javax.tools.JavaFileObject;
    33 
    38 
    34 import com.sun.source.doctree.AttributeTree.ValueKind;
    39 import com.sun.source.doctree.AttributeTree.ValueKind;
    35 import com.sun.source.doctree.DocTree;
    40 import com.sun.source.doctree.DocTree;
    36 import com.sun.source.doctree.DocTree.Kind;
    41 import com.sun.source.doctree.DocTree.Kind;
    37 import com.sun.source.doctree.EndElementTree;
    42 import com.sun.source.doctree.EndElementTree;
       
    43 import com.sun.source.doctree.IdentifierTree;
       
    44 import com.sun.source.doctree.ReferenceTree;
    38 import com.sun.source.doctree.StartElementTree;
    45 import com.sun.source.doctree.StartElementTree;
    39 import com.sun.source.doctree.TextTree;
    46 import com.sun.source.doctree.TextTree;
       
    47 import com.sun.source.util.DocTreeFactory;
    40 import com.sun.tools.doclint.HtmlTag;
    48 import com.sun.tools.doclint.HtmlTag;
    41 import com.sun.tools.javac.api.JavacTrees;
    49 import com.sun.tools.javac.api.JavacTrees;
       
    50 import com.sun.tools.javac.parser.ParserFactory;
       
    51 import com.sun.tools.javac.parser.ReferenceParser;
    42 import com.sun.tools.javac.parser.Tokens.Comment;
    52 import com.sun.tools.javac.parser.Tokens.Comment;
    43 import com.sun.tools.javac.tree.DCTree.DCAttribute;
    53 import com.sun.tools.javac.tree.DCTree.DCAttribute;
    44 import com.sun.tools.javac.tree.DCTree.DCAuthor;
    54 import com.sun.tools.javac.tree.DCTree.DCAuthor;
    45 import com.sun.tools.javac.tree.DCTree.DCComment;
    55 import com.sun.tools.javac.tree.DCTree.DCComment;
    46 import com.sun.tools.javac.tree.DCTree.DCDeprecated;
    56 import com.sun.tools.javac.tree.DCTree.DCDeprecated;
    68 import com.sun.tools.javac.tree.DCTree.DCUnknownBlockTag;
    78 import com.sun.tools.javac.tree.DCTree.DCUnknownBlockTag;
    69 import com.sun.tools.javac.tree.DCTree.DCUnknownInlineTag;
    79 import com.sun.tools.javac.tree.DCTree.DCUnknownInlineTag;
    70 import com.sun.tools.javac.tree.DCTree.DCValue;
    80 import com.sun.tools.javac.tree.DCTree.DCValue;
    71 import com.sun.tools.javac.tree.DCTree.DCVersion;
    81 import com.sun.tools.javac.tree.DCTree.DCVersion;
    72 import com.sun.tools.javac.util.Context;
    82 import com.sun.tools.javac.util.Context;
       
    83 import com.sun.tools.javac.util.DefinedBy;
       
    84 import com.sun.tools.javac.util.DefinedBy.Api;
    73 import com.sun.tools.javac.util.DiagnosticSource;
    85 import com.sun.tools.javac.util.DiagnosticSource;
    74 import com.sun.tools.javac.util.JCDiagnostic;
    86 import com.sun.tools.javac.util.JCDiagnostic;
    75 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
    87 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
    76 import com.sun.tools.javac.util.List;
       
    77 import com.sun.tools.javac.util.ListBuffer;
    88 import com.sun.tools.javac.util.ListBuffer;
    78 import com.sun.tools.javac.util.Name;
       
    79 import com.sun.tools.javac.util.Pair;
    89 import com.sun.tools.javac.util.Pair;
    80 import com.sun.tools.javac.util.Position;
    90 import com.sun.tools.javac.util.Position;
    81 
    91 
    82 import static com.sun.tools.doclint.HtmlTag.*;
    92 import static com.sun.tools.doclint.HtmlTag.*;
    83 
    93 
    86  *  <p><b>This is NOT part of any supported API.
    96  *  <p><b>This is NOT part of any supported API.
    87  *  If you write code that depends on this, you do so at your own risk.
    97  *  If you write code that depends on this, you do so at your own risk.
    88  *  This code and its internal interfaces are subject to change or
    98  *  This code and its internal interfaces are subject to change or
    89  *  deletion without notice.</b>
    99  *  deletion without notice.</b>
    90  */
   100  */
    91 public class DocTreeMaker {
   101 public class DocTreeMaker implements DocTreeFactory {
    92 
   102 
    93     /** The context key for the tree factory. */
   103     /** The context key for the tree factory. */
    94     protected static final Context.Key<DocTreeMaker> treeMakerKey = new Context.Key<>();
   104     protected static final Context.Key<DocTreeMaker> treeMakerKey = new Context.Key<>();
    95 
   105 
    96     // A subset of block tags, which acts as sentence breakers, appearing
   106     // A subset of block tags, which acts as sentence breakers, appearing
   112     /** Access to diag factory for ErroneousTrees. */
   122     /** Access to diag factory for ErroneousTrees. */
   113     private final JCDiagnostic.Factory diags;
   123     private final JCDiagnostic.Factory diags;
   114 
   124 
   115     private final JavacTrees trees;
   125     private final JavacTrees trees;
   116 
   126 
       
   127     /** Utility class to parse reference signatures. */
       
   128     private final ReferenceParser referenceParser;
       
   129 
   117     /** Create a tree maker with NOPOS as initial position.
   130     /** Create a tree maker with NOPOS as initial position.
   118      */
   131      */
   119     protected DocTreeMaker(Context context) {
   132     protected DocTreeMaker(Context context) {
   120         context.put(treeMakerKey, this);
   133         context.put(treeMakerKey, this);
   121         diags = JCDiagnostic.Factory.instance(context);
   134         diags = JCDiagnostic.Factory.instance(context);
   122         this.pos = Position.NOPOS;
   135         this.pos = Position.NOPOS;
   123         trees = JavacTrees.instance(context);
   136         trees = JavacTrees.instance(context);
       
   137         referenceParser = new ReferenceParser(ParserFactory.instance(context));
   124         sentenceBreakTags = EnumSet.of(H1, H2, H3, H4, H5, H6, PRE, P);
   138         sentenceBreakTags = EnumSet.of(H1, H2, H3, H4, H5, H6, PRE, P);
   125     }
   139     }
   126 
   140 
   127     /** Reassign current position.
   141     /** Reassign current position.
   128      */
   142      */
       
   143     @Override @DefinedBy(Api.COMPILER_TREE)
   129     public DocTreeMaker at(int pos) {
   144     public DocTreeMaker at(int pos) {
   130         this.pos = pos;
   145         this.pos = pos;
   131         return this;
   146         return this;
   132     }
   147     }
   133 
   148 
   136     public DocTreeMaker at(DiagnosticPosition pos) {
   151     public DocTreeMaker at(DiagnosticPosition pos) {
   137         this.pos = (pos == null ? Position.NOPOS : pos.getStartPosition());
   152         this.pos = (pos == null ? Position.NOPOS : pos.getStartPosition());
   138         return this;
   153         return this;
   139     }
   154     }
   140 
   155 
   141     public DCAttribute Attribute(Name name, ValueKind vkind, List<DCTree> value) {
   156     @Override @DefinedBy(Api.COMPILER_TREE)
   142         DCAttribute tree = new DCAttribute(name, vkind, value);
   157     public DCAttribute newAttributeTree(javax.lang.model.element.Name name, ValueKind vkind, java.util.List<? extends DocTree> value) {
   143         tree.pos = pos;
   158         DCAttribute tree = new DCAttribute(name, vkind, cast(value));
   144         return tree;
   159         tree.pos = pos;
   145     }
   160         return tree;
   146 
   161     }
   147     public DCAuthor Author(List<DCTree> name) {
   162 
   148         DCAuthor tree = new DCAuthor(name);
   163     @Override @DefinedBy(Api.COMPILER_TREE)
   149         tree.pos = pos;
   164     public DCAuthor newAuthorTree(java.util.List<? extends DocTree> name) {
   150         return tree;
   165         DCAuthor tree = new DCAuthor(cast(name));
   151     }
   166         tree.pos = pos;
   152 
   167         return tree;
   153     public DCLiteral Code(DCText text) {
   168     }
   154         DCLiteral tree = new DCLiteral(Kind.CODE, text);
   169 
   155         tree.pos = pos;
   170     @Override @DefinedBy(Api.COMPILER_TREE)
   156         return tree;
   171     public DCLiteral newCodeTree(TextTree text) {
   157     }
   172         DCLiteral tree = new DCLiteral(Kind.CODE, (DCText) text);
   158 
   173         tree.pos = pos;
   159     public DCComment Comment(String text) {
   174         return tree;
       
   175     }
       
   176 
       
   177     @Override @DefinedBy(Api.COMPILER_TREE)
       
   178     public DCComment newCommentTree(String text) {
   160         DCComment tree = new DCComment(text);
   179         DCComment tree = new DCComment(text);
   161         tree.pos = pos;
   180         tree.pos = pos;
   162         return tree;
   181         return tree;
   163     }
   182     }
   164 
   183 
   165     public DCDeprecated Deprecated(List<DCTree> text) {
   184     @Override @DefinedBy(Api.COMPILER_TREE)
   166         DCDeprecated tree = new DCDeprecated(text);
   185     public DCDeprecated newDeprecatedTree(List<? extends DocTree> text) {
   167         tree.pos = pos;
   186         DCDeprecated tree = new DCDeprecated(cast(text));
   168         return tree;
   187         tree.pos = pos;
   169     }
   188         return tree;
   170 
   189     }
   171     public DCDocComment DocComment(Comment comment, List<DCTree> fullBody, List<DCTree> tags) {
   190 
       
   191     public DCDocComment newDocCommentTree(Comment comment, List<? extends DocTree> fullBody, List<? extends DocTree> tags) {
   172         Pair<List<DCTree>, List<DCTree>> pair = splitBody(fullBody);
   192         Pair<List<DCTree>, List<DCTree>> pair = splitBody(fullBody);
   173         DCDocComment tree = new DCDocComment(comment, fullBody, pair.fst, pair.snd, tags);
   193         DCDocComment tree = new DCDocComment(comment, cast(fullBody), pair.fst, pair.snd, cast(tags));
   174         tree.pos = pos;
   194         tree.pos = pos;
   175         return tree;
   195         return tree;
   176     }
   196     }
   177 
   197 
   178     /*
   198     /*
   179      * Primarily to produce a DocCommenTree when given a
   199      * Primarily to produce a DocCommenTree when given a
   180      * first sentence and a body, this is useful, in cases
   200      * first sentence and a body, this is useful, in cases
   181      * where the trees are being synthesized by a tool.
   201      * where the trees are being synthesized by a tool.
   182      */
   202      */
   183     public DCDocComment DocComment(List<DCTree> firstSentence, List<DCTree> body, List<DCTree> tags) {
   203     @Override @DefinedBy(Api.COMPILER_TREE)
       
   204     public DCDocComment newDocCommentTree(List<? extends DocTree> firstSentence, List<? extends DocTree> body, List<? extends DocTree> tags) {
   184         ListBuffer<DCTree> lb = new ListBuffer<>();
   205         ListBuffer<DCTree> lb = new ListBuffer<>();
   185         lb.addAll(firstSentence);
   206         lb.addAll(cast(firstSentence));
   186         lb.addAll(body);
   207         lb.addAll(cast(body));
   187         List<DCTree> fullBody = lb.toList();
   208         List<DCTree> fullBody = lb.toList();
   188         DCDocComment tree = new DCDocComment(null, fullBody, firstSentence, body, tags);
   209         DCDocComment tree = new DCDocComment(null, fullBody, cast(firstSentence), cast(body), cast(tags));
   189         return tree;
   210         return tree;
   190     }
   211     }
   191 
   212 
   192     public DCDocRoot DocRoot() {
   213     @Override @DefinedBy(Api.COMPILER_TREE)
       
   214     public DCDocRoot newDocRootTree() {
   193         DCDocRoot tree = new DCDocRoot();
   215         DCDocRoot tree = new DCDocRoot();
   194         tree.pos = pos;
   216         tree.pos = pos;
   195         return tree;
   217         return tree;
   196     }
   218     }
   197 
   219 
   198     public DCEndElement EndElement(Name name) {
   220     @Override @DefinedBy(Api.COMPILER_TREE)
       
   221     public DCEndElement newEndElementTree(Name name) {
   199         DCEndElement tree = new DCEndElement(name);
   222         DCEndElement tree = new DCEndElement(name);
   200         tree.pos = pos;
   223         tree.pos = pos;
   201         return tree;
   224         return tree;
   202     }
   225     }
   203 
   226 
   204     public DCEntity Entity(Name name) {
   227     @Override @DefinedBy(Api.COMPILER_TREE)
       
   228     public DCEntity newEntityTree(Name name) {
   205         DCEntity tree = new DCEntity(name);
   229         DCEntity tree = new DCEntity(name);
   206         tree.pos = pos;
   230         tree.pos = pos;
   207         return tree;
   231         return tree;
   208     }
   232     }
   209 
   233 
   210     public DCErroneous Erroneous(String text, DiagnosticSource diagSource, String code, Object... args) {
   234     @Override @DefinedBy(Api.COMPILER_TREE)
       
   235     public DCErroneous newErroneousTree(String text, Diagnostic<JavaFileObject> diag) {
       
   236         DCErroneous tree = new DCErroneous(text, (JCDiagnostic) diag);
       
   237         tree.pos = pos;
       
   238         return tree;
       
   239     }
       
   240 
       
   241     public DCErroneous newErroneousTree(String text, DiagnosticSource diagSource, String code, Object... args) {
   211         DCErroneous tree = new DCErroneous(text, diags, diagSource, code, args);
   242         DCErroneous tree = new DCErroneous(text, diags, diagSource, code, args);
   212         tree.pos = pos;
   243         tree.pos = pos;
   213         return tree;
   244         return tree;
   214     }
   245     }
   215 
   246 
   216     public DCThrows Exception(DCReference name, List<DCTree> description) {
   247     @Override @DefinedBy(Api.COMPILER_TREE)
   217         DCThrows tree = new DCThrows(Kind.EXCEPTION, name, description);
   248     public DCThrows newExceptionTree(ReferenceTree name, List<? extends DocTree> description) {
   218         tree.pos = pos;
   249         // TODO: verify the reference is just to a type (not a field or method)
   219         return tree;
   250         DCThrows tree = new DCThrows(Kind.EXCEPTION, (DCReference) name, cast(description));
   220     }
   251         tree.pos = pos;
   221 
   252         return tree;
   222     public DCIdentifier Identifier(Name name) {
   253     }
       
   254 
       
   255     @Override @DefinedBy(Api.COMPILER_TREE)
       
   256     public DCIdentifier newIdentifierTree(Name name) {
   223         DCIdentifier tree = new DCIdentifier(name);
   257         DCIdentifier tree = new DCIdentifier(name);
   224         tree.pos = pos;
   258         tree.pos = pos;
   225         return tree;
   259         return tree;
   226     }
   260     }
   227 
   261 
   228     public DCIndex Index(DCTree term, List<DCTree> description) {
   262     @Override @DefinedBy(Api.COMPILER_TREE)
   229         DCIndex tree = new DCIndex(term, description);
   263     public DCIndex newIndexTree(DocTree term, List<? extends DocTree> description) {
   230         tree.pos = pos;
   264         DCIndex tree = new DCIndex((DCTree) term, cast(description));
   231         return tree;
   265         tree.pos = pos;
   232     }
   266         return tree;
   233 
   267     }
   234     public DCInheritDoc InheritDoc() {
   268 
       
   269     @Override @DefinedBy(Api.COMPILER_TREE)
       
   270     public DCInheritDoc newInheritDocTree() {
   235         DCInheritDoc tree = new DCInheritDoc();
   271         DCInheritDoc tree = new DCInheritDoc();
   236         tree.pos = pos;
   272         tree.pos = pos;
   237         return tree;
   273         return tree;
   238     }
   274     }
   239 
   275 
   240     public DCLink Link(DCReference ref, List<DCTree> label) {
   276     @Override @DefinedBy(Api.COMPILER_TREE)
   241         DCLink tree = new DCLink(Kind.LINK, ref, label);
   277     public DCLink newLinkTree(ReferenceTree ref, List<? extends DocTree> label) {
   242         tree.pos = pos;
   278         DCLink tree = new DCLink(Kind.LINK, (DCReference) ref, cast(label));
   243         return tree;
   279         tree.pos = pos;
   244     }
   280         return tree;
   245 
   281     }
   246     public DCLink LinkPlain(DCReference ref, List<DCTree> label) {
   282 
   247         DCLink tree = new DCLink(Kind.LINK_PLAIN, ref, label);
   283     @Override @DefinedBy(Api.COMPILER_TREE)
   248         tree.pos = pos;
   284     public DCLink newLinkPlainTree(ReferenceTree ref, List<? extends DocTree> label) {
   249         return tree;
   285         DCLink tree = new DCLink(Kind.LINK_PLAIN, (DCReference) ref, cast(label));
   250     }
   286         tree.pos = pos;
   251 
   287         return tree;
   252     public DCLiteral Literal(DCText text) {
   288     }
   253         DCLiteral tree = new DCLiteral(Kind.LITERAL, text);
   289 
   254         tree.pos = pos;
   290     @Override @DefinedBy(Api.COMPILER_TREE)
   255         return tree;
   291     public DCLiteral newLiteralTree(TextTree text) {
   256     }
   292         DCLiteral tree = new DCLiteral(Kind.LITERAL, (DCText) text);
   257 
   293         tree.pos = pos;
   258     public DCParam Param(boolean isTypeParameter, DCIdentifier name, List<DCTree> description) {
   294         return tree;
   259         DCParam tree = new DCParam(isTypeParameter, name, description);
   295     }
   260         tree.pos = pos;
   296 
   261         return tree;
   297     @Override @DefinedBy(Api.COMPILER_TREE)
   262     }
   298     public DCParam newParamTree(boolean isTypeParameter, IdentifierTree name, List<? extends DocTree> description) {
   263 
   299         DCParam tree = new DCParam(isTypeParameter, (DCIdentifier) name, cast(description));
   264     public DCReference Reference(String signature,
   300         tree.pos = pos;
   265             JCTree qualExpr, Name member, List<JCTree> paramTypes) {
   301         return tree;
       
   302     }
       
   303 
       
   304     @Override @DefinedBy(Api.COMPILER_TREE)
       
   305     public DCReference newReferenceTree(String signature) {
       
   306         try {
       
   307             ReferenceParser.Reference ref = referenceParser.parse(signature);
       
   308             DCReference tree = new DCReference(signature, ref.qualExpr, ref.member, ref.paramTypes);
       
   309             tree.pos = pos;
       
   310             return tree;
       
   311         } catch (ReferenceParser.ParseException e) {
       
   312             throw new IllegalArgumentException("invalid signature", e);
       
   313         }
       
   314     }
       
   315 
       
   316     public DCReference newReferenceTree(String signature, JCTree qualExpr, Name member, List<JCTree> paramTypes) {
   266         DCReference tree = new DCReference(signature, qualExpr, member, paramTypes);
   317         DCReference tree = new DCReference(signature, qualExpr, member, paramTypes);
   267         tree.pos = pos;
   318         tree.pos = pos;
   268         return tree;
   319         return tree;
   269     }
   320     }
   270 
   321 
   271     public DCReturn Return(List<DCTree> description) {
   322     @Override @DefinedBy(Api.COMPILER_TREE)
   272         DCReturn tree = new DCReturn(description);
   323     public DCReturn newReturnTree(List<? extends DocTree> description) {
   273         tree.pos = pos;
   324         DCReturn tree = new DCReturn(cast(description));
   274         return tree;
   325         tree.pos = pos;
   275     }
   326         return tree;
   276 
   327     }
   277     public DCSee See(List<DCTree> reference) {
   328 
   278         DCSee tree = new DCSee(reference);
   329     @Override @DefinedBy(Api.COMPILER_TREE)
   279         tree.pos = pos;
   330     public DCSee newSeeTree(List<? extends DocTree> reference) {
   280         return tree;
   331         DCSee tree = new DCSee(cast(reference));
   281     }
   332         tree.pos = pos;
   282 
   333         return tree;
   283     public DCSerial Serial(List<DCTree> description) {
   334     }
   284         DCSerial tree = new DCSerial(description);
   335 
   285         tree.pos = pos;
   336     @Override @DefinedBy(Api.COMPILER_TREE)
   286         return tree;
   337     public DCSerial newSerialTree(List<? extends DocTree> description) {
   287     }
   338         DCSerial tree = new DCSerial(cast(description));
   288 
   339         tree.pos = pos;
   289     public DCSerialData SerialData(List<DCTree> description) {
   340         return tree;
   290         DCSerialData tree = new DCSerialData(description);
   341     }
   291         tree.pos = pos;
   342 
   292         return tree;
   343     @Override @DefinedBy(Api.COMPILER_TREE)
   293     }
   344     public DCSerialData newSerialDataTree(List<? extends DocTree> description) {
   294 
   345         DCSerialData tree = new DCSerialData(cast(description));
   295     public DCSerialField SerialField(DCIdentifier name, DCReference type, List<DCTree> description) {
   346         tree.pos = pos;
   296         DCSerialField tree = new DCSerialField(name, type, description);
   347         return tree;
   297         tree.pos = pos;
   348     }
   298         return tree;
   349 
   299     }
   350     @Override @DefinedBy(Api.COMPILER_TREE)
   300 
   351     public DCSerialField newSerialFieldTree(IdentifierTree name, ReferenceTree type, List<? extends DocTree> description) {
   301     public DCSince Since(List<DCTree> text) {
   352         DCSerialField tree = new DCSerialField((DCIdentifier) name, (DCReference) type, cast(description));
   302         DCSince tree = new DCSince(text);
   353         tree.pos = pos;
   303         tree.pos = pos;
   354         return tree;
   304         return tree;
   355     }
   305     }
   356 
   306 
   357     @Override @DefinedBy(Api.COMPILER_TREE)
   307     public DCStartElement StartElement(Name name, List<DCTree> attrs, boolean selfClosing) {
   358     public DCSince newSinceTree(List<? extends DocTree> text) {
   308         DCStartElement tree = new DCStartElement(name, attrs, selfClosing);
   359         DCSince tree = new DCSince(cast(text));
   309         tree.pos = pos;
   360         tree.pos = pos;
   310         return tree;
   361         return tree;
   311     }
   362     }
   312 
   363 
   313     public DCText Text(String text) {
   364     @Override @DefinedBy(Api.COMPILER_TREE)
       
   365     public DCStartElement newStartElementTree(Name name, List<? extends DocTree> attrs, boolean selfClosing) {
       
   366         DCStartElement tree = new DCStartElement(name, cast(attrs), selfClosing);
       
   367         tree.pos = pos;
       
   368         return tree;
       
   369     }
       
   370 
       
   371     @Override @DefinedBy(Api.COMPILER_TREE)
       
   372     public DCText newTextTree(String text) {
   314         DCText tree = new DCText(text);
   373         DCText tree = new DCText(text);
   315         tree.pos = pos;
   374         tree.pos = pos;
   316         return tree;
   375         return tree;
   317     }
   376     }
   318 
   377 
   319     public DCThrows Throws(DCReference name, List<DCTree> description) {
   378     @Override @DefinedBy(Api.COMPILER_TREE)
   320         DCThrows tree = new DCThrows(Kind.THROWS, name, description);
   379     public DCThrows newThrowsTree(ReferenceTree name, List<? extends DocTree> description) {
   321         tree.pos = pos;
   380         // TODO: verify the reference is just to a type (not a field or method)
   322         return tree;
   381         DCThrows tree = new DCThrows(Kind.THROWS, (DCReference) name, cast(description));
   323     }
   382         tree.pos = pos;
   324 
   383         return tree;
   325     public DCUnknownBlockTag UnknownBlockTag(Name name, List<DCTree> content) {
   384     }
   326         DCUnknownBlockTag tree = new DCUnknownBlockTag(name, content);
   385 
   327         tree.pos = pos;
   386     @Override @DefinedBy(Api.COMPILER_TREE)
   328         return tree;
   387     public DCUnknownBlockTag newUnknownBlockTagTree(Name name, List<? extends DocTree> content) {
   329     }
   388         DCUnknownBlockTag tree = new DCUnknownBlockTag(name, cast(content));
   330 
   389         tree.pos = pos;
   331     public DCUnknownInlineTag UnknownInlineTag(Name name, List<DCTree> content) {
   390         return tree;
   332         DCUnknownInlineTag tree = new DCUnknownInlineTag(name, content);
   391     }
   333         tree.pos = pos;
   392 
   334         return tree;
   393     @Override @DefinedBy(Api.COMPILER_TREE)
   335     }
   394     public DCUnknownInlineTag newUnknownInlineTagTree(Name name, List<? extends DocTree> content) {
   336 
   395         DCUnknownInlineTag tree = new DCUnknownInlineTag(name, cast(content));
   337     public DCValue Value(DCReference ref) {
   396         tree.pos = pos;
   338         DCValue tree = new DCValue(ref);
   397         return tree;
   339         tree.pos = pos;
   398     }
   340         return tree;
   399 
   341     }
   400     @Override @DefinedBy(Api.COMPILER_TREE)
   342 
   401     public DCValue newValueTree(ReferenceTree ref) {
   343     public DCVersion Version(List<DCTree> text) {
   402         // TODO: verify the reference is to a constant value
   344         DCVersion tree = new DCVersion(text);
   403         DCValue tree = new DCValue((DCReference) ref);
   345         tree.pos = pos;
   404         tree.pos = pos;
   346         return tree;
   405         return tree;
   347     }
   406     }
   348 
   407 
       
   408     @Override @DefinedBy(Api.COMPILER_TREE)
       
   409     public DCVersion newVersionTree(List<? extends DocTree> text) {
       
   410         DCVersion tree = new DCVersion(cast(text));
       
   411         tree.pos = pos;
       
   412         return tree;
       
   413     }
       
   414 
       
   415     @Override @DefinedBy(Api.COMPILER_TREE)
   349     public java.util.List<DocTree> getFirstSentence(java.util.List<? extends DocTree> list) {
   416     public java.util.List<DocTree> getFirstSentence(java.util.List<? extends DocTree> list) {
   350         Pair<List<DCTree>, List<DCTree>> pair = splitBody(list);
   417         Pair<List<DCTree>, List<DCTree>> pair = splitBody(list);
   351         return new ArrayList<>(pair.fst);
   418         return new ArrayList<>(pair.fst);
   352     }
   419     }
   353 
   420 
   387                                 ? alist.get(itr.nextIndex())
   454                                 ? alist.get(itr.nextIndex())
   388                                 : null;
   455                                 : null;
   389                         int sbreak = getSentenceBreak(s, peekedNext);
   456                         int sbreak = getSentenceBreak(s, peekedNext);
   390                         if (sbreak > 0) {
   457                         if (sbreak > 0) {
   391                             s = removeTrailingWhitespace(s.substring(0, sbreak));
   458                             s = removeTrailingWhitespace(s.substring(0, sbreak));
   392                             DCText text = this.at(spos).Text(s);
   459                             DCText text = this.at(spos).newTextTree(s);
   393                             fs.add(text);
   460                             fs.add(text);
   394                             foundFirstSentence = true;
   461                             foundFirstSentence = true;
   395                             int nwPos = skipWhiteSpace(tt.getBody(), sbreak);
   462                             int nwPos = skipWhiteSpace(tt.getBody(), sbreak);
   396                             if (nwPos > 0) {
   463                             if (nwPos > 0) {
   397                                 DCText text2 = this.at(spos + nwPos).Text(tt.getBody().substring(nwPos));
   464                                 DCText text2 = this.at(spos + nwPos).newTextTree(tt.getBody().substring(nwPos));
   398                                 body.add(text2);
   465                                 body.add(text2);
   399                             }
   466                             }
   400                             continue;
   467                             continue;
   401                         } else if (itr.hasNext()) {
   468                         } else if (itr.hasNext()) {
   402                             // if the next doctree is a break, remove trailing spaces
   469                             // if the next doctree is a break, remove trailing spaces
   403                             peekedNext = alist.get(itr.nextIndex());
   470                             peekedNext = alist.get(itr.nextIndex());
   404                             boolean sbrk = isSentenceBreak(peekedNext, false);
   471                             boolean sbrk = isSentenceBreak(peekedNext, false);
   405                             if (sbrk) {
   472                             if (sbrk) {
   406                                 DocTree next = itr.next();
   473                                 DocTree next = itr.next();
   407                                 s = removeTrailingWhitespace(s);
   474                                 s = removeTrailingWhitespace(s);
   408                                 DCText text = this.at(spos).Text(s);
   475                                 DCText text = this.at(spos).newTextTree(s);
   409                                 fs.add(text);
   476                                 fs.add(text);
   410                                 body.add((DCTree) next);
   477                                 body.add((DCTree) next);
   411                                 foundFirstSentence = true;
   478                                 foundFirstSentence = true;
   412                                 continue;
   479                                 continue;
   413                             }
   480                             }
   434     }
   501     }
   435 
   502 
   436     /*
   503     /*
   437      * Computes the first sentence break, a simple dot-space algorithm.
   504      * Computes the first sentence break, a simple dot-space algorithm.
   438      */
   505      */
   439     int defaultSentenceBreak(String s) {
   506     private int defaultSentenceBreak(String s) {
   440         // scan for period followed by whitespace
   507         // scan for period followed by whitespace
   441         int period = -1;
   508         int period = -1;
   442         for (int i = 0; i < s.length(); i++) {
   509         for (int i = 0; i < s.length(); i++) {
   443             switch (s.charAt(i)) {
   510             switch (s.charAt(i)) {
   444                 case '.':
   511                 case '.':
   481      * |Abc.  |     (definitely a valid end of sentence break)
   548      * |Abc.  |     (definitely a valid end of sentence break)
   482      * |"Abc."  |   (definitely a valid end of sentence break)
   549      * |"Abc."  |   (definitely a valid end of sentence break)
   483      * Therefore, we have to probe further to determine whether
   550      * Therefore, we have to probe further to determine whether
   484      * there really is a sentence break or not at the end of this run of text.
   551      * there really is a sentence break or not at the end of this run of text.
   485      */
   552      */
   486     int getSentenceBreak(String s, DocTree dt) {
   553     private int getSentenceBreak(String s, DocTree dt) {
   487         BreakIterator breakIterator = trees.getBreakIterator();
   554         BreakIterator breakIterator = trees.getBreakIterator();
   488         if (breakIterator == null) {
   555         if (breakIterator == null) {
   489             return defaultSentenceBreak(s);
   556             return defaultSentenceBreak(s);
   490         }
   557         }
   491         breakIterator.setText(s);
   558         breakIterator.setText(s);
   531             return sbrk2;
   598             return sbrk2;
   532         }
   599         }
   533         return -1; // indeterminate at this time
   600         return -1; // indeterminate at this time
   534     }
   601     }
   535 
   602 
   536     boolean isSentenceBreak(javax.lang.model.element.Name tagName) {
   603     private boolean isSentenceBreak(javax.lang.model.element.Name tagName) {
   537         return sentenceBreakTags.contains(get(tagName));
   604         return sentenceBreakTags.contains(get(tagName));
   538     }
   605     }
   539 
   606 
   540     boolean isSentenceBreak(DocTree dt, boolean isFirstDocTree) {
   607     private boolean isSentenceBreak(DocTree dt, boolean isFirstDocTree) {
   541         switch (dt.getKind()) {
   608         switch (dt.getKind()) {
   542             case START_ELEMENT:
   609             case START_ELEMENT:
   543                     StartElementTree set = (StartElementTree)dt;
   610                     StartElementTree set = (StartElementTree)dt;
   544                     return !isFirstDocTree && ((DCTree) dt).pos > 1 && isSentenceBreak(set.getName());
   611                     return !isFirstDocTree && ((DCTree) dt).pos > 1 && isSentenceBreak(set.getName());
   545             case END_ELEMENT:
   612             case END_ELEMENT:
   551     }
   618     }
   552 
   619 
   553     /*
   620     /*
   554      * Returns the position of the the first non-white space
   621      * Returns the position of the the first non-white space
   555      */
   622      */
   556     int skipWhiteSpace(String s, int start) {
   623     private int skipWhiteSpace(String s, int start) {
   557         for (int i = start; i < s.length(); i++) {
   624         for (int i = start; i < s.length(); i++) {
   558             char c = s.charAt(i);
   625             char c = s.charAt(i);
   559             if (!Character.isWhitespace(c)) {
   626             if (!Character.isWhitespace(c)) {
   560                 return i;
   627                 return i;
   561             }
   628             }
   562         }
   629         }
   563         return -1;
   630         return -1;
   564     }
   631     }
   565 
   632 
   566     String removeTrailingWhitespace(String s) {
   633     private String removeTrailingWhitespace(String s) {
   567         for (int i = s.length() - 1 ; i >= 0 ; i--) {
   634         for (int i = s.length() - 1 ; i >= 0 ; i--) {
   568             char ch = s.charAt(i);
   635             char ch = s.charAt(i);
   569             if (!Character.isWhitespace(ch)) {
   636             if (!Character.isWhitespace(ch)) {
   570                 return s.substring(0, i + 1);
   637                 return s.substring(0, i + 1);
   571             }
   638             }
   572         }
   639         }
   573         return s;
   640         return s;
   574     }
   641     }
       
   642 
       
   643     @SuppressWarnings("unchecked")
       
   644     private List<DCTree> cast(List<? extends DocTree> list) {
       
   645         return (List<DCTree>) list;
       
   646     }
   575 }
   647 }