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