DocTreeMaker.java revision 3279:e90d9efcb13f
1/* 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. 4 * 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 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.tools.javac.tree; 27 28import java.text.BreakIterator; 29import java.util.ArrayList; 30import java.util.Collection; 31import java.util.EnumSet; 32import java.util.List; 33import java.util.ListIterator; 34 35import javax.lang.model.element.Name; 36import javax.tools.Diagnostic; 37import javax.tools.JavaFileObject; 38 39import com.sun.source.doctree.AttributeTree.ValueKind; 40import com.sun.source.doctree.DocTree; 41import com.sun.source.doctree.DocTree.Kind; 42import com.sun.source.doctree.EndElementTree; 43import com.sun.source.doctree.IdentifierTree; 44import com.sun.source.doctree.ReferenceTree; 45import com.sun.source.doctree.StartElementTree; 46import com.sun.source.doctree.TextTree; 47import com.sun.source.util.DocTreeFactory; 48import com.sun.tools.doclint.HtmlTag; 49import com.sun.tools.javac.api.JavacTrees; 50import com.sun.tools.javac.parser.ParserFactory; 51import com.sun.tools.javac.parser.ReferenceParser; 52import com.sun.tools.javac.parser.Tokens.Comment; 53import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle; 54import com.sun.tools.javac.tree.DCTree.DCAttribute; 55import com.sun.tools.javac.tree.DCTree.DCAuthor; 56import com.sun.tools.javac.tree.DCTree.DCComment; 57import com.sun.tools.javac.tree.DCTree.DCDeprecated; 58import com.sun.tools.javac.tree.DCTree.DCDocComment; 59import com.sun.tools.javac.tree.DCTree.DCDocRoot; 60import com.sun.tools.javac.tree.DCTree.DCEndElement; 61import com.sun.tools.javac.tree.DCTree.DCEntity; 62import com.sun.tools.javac.tree.DCTree.DCErroneous; 63import com.sun.tools.javac.tree.DCTree.DCIdentifier; 64import com.sun.tools.javac.tree.DCTree.DCIndex; 65import com.sun.tools.javac.tree.DCTree.DCInheritDoc; 66import com.sun.tools.javac.tree.DCTree.DCLink; 67import com.sun.tools.javac.tree.DCTree.DCLiteral; 68import com.sun.tools.javac.tree.DCTree.DCParam; 69import com.sun.tools.javac.tree.DCTree.DCReference; 70import com.sun.tools.javac.tree.DCTree.DCReturn; 71import com.sun.tools.javac.tree.DCTree.DCSee; 72import com.sun.tools.javac.tree.DCTree.DCSerial; 73import com.sun.tools.javac.tree.DCTree.DCSerialData; 74import com.sun.tools.javac.tree.DCTree.DCSerialField; 75import com.sun.tools.javac.tree.DCTree.DCSince; 76import com.sun.tools.javac.tree.DCTree.DCStartElement; 77import com.sun.tools.javac.tree.DCTree.DCText; 78import com.sun.tools.javac.tree.DCTree.DCThrows; 79import com.sun.tools.javac.tree.DCTree.DCUnknownBlockTag; 80import com.sun.tools.javac.tree.DCTree.DCUnknownInlineTag; 81import com.sun.tools.javac.tree.DCTree.DCValue; 82import com.sun.tools.javac.tree.DCTree.DCVersion; 83import com.sun.tools.javac.util.Context; 84import com.sun.tools.javac.util.DefinedBy; 85import com.sun.tools.javac.util.DefinedBy.Api; 86import com.sun.tools.javac.util.DiagnosticSource; 87import com.sun.tools.javac.util.JCDiagnostic; 88import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 89import com.sun.tools.javac.util.ListBuffer; 90import com.sun.tools.javac.util.Pair; 91import com.sun.tools.javac.util.Position; 92 93import static com.sun.tools.doclint.HtmlTag.*; 94 95/** 96 * 97 * <p><b>This is NOT part of any supported API. 98 * If you write code that depends on this, you do so at your own risk. 99 * This code and its internal interfaces are subject to change or 100 * deletion without notice.</b> 101 */ 102public class DocTreeMaker implements DocTreeFactory { 103 104 /** The context key for the tree factory. */ 105 protected static final Context.Key<DocTreeMaker> treeMakerKey = new Context.Key<>(); 106 107 // A subset of block tags, which acts as sentence breakers, appearing 108 // anywhere but the zero'th position in the first sentence. 109 final EnumSet<HtmlTag> sentenceBreakTags; 110 111 /** Get the TreeMaker instance. */ 112 public static DocTreeMaker instance(Context context) { 113 DocTreeMaker instance = context.get(treeMakerKey); 114 if (instance == null) 115 instance = new DocTreeMaker(context); 116 return instance; 117 } 118 119 /** The position at which subsequent trees will be created. 120 */ 121 public int pos = Position.NOPOS; 122 123 /** Access to diag factory for ErroneousTrees. */ 124 private final JCDiagnostic.Factory diags; 125 126 private final JavacTrees trees; 127 128 /** Utility class to parse reference signatures. */ 129 private final ReferenceParser referenceParser; 130 131 /** Create a tree maker with NOPOS as initial position. 132 */ 133 protected DocTreeMaker(Context context) { 134 context.put(treeMakerKey, this); 135 diags = JCDiagnostic.Factory.instance(context); 136 this.pos = Position.NOPOS; 137 trees = JavacTrees.instance(context); 138 referenceParser = new ReferenceParser(ParserFactory.instance(context)); 139 sentenceBreakTags = EnumSet.of(H1, H2, H3, H4, H5, H6, PRE, P); 140 } 141 142 /** Reassign current position. 143 */ 144 @Override @DefinedBy(Api.COMPILER_TREE) 145 public DocTreeMaker at(int pos) { 146 this.pos = pos; 147 return this; 148 } 149 150 /** Reassign current position. 151 */ 152 public DocTreeMaker at(DiagnosticPosition pos) { 153 this.pos = (pos == null ? Position.NOPOS : pos.getStartPosition()); 154 return this; 155 } 156 157 @Override @DefinedBy(Api.COMPILER_TREE) 158 public DCAttribute newAttributeTree(javax.lang.model.element.Name name, ValueKind vkind, java.util.List<? extends DocTree> value) { 159 DCAttribute tree = new DCAttribute(name, vkind, cast(value)); 160 tree.pos = pos; 161 return tree; 162 } 163 164 @Override @DefinedBy(Api.COMPILER_TREE) 165 public DCAuthor newAuthorTree(java.util.List<? extends DocTree> name) { 166 DCAuthor tree = new DCAuthor(cast(name)); 167 tree.pos = pos; 168 return tree; 169 } 170 171 @Override @DefinedBy(Api.COMPILER_TREE) 172 public DCLiteral newCodeTree(TextTree text) { 173 DCLiteral tree = new DCLiteral(Kind.CODE, (DCText) text); 174 tree.pos = pos; 175 return tree; 176 } 177 178 @Override @DefinedBy(Api.COMPILER_TREE) 179 public DCComment newCommentTree(String text) { 180 DCComment tree = new DCComment(text); 181 tree.pos = pos; 182 return tree; 183 } 184 185 @Override @DefinedBy(Api.COMPILER_TREE) 186 public DCDeprecated newDeprecatedTree(List<? extends DocTree> text) { 187 DCDeprecated tree = new DCDeprecated(cast(text)); 188 tree.pos = pos; 189 return tree; 190 } 191 192 public DCDocComment newDocCommentTree(Comment comment, List<? extends DocTree> fullBody, List<? extends DocTree> tags) { 193 Pair<List<DCTree>, List<DCTree>> pair = splitBody(fullBody); 194 DCDocComment tree = new DCDocComment(comment, cast(fullBody), pair.fst, pair.snd, cast(tags)); 195 tree.pos = pos; 196 return tree; 197 } 198 199 /* 200 * Primarily to produce a DocCommenTree when given a 201 * first sentence and a body, this is useful, in cases 202 * where the trees are being synthesized by a tool. 203 */ 204 @Override @DefinedBy(Api.COMPILER_TREE) 205 public DCDocComment newDocCommentTree(List<? extends DocTree> firstSentence, List<? extends DocTree> body, List<? extends DocTree> tags) { 206 ListBuffer<DCTree> lb = new ListBuffer<>(); 207 lb.addAll(cast(firstSentence)); 208 lb.addAll(cast(body)); 209 List<DCTree> fullBody = lb.toList(); 210 211 // A dummy comment to keep the diagnostics logic happy. 212 Comment c = new Comment() { 213 @Override 214 public String getText() { 215 return null; 216 } 217 218 @Override 219 public int getSourcePos(int index) { 220 return Position.NOPOS; 221 } 222 223 @Override 224 public CommentStyle getStyle() { 225 return CommentStyle.JAVADOC; 226 } 227 228 @Override 229 public boolean isDeprecated() { 230 return false; 231 } 232 }; 233 234 DCDocComment tree = new DCDocComment(c, fullBody, cast(firstSentence), cast(body), cast(tags)); 235 return tree; 236 } 237 238 @Override @DefinedBy(Api.COMPILER_TREE) 239 public DCDocRoot newDocRootTree() { 240 DCDocRoot tree = new DCDocRoot(); 241 tree.pos = pos; 242 return tree; 243 } 244 245 @Override @DefinedBy(Api.COMPILER_TREE) 246 public DCEndElement newEndElementTree(Name name) { 247 DCEndElement tree = new DCEndElement(name); 248 tree.pos = pos; 249 return tree; 250 } 251 252 @Override @DefinedBy(Api.COMPILER_TREE) 253 public DCEntity newEntityTree(Name name) { 254 DCEntity tree = new DCEntity(name); 255 tree.pos = pos; 256 return tree; 257 } 258 259 @Override @DefinedBy(Api.COMPILER_TREE) 260 public DCErroneous newErroneousTree(String text, Diagnostic<JavaFileObject> diag) { 261 DCErroneous tree = new DCErroneous(text, (JCDiagnostic) diag); 262 tree.pos = pos; 263 return tree; 264 } 265 266 public DCErroneous newErroneousTree(String text, DiagnosticSource diagSource, String code, Object... args) { 267 DCErroneous tree = new DCErroneous(text, diags, diagSource, code, args); 268 tree.pos = pos; 269 return tree; 270 } 271 272 @Override @DefinedBy(Api.COMPILER_TREE) 273 public DCThrows newExceptionTree(ReferenceTree name, List<? extends DocTree> description) { 274 // TODO: verify the reference is just to a type (not a field or method) 275 DCThrows tree = new DCThrows(Kind.EXCEPTION, (DCReference) name, cast(description)); 276 tree.pos = pos; 277 return tree; 278 } 279 280 @Override @DefinedBy(Api.COMPILER_TREE) 281 public DCIdentifier newIdentifierTree(Name name) { 282 DCIdentifier tree = new DCIdentifier(name); 283 tree.pos = pos; 284 return tree; 285 } 286 287 @Override @DefinedBy(Api.COMPILER_TREE) 288 public DCIndex newIndexTree(DocTree term, List<? extends DocTree> description) { 289 DCIndex tree = new DCIndex((DCTree) term, cast(description)); 290 tree.pos = pos; 291 return tree; 292 } 293 294 @Override @DefinedBy(Api.COMPILER_TREE) 295 public DCInheritDoc newInheritDocTree() { 296 DCInheritDoc tree = new DCInheritDoc(); 297 tree.pos = pos; 298 return tree; 299 } 300 301 @Override @DefinedBy(Api.COMPILER_TREE) 302 public DCLink newLinkTree(ReferenceTree ref, List<? extends DocTree> label) { 303 DCLink tree = new DCLink(Kind.LINK, (DCReference) ref, cast(label)); 304 tree.pos = pos; 305 return tree; 306 } 307 308 @Override @DefinedBy(Api.COMPILER_TREE) 309 public DCLink newLinkPlainTree(ReferenceTree ref, List<? extends DocTree> label) { 310 DCLink tree = new DCLink(Kind.LINK_PLAIN, (DCReference) ref, cast(label)); 311 tree.pos = pos; 312 return tree; 313 } 314 315 @Override @DefinedBy(Api.COMPILER_TREE) 316 public DCLiteral newLiteralTree(TextTree text) { 317 DCLiteral tree = new DCLiteral(Kind.LITERAL, (DCText) text); 318 tree.pos = pos; 319 return tree; 320 } 321 322 @Override @DefinedBy(Api.COMPILER_TREE) 323 public DCParam newParamTree(boolean isTypeParameter, IdentifierTree name, List<? extends DocTree> description) { 324 DCParam tree = new DCParam(isTypeParameter, (DCIdentifier) name, cast(description)); 325 tree.pos = pos; 326 return tree; 327 } 328 329 @Override @DefinedBy(Api.COMPILER_TREE) 330 public DCReference newReferenceTree(String signature) { 331 try { 332 ReferenceParser.Reference ref = referenceParser.parse(signature); 333 DCReference tree = new DCReference(signature, ref.qualExpr, ref.member, ref.paramTypes); 334 tree.pos = pos; 335 return tree; 336 } catch (ReferenceParser.ParseException e) { 337 throw new IllegalArgumentException("invalid signature", e); 338 } 339 } 340 341 public DCReference newReferenceTree(String signature, JCTree qualExpr, Name member, List<JCTree> paramTypes) { 342 DCReference tree = new DCReference(signature, qualExpr, member, paramTypes); 343 tree.pos = pos; 344 return tree; 345 } 346 347 @Override @DefinedBy(Api.COMPILER_TREE) 348 public DCReturn newReturnTree(List<? extends DocTree> description) { 349 DCReturn tree = new DCReturn(cast(description)); 350 tree.pos = pos; 351 return tree; 352 } 353 354 @Override @DefinedBy(Api.COMPILER_TREE) 355 public DCSee newSeeTree(List<? extends DocTree> reference) { 356 DCSee tree = new DCSee(cast(reference)); 357 tree.pos = pos; 358 return tree; 359 } 360 361 @Override @DefinedBy(Api.COMPILER_TREE) 362 public DCSerial newSerialTree(List<? extends DocTree> description) { 363 DCSerial tree = new DCSerial(cast(description)); 364 tree.pos = pos; 365 return tree; 366 } 367 368 @Override @DefinedBy(Api.COMPILER_TREE) 369 public DCSerialData newSerialDataTree(List<? extends DocTree> description) { 370 DCSerialData tree = new DCSerialData(cast(description)); 371 tree.pos = pos; 372 return tree; 373 } 374 375 @Override @DefinedBy(Api.COMPILER_TREE) 376 public DCSerialField newSerialFieldTree(IdentifierTree name, ReferenceTree type, List<? extends DocTree> description) { 377 DCSerialField tree = new DCSerialField((DCIdentifier) name, (DCReference) type, cast(description)); 378 tree.pos = pos; 379 return tree; 380 } 381 382 @Override @DefinedBy(Api.COMPILER_TREE) 383 public DCSince newSinceTree(List<? extends DocTree> text) { 384 DCSince tree = new DCSince(cast(text)); 385 tree.pos = pos; 386 return tree; 387 } 388 389 @Override @DefinedBy(Api.COMPILER_TREE) 390 public DCStartElement newStartElementTree(Name name, List<? extends DocTree> attrs, boolean selfClosing) { 391 DCStartElement tree = new DCStartElement(name, cast(attrs), selfClosing); 392 tree.pos = pos; 393 return tree; 394 } 395 396 @Override @DefinedBy(Api.COMPILER_TREE) 397 public DCText newTextTree(String text) { 398 DCText tree = new DCText(text); 399 tree.pos = pos; 400 return tree; 401 } 402 403 @Override @DefinedBy(Api.COMPILER_TREE) 404 public DCThrows newThrowsTree(ReferenceTree name, List<? extends DocTree> description) { 405 // TODO: verify the reference is just to a type (not a field or method) 406 DCThrows tree = new DCThrows(Kind.THROWS, (DCReference) name, cast(description)); 407 tree.pos = pos; 408 return tree; 409 } 410 411 @Override @DefinedBy(Api.COMPILER_TREE) 412 public DCUnknownBlockTag newUnknownBlockTagTree(Name name, List<? extends DocTree> content) { 413 DCUnknownBlockTag tree = new DCUnknownBlockTag(name, cast(content)); 414 tree.pos = pos; 415 return tree; 416 } 417 418 @Override @DefinedBy(Api.COMPILER_TREE) 419 public DCUnknownInlineTag newUnknownInlineTagTree(Name name, List<? extends DocTree> content) { 420 DCUnknownInlineTag tree = new DCUnknownInlineTag(name, cast(content)); 421 tree.pos = pos; 422 return tree; 423 } 424 425 @Override @DefinedBy(Api.COMPILER_TREE) 426 public DCValue newValueTree(ReferenceTree ref) { 427 // TODO: verify the reference is to a constant value 428 DCValue tree = new DCValue((DCReference) ref); 429 tree.pos = pos; 430 return tree; 431 } 432 433 @Override @DefinedBy(Api.COMPILER_TREE) 434 public DCVersion newVersionTree(List<? extends DocTree> text) { 435 DCVersion tree = new DCVersion(cast(text)); 436 tree.pos = pos; 437 return tree; 438 } 439 440 @Override @DefinedBy(Api.COMPILER_TREE) 441 public java.util.List<DocTree> getFirstSentence(java.util.List<? extends DocTree> list) { 442 Pair<List<DCTree>, List<DCTree>> pair = splitBody(list); 443 return new ArrayList<>(pair.fst); 444 } 445 446 /* 447 * Breaks up the body tags into the first sentence and its successors. 448 * The first sentence is determined with the presence of a period, 449 * block tag, or a sentence break, as returned by the BreakIterator. 450 * Trailing whitespaces are trimmed. 451 */ 452 private Pair<List<DCTree>, List<DCTree>> splitBody(Collection<? extends DocTree> list) { 453 // pos is modified as we create trees, therefore 454 // we save the pos and restore it later. 455 final int savedpos = this.pos; 456 try { 457 ListBuffer<DCTree> body = new ListBuffer<>(); 458 // split body into first sentence and body 459 ListBuffer<DCTree> fs = new ListBuffer<>(); 460 if (list.isEmpty()) { 461 return new Pair<>(fs.toList(), body.toList()); 462 } 463 boolean foundFirstSentence = false; 464 ArrayList<DocTree> alist = new ArrayList<>(list); 465 ListIterator<DocTree> itr = alist.listIterator(); 466 while (itr.hasNext()) { 467 boolean isFirst = !itr.hasPrevious(); 468 DocTree dt = itr.next(); 469 int spos = ((DCTree) dt).pos; 470 if (foundFirstSentence) { 471 body.add((DCTree) dt); 472 continue; 473 } 474 switch (dt.getKind()) { 475 case TEXT: 476 DCText tt = (DCText) dt; 477 String s = tt.getBody(); 478 DocTree peekedNext = itr.hasNext() 479 ? alist.get(itr.nextIndex()) 480 : null; 481 int sbreak = getSentenceBreak(s, peekedNext); 482 if (sbreak > 0) { 483 s = removeTrailingWhitespace(s.substring(0, sbreak)); 484 DCText text = this.at(spos).newTextTree(s); 485 fs.add(text); 486 foundFirstSentence = true; 487 int nwPos = skipWhiteSpace(tt.getBody(), sbreak); 488 if (nwPos > 0) { 489 DCText text2 = this.at(spos + nwPos).newTextTree(tt.getBody().substring(nwPos)); 490 body.add(text2); 491 } 492 continue; 493 } else if (itr.hasNext()) { 494 // if the next doctree is a break, remove trailing spaces 495 peekedNext = alist.get(itr.nextIndex()); 496 boolean sbrk = isSentenceBreak(peekedNext, false); 497 if (sbrk) { 498 DocTree next = itr.next(); 499 s = removeTrailingWhitespace(s); 500 DCText text = this.at(spos).newTextTree(s); 501 fs.add(text); 502 body.add((DCTree) next); 503 foundFirstSentence = true; 504 continue; 505 } 506 } 507 break; 508 default: 509 if (isSentenceBreak(dt, isFirst)) { 510 body.add((DCTree) dt); 511 foundFirstSentence = true; 512 continue; 513 } 514 break; 515 } 516 fs.add((DCTree) dt); 517 } 518 return new Pair<>(fs.toList(), body.toList()); 519 } finally { 520 this.pos = savedpos; 521 } 522 } 523 524 private boolean isTextTree(DocTree tree) { 525 return tree.getKind() == Kind.TEXT; 526 } 527 528 /* 529 * Computes the first sentence break, a simple dot-space algorithm. 530 */ 531 private int defaultSentenceBreak(String s) { 532 // scan for period followed by whitespace 533 int period = -1; 534 for (int i = 0; i < s.length(); i++) { 535 switch (s.charAt(i)) { 536 case '.': 537 period = i; 538 break; 539 540 case ' ': 541 case '\f': 542 case '\n': 543 case '\r': 544 case '\t': 545 if (period >= 0) { 546 return i; 547 } 548 break; 549 550 default: 551 period = -1; 552 break; 553 } 554 } 555 return -1; 556 } 557 558 /* 559 * Computes the first sentence, if using a default breaker, 560 * the break is returned, if not then a -1, indicating that 561 * more doctree elements are required to be examined. 562 * 563 * BreakIterator.next points to the the start of the following sentence, 564 * and does not provide an easy way to disambiguate between "sentence break", 565 * "possible sentence break" and "not a sentence break" at the end of the input. 566 * For example, BreakIterator.next returns the index for the end 567 * of the string for all of these examples, 568 * using vertical bars to delimit the bounds of the example text 569 * |Abc| (not a valid end of sentence break, if followed by more text) 570 * |Abc.| (maybe a valid end of sentence break, depending on the following text) 571 * |Abc. | (maybe a valid end of sentence break, depending on the following text) 572 * |"Abc." | (maybe a valid end of sentence break, depending on the following text) 573 * |Abc. | (definitely a valid end of sentence break) 574 * |"Abc." | (definitely a valid end of sentence break) 575 * Therefore, we have to probe further to determine whether 576 * there really is a sentence break or not at the end of this run of text. 577 */ 578 private int getSentenceBreak(String s, DocTree dt) { 579 BreakIterator breakIterator = trees.getBreakIterator(); 580 if (breakIterator == null) { 581 return defaultSentenceBreak(s); 582 } 583 breakIterator.setText(s); 584 final int sbrk = breakIterator.next(); 585 // This is the last doctree, found the droid we are looking for 586 if (dt == null) { 587 return sbrk; 588 } 589 590 // If the break is well within the span of the string ie. not 591 // at EOL, then we have a clear break. 592 if (sbrk < s.length() - 1) { 593 return sbrk; 594 } 595 596 if (isTextTree(dt)) { 597 // Two adjacent text trees, a corner case, perhaps 598 // produced by a tool synthesizing a doctree. In 599 // this case, does the break lie within the first span, 600 // then we have the droid, otherwise allow the callers 601 // logic to handle the break in the adjacent doctree. 602 TextTree ttnext = (TextTree) dt; 603 String combined = s + ttnext.getBody(); 604 breakIterator.setText(combined); 605 int sbrk2 = breakIterator.next(); 606 if (sbrk < sbrk2) { 607 return sbrk; 608 } 609 } 610 611 // Is the adjacent tree a sentence breaker ? 612 if (isSentenceBreak(dt, false)) { 613 return sbrk; 614 } 615 616 // At this point the adjacent tree is either a javadoc tag ({@..), 617 // html tag (<..) or an entity (&..). Perform a litmus test, by 618 // concatenating a sentence, to validate the break earlier identified. 619 String combined = s + "Dummy Sentence."; 620 breakIterator.setText(combined); 621 int sbrk2 = breakIterator.next(); 622 if (sbrk2 <= sbrk) { 623 return sbrk2; 624 } 625 return -1; // indeterminate at this time 626 } 627 628 private boolean isSentenceBreak(javax.lang.model.element.Name tagName) { 629 return sentenceBreakTags.contains(get(tagName)); 630 } 631 632 private boolean isSentenceBreak(DocTree dt, boolean isFirstDocTree) { 633 switch (dt.getKind()) { 634 case START_ELEMENT: 635 StartElementTree set = (StartElementTree)dt; 636 return !isFirstDocTree && ((DCTree) dt).pos > 1 && isSentenceBreak(set.getName()); 637 case END_ELEMENT: 638 EndElementTree eet = (EndElementTree)dt; 639 return !isFirstDocTree && ((DCTree) dt).pos > 1 && isSentenceBreak(eet.getName()); 640 default: 641 return false; 642 } 643 } 644 645 /* 646 * Returns the position of the the first non-white space 647 */ 648 private int skipWhiteSpace(String s, int start) { 649 for (int i = start; i < s.length(); i++) { 650 char c = s.charAt(i); 651 if (!Character.isWhitespace(c)) { 652 return i; 653 } 654 } 655 return -1; 656 } 657 658 private String removeTrailingWhitespace(String s) { 659 for (int i = s.length() - 1 ; i >= 0 ; i--) { 660 char ch = s.charAt(i); 661 if (!Character.isWhitespace(ch)) { 662 return s.substring(0, i + 1); 663 } 664 } 665 return s; 666 } 667 668 @SuppressWarnings("unchecked") 669 private List<DCTree> cast(List<? extends DocTree> list) { 670 return (List<DCTree>) list; 671 } 672} 673