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&lt;Integer,Void&gt; {
  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 }