DocPretty.java revision 3337:cba09a2e6ae9
1/* 2 * Copyright (c) 1999, 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.io.IOException; 29import java.io.Writer; 30import java.util.List; 31 32import com.sun.source.doctree.*; 33import com.sun.source.doctree.AttributeTree.ValueKind; 34import com.sun.tools.javac.util.Convert; 35import com.sun.tools.javac.util.DefinedBy; 36import com.sun.tools.javac.util.DefinedBy.Api; 37 38/** 39 * Prints out a doc comment tree. 40 * 41 * <p><b>This is NOT part of any supported API. 42 * If you write code that depends on this, you do so at your own risk. 43 * This code and its internal interfaces are subject to change or 44 * deletion without notice.</b> 45 */ 46public class DocPretty implements DocTreeVisitor<Void,Void> { 47 48 /** 49 * The output stream on which trees are printed. 50 */ 51 final Writer out; 52 53 /** 54 * The left margin. 55 */ 56 int lmargin = 0; 57 58 public DocPretty(Writer out) { 59 this.out = out; 60 } 61 62 /** Visitor method: print expression tree. 63 */ 64 public void print(DocTree tree) throws IOException { 65 try { 66 if (tree == null) 67 print("/*missing*/"); 68 else { 69 tree.accept(this, null); 70 } 71 } catch (UncheckedIOException ex) { 72 throw new IOException(ex.getMessage(), ex); 73 } 74 } 75 76 /** 77 * Print string, replacing all non-ascii character with unicode escapes. 78 */ 79 protected void print(Object s) throws IOException { 80 out.write(Convert.escapeUnicode(s.toString())); 81 } 82 83 /** 84 * Print list. 85 */ 86 public void print(List<? extends DocTree> list) throws IOException { 87 for (DocTree t: list) { 88 print(t); 89 } 90 } 91 92 /** 93 * Print list., with separators 94 */ 95 protected void print(List<? extends DocTree> list, String sep) throws IOException { 96 if (list.isEmpty()) 97 return; 98 boolean first = true; 99 for (DocTree t: list) { 100 if (!first) 101 print(sep); 102 print(t); 103 first = false; 104 } 105 } 106 107 /** Print new line. 108 */ 109 protected void println() throws IOException { 110 out.write(lineSep); 111 } 112 113 protected void printTagName(DocTree node) throws IOException { 114 out.write("@"); 115 out.write(node.getKind().tagName); 116 } 117 118 final String lineSep = System.getProperty("line.separator"); 119 120 /************************************************************************** 121 * Traversal methods 122 *************************************************************************/ 123 124 /** Exception to propagate IOException through visitXXX methods */ 125 private static class UncheckedIOException extends Error { 126 static final long serialVersionUID = -4032692679158424751L; 127 UncheckedIOException(IOException e) { 128 super(e.getMessage(), e); 129 } 130 } 131 132 133 @DefinedBy(Api.COMPILER_TREE) 134 public Void visitAttribute(AttributeTree node, Void p) { 135 try { 136 print(node.getName()); 137 String quote; 138 switch (node.getValueKind()) { 139 case EMPTY: 140 quote = null; 141 break; 142 case UNQUOTED: 143 quote = ""; 144 break; 145 case SINGLE: 146 quote = "'"; 147 break; 148 case DOUBLE: 149 quote = "\""; 150 break; 151 default: 152 throw new AssertionError(); 153 } 154 if (quote != null) { 155 print("=" + quote); 156 print(node.getValue()); 157 print(quote); 158 } 159 } catch (IOException e) { 160 throw new UncheckedIOException(e); 161 } 162 return null; 163 } 164 165 @DefinedBy(Api.COMPILER_TREE) 166 public Void visitAuthor(AuthorTree node, Void p) { 167 try { 168 printTagName(node); 169 print(" "); 170 print(node.getName()); 171 } catch (IOException e) { 172 throw new UncheckedIOException(e); 173 } 174 return null; 175 } 176 177 @DefinedBy(Api.COMPILER_TREE) 178 public Void visitComment(CommentTree node, Void p) { 179 try { 180 print(node.getBody()); 181 } catch (IOException e) { 182 throw new UncheckedIOException(e); 183 } 184 return null; 185 } 186 187 @DefinedBy(Api.COMPILER_TREE) 188 public Void visitDeprecated(DeprecatedTree node, Void p) { 189 try { 190 printTagName(node); 191 if (!node.getBody().isEmpty()) { 192 print(" "); 193 print(node.getBody()); 194 } 195 } catch (IOException e) { 196 throw new UncheckedIOException(e); 197 } 198 return null; 199 } 200 201 @DefinedBy(Api.COMPILER_TREE) 202 public Void visitDocComment(DocCommentTree node, Void p) { 203 try { 204 List<? extends DocTree> b = node.getFullBody(); 205 List<? extends DocTree> t = node.getBlockTags(); 206 print(b); 207 if (!b.isEmpty() && !t.isEmpty()) 208 print("\n"); 209 print(t, "\n"); 210 } catch (IOException e) { 211 throw new UncheckedIOException(e); 212 } 213 return null; 214 } 215 216 @DefinedBy(Api.COMPILER_TREE) 217 public Void visitDocRoot(DocRootTree node, Void p) { 218 try { 219 print("{"); 220 printTagName(node); 221 print("}"); 222 } catch (IOException e) { 223 throw new UncheckedIOException(e); 224 } 225 return null; 226 } 227 228 @DefinedBy(Api.COMPILER_TREE) 229 public Void visitEndElement(EndElementTree node, Void p) { 230 try { 231 print("</"); 232 print(node.getName()); 233 print(">"); 234 } catch (IOException e) { 235 throw new UncheckedIOException(e); 236 } 237 return null; 238 } 239 240 @DefinedBy(Api.COMPILER_TREE) 241 public Void visitEntity(EntityTree node, Void p) { 242 try { 243 print("&"); 244 print(node.getName()); 245 print(";"); 246 } catch (IOException e) { 247 throw new UncheckedIOException(e); 248 } 249 return null; 250 } 251 252 @DefinedBy(Api.COMPILER_TREE) 253 public Void visitErroneous(ErroneousTree node, Void p) { 254 try { 255 print(node.getBody()); 256 } catch (IOException e) { 257 throw new UncheckedIOException(e); 258 } 259 return null; 260 } 261 262 @DefinedBy(Api.COMPILER_TREE) 263 public Void visitHidden(HiddenTree node, Void p) { 264 try { 265 printTagName(node); 266 if (!node.getBody().isEmpty()) { 267 print(" "); 268 print(node.getBody()); 269 } 270 } catch (IOException e) { 271 throw new UncheckedIOException(e); 272 } 273 return null; 274 } 275 276 @DefinedBy(Api.COMPILER_TREE) 277 public Void visitIdentifier(IdentifierTree node, Void p) { 278 try { 279 print(node.getName()); 280 } catch (IOException e) { 281 throw new UncheckedIOException(e); 282 } 283 return null; 284 } 285 286 @DefinedBy(Api.COMPILER_TREE) 287 public Void visitIndex(IndexTree node, Void p) { 288 try { 289 print("{"); 290 printTagName(node); 291 print(" "); 292 print(node.getSearchTerm()); 293 if (!node.getDescription().isEmpty()) { 294 print(" "); 295 print(node.getDescription()); 296 } 297 print("}"); 298 } catch (IOException e) { 299 throw new UncheckedIOException(e); 300 } 301 return null; 302 } 303 304 @DefinedBy(Api.COMPILER_TREE) 305 public Void visitInheritDoc(InheritDocTree node, Void p) { 306 try { 307 print("{"); 308 printTagName(node); 309 print("}"); 310 } catch (IOException e) { 311 throw new UncheckedIOException(e); 312 } 313 return null; 314 } 315 316 @DefinedBy(Api.COMPILER_TREE) 317 public Void visitLink(LinkTree node, Void p) { 318 try { 319 print("{"); 320 printTagName(node); 321 print(" "); 322 print(node.getReference()); 323 if (!node.getLabel().isEmpty()) { 324 print(" "); 325 print(node.getLabel()); 326 } 327 print("}"); 328 } catch (IOException e) { 329 throw new UncheckedIOException(e); 330 } 331 return null; 332 } 333 334 @DefinedBy(Api.COMPILER_TREE) 335 public Void visitLiteral(LiteralTree node, Void p) { 336 try { 337 print("{"); 338 printTagName(node); 339 String body = node.getBody().getBody(); 340 if (!body.isEmpty() && !Character.isWhitespace(body.charAt(0))) { 341 print(" "); 342 } 343 print(node.getBody()); 344 print("}"); 345 } catch (IOException e) { 346 throw new UncheckedIOException(e); 347 } 348 return null; 349 } 350 351 @DefinedBy(Api.COMPILER_TREE) 352 public Void visitParam(ParamTree node, Void p) { 353 try { 354 printTagName(node); 355 print(" "); 356 if (node.isTypeParameter()) print("<"); 357 print(node.getName()); 358 if (node.isTypeParameter()) print(">"); 359 if (!node.getDescription().isEmpty()) { 360 print(" "); 361 print(node.getDescription()); 362 } 363 } catch (IOException e) { 364 throw new UncheckedIOException(e); 365 } 366 return null; 367 } 368 369 @DefinedBy(Api.COMPILER_TREE) 370 public Void visitReference(ReferenceTree node, Void p) { 371 try { 372 print(node.getSignature()); 373 } catch (IOException e) { 374 throw new UncheckedIOException(e); 375 } 376 return null; 377 } 378 379 @DefinedBy(Api.COMPILER_TREE) 380 public Void visitReturn(ReturnTree node, Void p) { 381 try { 382 printTagName(node); 383 print(" "); 384 print(node.getDescription()); 385 } catch (IOException e) { 386 throw new UncheckedIOException(e); 387 } 388 return null; 389 } 390 391 @DefinedBy(Api.COMPILER_TREE) 392 public Void visitSee(SeeTree node, Void p) { 393 try { 394 printTagName(node); 395 boolean first = true; 396 boolean needSep = true; 397 for (DocTree t: node.getReference()) { 398 if (needSep) print(" "); 399 needSep = (first && (t instanceof ReferenceTree)); 400 first = false; 401 print(t); 402 } 403 } catch (IOException e) { 404 throw new UncheckedIOException(e); 405 } 406 return null; 407 } 408 409 @DefinedBy(Api.COMPILER_TREE) 410 public Void visitSerial(SerialTree node, Void p) { 411 try { 412 printTagName(node); 413 if (!node.getDescription().isEmpty()) { 414 print(" "); 415 print(node.getDescription()); 416 } 417 } catch (IOException e) { 418 throw new UncheckedIOException(e); 419 } 420 return null; 421 } 422 423 @DefinedBy(Api.COMPILER_TREE) 424 public Void visitSerialData(SerialDataTree node, Void p) { 425 try { 426 printTagName(node); 427 if (!node.getDescription().isEmpty()) { 428 print(" "); 429 print(node.getDescription()); 430 } 431 } catch (IOException e) { 432 throw new UncheckedIOException(e); 433 } 434 return null; 435 } 436 437 @DefinedBy(Api.COMPILER_TREE) 438 public Void visitSerialField(SerialFieldTree node, Void p) { 439 try { 440 printTagName(node); 441 print(" "); 442 print(node.getName()); 443 print(" "); 444 print(node.getType()); 445 if (!node.getDescription().isEmpty()) { 446 print(" "); 447 print(node.getDescription()); 448 } 449 } catch (IOException e) { 450 throw new UncheckedIOException(e); 451 } 452 return null; 453 } 454 455 @DefinedBy(Api.COMPILER_TREE) 456 public Void visitSince(SinceTree node, Void p) { 457 try { 458 printTagName(node); 459 print(" "); 460 print(node.getBody()); 461 } catch (IOException e) { 462 throw new UncheckedIOException(e); 463 } 464 return null; 465 } 466 467 @DefinedBy(Api.COMPILER_TREE) 468 public Void visitStartElement(StartElementTree node, Void p) { 469 try { 470 print("<"); 471 print(node.getName()); 472 List<? extends DocTree> attrs = node.getAttributes(); 473 if (!attrs.isEmpty()) { 474 print(" "); 475 print(attrs); 476 DocTree last = node.getAttributes().get(attrs.size() - 1); 477 if (node.isSelfClosing() && last instanceof AttributeTree 478 && ((AttributeTree) last).getValueKind() == ValueKind.UNQUOTED) 479 print(" "); 480 } 481 if (node.isSelfClosing()) 482 print("/"); 483 print(">"); 484 } catch (IOException e) { 485 throw new UncheckedIOException(e); 486 } 487 return null; 488 } 489 490 @DefinedBy(Api.COMPILER_TREE) 491 public Void visitText(TextTree node, Void p) { 492 try { 493 print(node.getBody()); 494 } catch (IOException e) { 495 throw new UncheckedIOException(e); 496 } 497 return null; 498 } 499 500 @DefinedBy(Api.COMPILER_TREE) 501 public Void visitThrows(ThrowsTree node, Void p) { 502 try { 503 printTagName(node); 504 print(" "); 505 print(node.getExceptionName()); 506 if (!node.getDescription().isEmpty()) { 507 print(" "); 508 print(node.getDescription()); 509 } 510 } catch (IOException e) { 511 throw new UncheckedIOException(e); 512 } 513 return null; 514 } 515 516 @DefinedBy(Api.COMPILER_TREE) 517 public Void visitUnknownBlockTag(UnknownBlockTagTree node, Void p) { 518 try { 519 print("@"); 520 print(node.getTagName()); 521 print(" "); 522 print(node.getContent()); 523 } catch (IOException e) { 524 throw new UncheckedIOException(e); 525 } 526 return null; 527 } 528 529 @DefinedBy(Api.COMPILER_TREE) 530 public Void visitUnknownInlineTag(UnknownInlineTagTree node, Void p) { 531 try { 532 print("{"); 533 print("@"); 534 print(node.getTagName()); 535 print(" "); 536 print(node.getContent()); 537 print("}"); 538 } catch (IOException e) { 539 throw new UncheckedIOException(e); 540 } 541 return null; 542 } 543 544 @DefinedBy(Api.COMPILER_TREE) 545 public Void visitValue(ValueTree node, Void p) { 546 try { 547 print("{"); 548 printTagName(node); 549 if (node.getReference() != null) { 550 print(" "); 551 print(node.getReference()); 552 } 553 print("}"); 554 } catch (IOException e) { 555 throw new UncheckedIOException(e); 556 } 557 return null; 558 } 559 560 @DefinedBy(Api.COMPILER_TREE) 561 public Void visitVersion(VersionTree node, Void p) { 562 try { 563 printTagName(node); 564 print(" "); 565 print(node.getBody()); 566 } catch (IOException e) { 567 throw new UncheckedIOException(e); 568 } 569 return null; 570 } 571 572 @DefinedBy(Api.COMPILER_TREE) 573 public Void visitOther(DocTree node, Void p) { 574 try { 575 print("(UNKNOWN: " + node + ")"); 576 println(); 577 } catch (IOException e) { 578 throw new UncheckedIOException(e); 579 } 580 return null; 581 } 582} 583