1 /* 2 * Copyright (c) 2011, 2019, 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 26 package com.sun.source.util; 27 28 import com.sun.source.doctree.*; 29 30 31 /** 32 * A TreeVisitor that visits all the child tree nodes. 33 * To visit nodes of a particular type, just override the 34 * corresponding visitXYZ method. 35 * Inside your method, call super.visitXYZ to visit descendant 36 * nodes. 37 * 38 * <p>The default implementation of the visitXYZ methods will determine 39 * a result as follows: 40 * <ul> 41 * <li>If the node being visited has no children, the result will be {@code null}. 42 * <li>If the node being visited has one child, the result will be the 43 * result of calling {@code scan} on that child. The child may be a simple node 44 * or itself a list of nodes. 45 * <li> If the node being visited has more than one child, the result will 46 * be determined by calling {@code scan} each child in turn, and then combining the 47 * result of each scan after the first with the cumulative result 48 * so far, as determined by the {@link #reduce} method. Each child may be either 49 * a simple node of a list of nodes. The default behavior of the {@code reduce} 50 * method is such that the result of the visitXYZ method will be the result of 51 * the last child scanned. 52 * </ul> 53 * 54 * <p>Here is an example to count the number of erroneous nodes in a tree: 55 * <pre> 56 * class CountErrors extends DocTreeScanner<Integer,Void> { 57 * {@literal @}Override 58 * public Integer visitErroneous(ErroneousTree node, Void p) { 59 * return 1; 60 * } 61 * {@literal @}Override 62 * public Integer reduce(Integer r1, Integer r2) { 63 * return (r1 == null ? 0 : r1) + (r2 == null ? 0 : r2); 64 * } 65 * } 66 * </pre> 67 * 68 * @since 1.8 69 */ 70 public class DocTreeScanner<R,P> implements DocTreeVisitor<R,P> { 71 /** 72 * Constructs a {@code DocTreeScanner}. 73 */ 74 public DocTreeScanner() {} 75 76 /** 77 * Scans a single node. 78 * @param node the node to be scanned 79 * @param p a parameter value passed to the visit method 80 * @return the result value from the visit method 81 */ 82 public R scan(DocTree node, P p) { 83 return (node == null) ? null : node.accept(this, p); 84 } 85 86 private R scanAndReduce(DocTree node, P p, R r) { 87 return reduce(scan(node, p), r); 88 } 89 90 /** 91 * Scans a sequence of nodes. 92 * @param nodes the nodes to be scanned 93 * @param p a parameter value to be passed to the visit method for each node 94 * @return the combined return value from the visit methods. 95 * The values are combined using the {@link #reduce reduce} method. 96 */ 97 public R scan(Iterable<? extends DocTree> nodes, P p) { 98 R r = null; 99 if (nodes != null) { 100 boolean first = true; 101 for (DocTree node : nodes) { 102 r = (first ? scan(node, p) : scanAndReduce(node, p, r)); 103 first = false; 104 } 105 } 106 return r; 107 } 108 109 private R scanAndReduce(Iterable<? extends DocTree> nodes, P p, R r) { 110 return reduce(scan(nodes, p), r); 111 } 112 113 /** 114 * Reduces two results into a combined result. 115 * The default implementation is to return the first parameter. 116 * The general contract of the method is that it may take any action whatsoever. 117 * @param r1 the first of the values to be combined 118 * @param r2 the second of the values to be combined 119 * @return the result of combining the two parameters 120 */ 121 public R reduce(R r1, R r2) { 122 return r1; 123 } 124 125 126 /* *************************************************************************** 127 * Visitor methods 128 ****************************************************************************/ 129 130 /** 131 * {@inheritDoc} This implementation scans the children in left to right order. 132 * 133 * @param node {@inheritDoc} 134 * @param p {@inheritDoc} 135 * @return the result of scanning 136 */ 137 @Override 138 public R visitAttribute(AttributeTree node, P p) { 139 return scan(node.getValue(), p); 140 } 141 142 /** 143 * {@inheritDoc} This implementation scans the children in left to right order. 144 * 145 * @param node {@inheritDoc} 146 * @param p {@inheritDoc} 147 * @return the result of scanning 148 */ 149 @Override 150 public R visitAuthor(AuthorTree node, P p) { 151 return scan(node.getName(), p); 152 } 153 154 /** 155 * {@inheritDoc} This implementation returns {@code null}. 156 * 157 * @param node {@inheritDoc} 158 * @param p {@inheritDoc} 159 * @return the result of scanning 160 */ 161 @Override 162 public R visitComment(CommentTree node, P p) { 163 return null; 164 } 165 166 /** 167 * {@inheritDoc} This implementation scans the children in left to right order. 168 * 169 * @param node {@inheritDoc} 170 * @param p {@inheritDoc} 171 * @return the result of scanning 172 */ 173 @Override 174 public R visitDeprecated(DeprecatedTree node, P p) { 175 return scan(node.getBody(), p); 176 } 177 178 /** 179 * {@inheritDoc} This implementation scans the children in left to right order. 180 * 181 * @param node {@inheritDoc} 182 * @param p {@inheritDoc} 183 * @return the result of scanning 184 */ 185 @Override 186 public R visitDocComment(DocCommentTree node, P p) { 187 R r = scan(node.getFirstSentence(), p); 188 r = scanAndReduce(node.getBody(), p, r); 189 r = scanAndReduce(node.getBlockTags(), p, r); 190 return r; 191 } 192 193 /** 194 * {@inheritDoc} This implementation returns {@code null}. 195 * 196 * @param node {@inheritDoc} 197 * @param p {@inheritDoc} 198 * @return the result of scanning 199 */ 200 @Override 201 public R visitDocRoot(DocRootTree node, P p) { 202 return null; 203 } 204 205 /** 206 * {@inheritDoc} This implementation returns {@code null}. 207 * 208 * @param node {@inheritDoc} 209 * @param p {@inheritDoc} 210 * @return the result of scanning 211 */ 212 @Override 213 public R visitDocType(DocTypeTree node, P p) { 214 return null; 215 } 216 217 /** 218 * {@inheritDoc} This implementation returns {@code null}. 219 * 220 * @param node {@inheritDoc} 221 * @param p {@inheritDoc} 222 * @return the result of scanning 223 */ 224 @Override 225 public R visitEndElement(EndElementTree node, P p) { 226 return null; 227 } 228 229 /** 230 * {@inheritDoc} This implementation returns {@code null}. 231 * 232 * @param node {@inheritDoc} 233 * @param p {@inheritDoc} 234 * @return the result of scanning 235 */ 236 @Override 237 public R visitEntity(EntityTree node, P p) { 238 return null; 239 } 240 241 /** 242 * {@inheritDoc} This implementation returns {@code null}. 243 * 244 * @param node {@inheritDoc} 245 * @param p {@inheritDoc} 246 * @return the result of scanning 247 */ 248 @Override 249 public R visitErroneous(ErroneousTree node, P p) { 250 return null; 251 } 252 253 /** 254 * {@inheritDoc} This implementation scans the children in left to right order. 255 * 256 * @param node {@inheritDoc} 257 * @param p {@inheritDoc} 258 * @return the result of scanning 259 */ 260 @Override 261 public R visitHidden(HiddenTree node, P p) { 262 return scan(node.getBody(), p); 263 } 264 265 /** 266 * {@inheritDoc} This implementation returns {@code null}. 267 * 268 * @param node {@inheritDoc} 269 * @param p {@inheritDoc} 270 * @return the result of scanning 271 */ 272 @Override 273 public R visitIdentifier(IdentifierTree node, P p) { 274 return null; 275 } 276 277 /** 278 * {@inheritDoc} This implementation returns {@code null}. 279 * 280 * @param node {@inheritDoc} 281 * @param p {@inheritDoc} 282 * @return the result of scanning 283 */ 284 @Override 285 public R visitIndex(IndexTree node, P p) { 286 R r = scan(node.getSearchTerm(), p); 287 r = scanAndReduce(node.getDescription(), p, r); 288 return r; 289 } 290 291 /** 292 * {@inheritDoc} This implementation returns {@code null}. 293 * 294 * @param node {@inheritDoc} 295 * @param p {@inheritDoc} 296 * @return the result of scanning 297 */ 298 @Override 299 public R visitInheritDoc(InheritDocTree node, P p) { 300 return null; 301 } 302 303 /** 304 * {@inheritDoc} This implementation scans the children in left to right order. 305 * 306 * @param node {@inheritDoc} 307 * @param p {@inheritDoc} 308 * @return the result of scanning 309 */ 310 @Override 311 public R visitLink(LinkTree node, P p) { 312 R r = scan(node.getReference(), p); 313 r = scanAndReduce(node.getLabel(), p, r); 314 return r; 315 } 316 317 /** 318 * {@inheritDoc} This implementation scans the children in left to right order. 319 * 320 * @param node {@inheritDoc} 321 * @param p {@inheritDoc} 322 * @return the result of scanning 323 */ 324 @Override 325 public R visitLiteral(LiteralTree node, P p) { 326 return scan(node.getBody(), p); 327 } 328 329 /** 330 * {@inheritDoc} This implementation scans the children in left to right order. 331 * 332 * @param node {@inheritDoc} 333 * @param p {@inheritDoc} 334 * @return the result of scanning 335 */ 336 @Override 337 public R visitParam(ParamTree node, P p) { 338 R r = scan(node.getName(), p); 339 r = scanAndReduce(node.getDescription(), p, r); 340 return r; 341 } 342 343 /** 344 * {@inheritDoc} This implementation scans the children in left to right order. 345 * 346 * @param node {@inheritDoc} 347 * @param p {@inheritDoc} 348 * @return the result of scanning 349 */ 350 @Override 351 public R visitProvides(ProvidesTree node, P p) { 352 R r = scan(node.getServiceType(), p); 353 r = scanAndReduce(node.getDescription(), p, r); 354 return r; 355 } 356 357 /** 358 * {@inheritDoc} This implementation returns {@code null}. 359 * 360 * @param node {@inheritDoc} 361 * @param p {@inheritDoc} 362 * @return the result of scanning 363 */ 364 @Override 365 public R visitReference(ReferenceTree node, P p) { 366 return null; 367 } 368 369 /** 370 * {@inheritDoc} This implementation scans the children in left to right order. 371 * 372 * @param node {@inheritDoc} 373 * @param p {@inheritDoc} 374 * @return the result of scanning 375 */ 376 @Override 377 public R visitReturn(ReturnTree node, P p) { 378 return scan(node.getDescription(), p); 379 } 380 381 /** 382 * {@inheritDoc} This implementation scans the children in left to right order. 383 * 384 * @param node {@inheritDoc} 385 * @param p {@inheritDoc} 386 * @return the result of scanning 387 */ 388 @Override 389 public R visitSee(SeeTree node, P p) { 390 return scan(node.getReference(), p); 391 } 392 393 /** 394 * {@inheritDoc} This implementation scans the children in left to right order. 395 * 396 * @param node {@inheritDoc} 397 * @param p {@inheritDoc} 398 * @return the result of scanning 399 */ 400 @Override 401 public R visitSerial(SerialTree node, P p) { 402 return scan(node.getDescription(), p); 403 } 404 405 /** 406 * {@inheritDoc} This implementation scans the children in left to right order. 407 * 408 * @param node {@inheritDoc} 409 * @param p {@inheritDoc} 410 * @return the result of scanning 411 */ 412 @Override 413 public R visitSerialData(SerialDataTree node, P p) { 414 return scan(node.getDescription(), p); 415 } 416 417 /** 418 * {@inheritDoc} This implementation scans the children in left to right order. 419 * 420 * @param node {@inheritDoc} 421 * @param p {@inheritDoc} 422 * @return the result of scanning 423 */ 424 @Override 425 public R visitSerialField(SerialFieldTree node, P p) { 426 R r = scan(node.getName(), p); 427 r = scanAndReduce(node.getType(), p, r); 428 r = scanAndReduce(node.getDescription(), p, r); 429 return r; 430 } 431 432 /** 433 * {@inheritDoc} This implementation scans the children in left to right order. 434 * 435 * @param node {@inheritDoc} 436 * @param p {@inheritDoc} 437 * @return the result of scanning 438 */ 439 @Override 440 public R visitSince(SinceTree node, P p) { 441 return scan(node.getBody(), p); 442 } 443 444 /** 445 * {@inheritDoc} This implementation scans the children in left to right order. 446 * 447 * @param node {@inheritDoc} 448 * @param p {@inheritDoc} 449 * @return the result of scanning 450 */ 451 @Override 452 public R visitStartElement(StartElementTree node, P p) { 453 return scan(node.getAttributes(), p); 454 } 455 456 /** 457 * {@inheritDoc} This implementation scans the children in left to right order. 458 * 459 * @param node {@inheritDoc} 460 * @param p {@inheritDoc} 461 * @return the result of scanning 462 * @since 10 463 */ 464 @Override 465 public R visitSummary(SummaryTree node, P p) { 466 R r = scan(node.getSummary(), p); 467 return r; 468 } 469 470 /** 471 * {@inheritDoc} This implementation returns {@code null}. 472 * 473 * @param node {@inheritDoc} 474 * @param p {@inheritDoc} 475 * @return the result of scanning 476 * @since 12 477 */ 478 @Override 479 public R visitSystemProperty(SystemPropertyTree node, P p) { 480 return null; 481 } 482 483 /** 484 * {@inheritDoc} This implementation returns {@code null}. 485 * 486 * @param node {@inheritDoc} 487 * @param p {@inheritDoc} 488 * @return the result of scanning 489 */ 490 @Override 491 public R visitText(TextTree node, P p) { 492 return null; 493 } 494 495 /** 496 * {@inheritDoc} This implementation scans the children in left to right order. 497 * 498 * @param node {@inheritDoc} 499 * @param p {@inheritDoc} 500 * @return the result of scanning 501 */ 502 @Override 503 public R visitThrows(ThrowsTree node, P p) { 504 R r = scan(node.getExceptionName(), p); 505 r = scanAndReduce(node.getDescription(), p, r); 506 return r; 507 } 508 509 /** 510 * {@inheritDoc} This implementation scans the children in left to right order. 511 * 512 * @param node {@inheritDoc} 513 * @param p {@inheritDoc} 514 * @return the result of scanning 515 */ 516 @Override 517 public R visitUnknownBlockTag(UnknownBlockTagTree node, P p) { 518 return scan(node.getContent(), p); 519 } 520 521 /** 522 * {@inheritDoc} This implementation scans the children in left to right order. 523 * 524 * @param node {@inheritDoc} 525 * @param p {@inheritDoc} 526 * @return the result of scanning 527 */ 528 @Override 529 public R visitUnknownInlineTag(UnknownInlineTagTree node, P p) { 530 return scan(node.getContent(), p); 531 } 532 533 /** 534 * {@inheritDoc} This implementation scans the children in left to right order. 535 * 536 * @param node {@inheritDoc} 537 * @param p {@inheritDoc} 538 * @return the result of scanning 539 */ 540 @Override 541 public R visitUses(UsesTree node, P p) { 542 R r = scan(node.getServiceType(), p); 543 r = scanAndReduce(node.getDescription(), p, r); 544 return r; 545 } 546 547 /** 548 * {@inheritDoc} This implementation scans the children in left to right order. 549 * 550 * @param node {@inheritDoc} 551 * @param p {@inheritDoc} 552 * @return the result of scanning 553 */ 554 @Override 555 public R visitValue(ValueTree node, P p) { 556 return scan(node.getReference(), p); 557 } 558 559 /** 560 * {@inheritDoc} This implementation scans the children in left to right order. 561 * 562 * @param node {@inheritDoc} 563 * @param p {@inheritDoc} 564 * @return the result of scanning 565 */ 566 @Override 567 public R visitVersion(VersionTree node, P p) { 568 return scan(node.getBody(), p); 569 } 570 571 /** 572 * {@inheritDoc} This implementation returns {@code null}. 573 * 574 * @param node {@inheritDoc} 575 * @param p {@inheritDoc} 576 * @return the result of scanning 577 */ 578 @Override 579 public R visitOther(DocTree node, P p) { 580 return null; 581 } 582 583 }