DocPretty.java revision 3162:f164d4c2d33e
1/* 2 * Copyright (c) 1999, 2015, 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 visitIdentifier(IdentifierTree node, Void p) { 264 try { 265 print(node.getName()); 266 } catch (IOException e) { 267 throw new UncheckedIOException(e); 268 } 269 return null; 270 } 271 272 @DefinedBy(Api.COMPILER_TREE) 273 public Void visitIndex(IndexTree node, Void p) { 274 try { 275 print("{"); 276 printTagName(node); 277 print(" "); 278 print(node.getSearchTerm()); 279 if (!node.getDescription().isEmpty()) { 280 print(" "); 281 print(node.getDescription()); 282 } 283 print("}"); 284 } catch (IOException e) { 285 throw new UncheckedIOException(e); 286 } 287 return null; 288 } 289 290 @DefinedBy(Api.COMPILER_TREE) 291 public Void visitInheritDoc(InheritDocTree node, Void p) { 292 try { 293 print("{"); 294 printTagName(node); 295 print("}"); 296 } catch (IOException e) { 297 throw new UncheckedIOException(e); 298 } 299 return null; 300 } 301 302 @DefinedBy(Api.COMPILER_TREE) 303 public Void visitLink(LinkTree node, Void p) { 304 try { 305 print("{"); 306 printTagName(node); 307 print(" "); 308 print(node.getReference()); 309 if (!node.getLabel().isEmpty()) { 310 print(" "); 311 print(node.getLabel()); 312 } 313 print("}"); 314 } catch (IOException e) { 315 throw new UncheckedIOException(e); 316 } 317 return null; 318 } 319 320 @DefinedBy(Api.COMPILER_TREE) 321 public Void visitLiteral(LiteralTree node, Void p) { 322 try { 323 print("{"); 324 printTagName(node); 325 String body = node.getBody().getBody(); 326 if (!body.isEmpty() && !Character.isWhitespace(body.charAt(0))) { 327 print(" "); 328 } 329 print(node.getBody()); 330 print("}"); 331 } catch (IOException e) { 332 throw new UncheckedIOException(e); 333 } 334 return null; 335 } 336 337 @DefinedBy(Api.COMPILER_TREE) 338 public Void visitParam(ParamTree node, Void p) { 339 try { 340 printTagName(node); 341 print(" "); 342 if (node.isTypeParameter()) print("<"); 343 print(node.getName()); 344 if (node.isTypeParameter()) print(">"); 345 if (!node.getDescription().isEmpty()) { 346 print(" "); 347 print(node.getDescription()); 348 } 349 } catch (IOException e) { 350 throw new UncheckedIOException(e); 351 } 352 return null; 353 } 354 355 @DefinedBy(Api.COMPILER_TREE) 356 public Void visitReference(ReferenceTree node, Void p) { 357 try { 358 print(node.getSignature()); 359 } catch (IOException e) { 360 throw new UncheckedIOException(e); 361 } 362 return null; 363 } 364 365 @DefinedBy(Api.COMPILER_TREE) 366 public Void visitReturn(ReturnTree node, Void p) { 367 try { 368 printTagName(node); 369 print(" "); 370 print(node.getDescription()); 371 } catch (IOException e) { 372 throw new UncheckedIOException(e); 373 } 374 return null; 375 } 376 377 @DefinedBy(Api.COMPILER_TREE) 378 public Void visitSee(SeeTree node, Void p) { 379 try { 380 printTagName(node); 381 boolean first = true; 382 boolean needSep = true; 383 for (DocTree t: node.getReference()) { 384 if (needSep) print(" "); 385 needSep = (first && (t instanceof ReferenceTree)); 386 first = false; 387 print(t); 388 } 389 } catch (IOException e) { 390 throw new UncheckedIOException(e); 391 } 392 return null; 393 } 394 395 @DefinedBy(Api.COMPILER_TREE) 396 public Void visitSerial(SerialTree node, Void p) { 397 try { 398 printTagName(node); 399 if (!node.getDescription().isEmpty()) { 400 print(" "); 401 print(node.getDescription()); 402 } 403 } catch (IOException e) { 404 throw new UncheckedIOException(e); 405 } 406 return null; 407 } 408 409 @DefinedBy(Api.COMPILER_TREE) 410 public Void visitSerialData(SerialDataTree 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 visitSerialField(SerialFieldTree node, Void p) { 425 try { 426 printTagName(node); 427 print(" "); 428 print(node.getName()); 429 print(" "); 430 print(node.getType()); 431 if (!node.getDescription().isEmpty()) { 432 print(" "); 433 print(node.getDescription()); 434 } 435 } catch (IOException e) { 436 throw new UncheckedIOException(e); 437 } 438 return null; 439 } 440 441 @DefinedBy(Api.COMPILER_TREE) 442 public Void visitSince(SinceTree node, Void p) { 443 try { 444 printTagName(node); 445 print(" "); 446 print(node.getBody()); 447 } catch (IOException e) { 448 throw new UncheckedIOException(e); 449 } 450 return null; 451 } 452 453 @DefinedBy(Api.COMPILER_TREE) 454 public Void visitStartElement(StartElementTree node, Void p) { 455 try { 456 print("<"); 457 print(node.getName()); 458 List<? extends DocTree> attrs = node.getAttributes(); 459 if (!attrs.isEmpty()) { 460 print(" "); 461 print(attrs); 462 DocTree last = node.getAttributes().get(attrs.size() - 1); 463 if (node.isSelfClosing() && last instanceof AttributeTree 464 && ((AttributeTree) last).getValueKind() == ValueKind.UNQUOTED) 465 print(" "); 466 } 467 if (node.isSelfClosing()) 468 print("/"); 469 print(">"); 470 } catch (IOException e) { 471 throw new UncheckedIOException(e); 472 } 473 return null; 474 } 475 476 @DefinedBy(Api.COMPILER_TREE) 477 public Void visitText(TextTree node, Void p) { 478 try { 479 print(node.getBody()); 480 } catch (IOException e) { 481 throw new UncheckedIOException(e); 482 } 483 return null; 484 } 485 486 @DefinedBy(Api.COMPILER_TREE) 487 public Void visitThrows(ThrowsTree node, Void p) { 488 try { 489 printTagName(node); 490 print(" "); 491 print(node.getExceptionName()); 492 if (!node.getDescription().isEmpty()) { 493 print(" "); 494 print(node.getDescription()); 495 } 496 } catch (IOException e) { 497 throw new UncheckedIOException(e); 498 } 499 return null; 500 } 501 502 @DefinedBy(Api.COMPILER_TREE) 503 public Void visitUnknownBlockTag(UnknownBlockTagTree node, Void p) { 504 try { 505 print("@"); 506 print(node.getTagName()); 507 print(" "); 508 print(node.getContent()); 509 } catch (IOException e) { 510 throw new UncheckedIOException(e); 511 } 512 return null; 513 } 514 515 @DefinedBy(Api.COMPILER_TREE) 516 public Void visitUnknownInlineTag(UnknownInlineTagTree node, Void p) { 517 try { 518 print("{"); 519 print("@"); 520 print(node.getTagName()); 521 print(" "); 522 print(node.getContent()); 523 print("}"); 524 } catch (IOException e) { 525 throw new UncheckedIOException(e); 526 } 527 return null; 528 } 529 530 @DefinedBy(Api.COMPILER_TREE) 531 public Void visitValue(ValueTree node, Void p) { 532 try { 533 print("{"); 534 printTagName(node); 535 if (node.getReference() != null) { 536 print(" "); 537 print(node.getReference()); 538 } 539 print("}"); 540 } catch (IOException e) { 541 throw new UncheckedIOException(e); 542 } 543 return null; 544 } 545 546 @DefinedBy(Api.COMPILER_TREE) 547 public Void visitVersion(VersionTree node, Void p) { 548 try { 549 printTagName(node); 550 print(" "); 551 print(node.getBody()); 552 } catch (IOException e) { 553 throw new UncheckedIOException(e); 554 } 555 return null; 556 } 557 558 @DefinedBy(Api.COMPILER_TREE) 559 public Void visitOther(DocTree node, Void p) { 560 try { 561 print("(UNKNOWN: " + node + ")"); 562 println(); 563 } catch (IOException e) { 564 throw new UncheckedIOException(e); 565 } 566 return null; 567 } 568} 569