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