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