001    /*
002     * Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
003     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004     *
005     * This code is free software; you can redistribute it and/or modify it
006     * under the terms of the GNU General Public License version 2 only, as
007     * published by the Free Software Foundation.  Sun designates this
008     * particular file as subject to the "Classpath" exception as provided
009     * by Sun in the LICENSE file that accompanied this code.
010     *
011     * This code is distributed in the hope that it will be useful, but WITHOUT
012     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014     * version 2 for more details (a copy is included in the LICENSE file that
015     * accompanied this code).
016     *
017     * You should have received a copy of the GNU General Public License version
018     * 2 along with this work; if not, write to the Free Software Foundation,
019     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020     *
021     * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022     * CA 95054 USA or visit www.sun.com if you need additional information or
023     * have any questions.
024     */
025    
026    package com.sun.source.util;
027    
028    import com.sun.source.tree.*;
029    
030    /**
031     * A TreeVisitor that visits all the child tree nodes.
032     * To visit nodes of a particular type, just override the
033     * corresponding visitXYZ method.
034     * Inside your method, call super.visitXYZ to visit descendant
035     * nodes.
036     *
037     * <p>The default implementation of the visitXYZ methods will determine
038     * a result as follows:
039     * <ul>
040     * <li>If the node being visited has no children, the result will be null.
041     * <li>If the node being visited has one child, the result will be the
042     * result of calling {@code scan} on that child. The child may be a simple node
043     * or itself a list of nodes.
044     * <li> If the node being visited has more than one child, the result will
045     * be determined by calling {@code scan} each child in turn, and then combining the
046     * result of each scan after the first with the cumulative result
047     * so far, as determined by the {@link #reduce} method. Each child may be either
048     * a simple node of a list of nodes. The default behavior of the {@code reduce}
049     * method is such that the result of the visitXYZ method will be the result of
050     * the last child scanned.
051     * </ul>
052     *
053     * <p>Here is an example to count the number of identifier nodes in a tree:
054     * <pre>
055     *   class CountIdentifiers extends TreeScanner<Integer,Void> {
056     *      {@literal @}Override
057     *      public Integer visitIdentifier(IdentifierTree node, Void p) {
058     *          return 1;
059     *      }
060     *      {@literal @}Override
061     *      public Integer reduce(Integer r1, Integer r2) {
062     *          return (r1 == null ? 0 : r1) + (r2 == null ? 0 : r2);
063     *      }
064     *   }
065     * </pre>
066     *
067     * @author Peter von der Ah&eacute;
068     * @author Jonathan Gibbons
069     * @since 1.6
070     */
071    public class TreeScanner<R,P> implements TreeVisitor<R,P> {
072    
073        /** Scan a single node.
074         */
075        public R scan(Tree node, P p) {
076            return (node == null) ? null : node.accept(this, p);
077        }
078    
079        private R scanAndReduce(Tree node, P p, R r) {
080            return reduce(scan(node, p), r);
081        }
082    
083        /** Scan a list of nodes.
084         */
085        public R scan(Iterable<? extends Tree> nodes, P p) {
086            R r = null;
087            if (nodes != null) {
088                boolean first = true;
089                for (Tree node : nodes) {
090                    r = (first ? scan(node, p) : scanAndReduce(node, p, r));
091                    first = false;
092                }
093            }
094            return r;
095        }
096    
097        private R scanAndReduce(Iterable<? extends Tree> nodes, P p, R r) {
098            return reduce(scan(nodes, p), r);
099        }
100    
101        /**
102         * Reduces two results into a combined result.
103         * The default implementation is to return the first parameter.
104         * The general contract of the method is that it may take any action whatsoever.
105         */
106        public R reduce(R r1, R r2) {
107            return r1;
108        }
109    
110    
111    /* ***************************************************************************
112     * Visitor methods
113     ****************************************************************************/
114    
115        public R visitCompilationUnit(CompilationUnitTree node, P p) {
116            R r = scan(node.getPackageAnnotations(), p);
117            r = scanAndReduce(node.getPackageName(), p, r);
118            r = scanAndReduce(node.getImports(), p, r);
119            r = scanAndReduce(node.getTypeDecls(), p, r);
120            return r;
121        }
122    
123        public R visitImport(ImportTree node, P p) {
124            return scan(node.getQualifiedIdentifier(), p);
125        }
126    
127        public R visitClass(ClassTree node, P p) {
128            R r = scan(node.getModifiers(), p);
129            r = scanAndReduce(node.getTypeParameters(), p, r);
130            r = scanAndReduce(node.getExtendsClause(), p, r);
131            r = scanAndReduce(node.getImplementsClause(), p, r);
132            r = scanAndReduce(node.getMembers(), p, r);
133            return r;
134        }
135    
136        public R visitMethod(MethodTree node, P p) {
137            R r = scan(node.getModifiers(), p);
138            r = scanAndReduce(node.getReturnType(), p, r);
139            r = scanAndReduce(node.getTypeParameters(), p, r);
140            r = scanAndReduce(node.getParameters(), p, r);
141            r = scanAndReduce(node.getThrows(), p, r);
142            r = scanAndReduce(node.getBody(), p, r);
143            return r;
144        }
145    
146        public R visitVariable(VariableTree node, P p) {
147            R r = scan(node.getModifiers(), p);
148            r = scanAndReduce(node.getType(), p, r);
149            r = scanAndReduce(node.getInitializer(), p, r);
150            return r;
151        }
152    
153        public R visitEmptyStatement(EmptyStatementTree node, P p) {
154            return null;
155        }
156    
157        public R visitBlock(BlockTree node, P p) {
158            return scan(node.getStatements(), p);
159        }
160    
161        /* emw4: staging stuff */
162        public R visitBracketExpr(BracketExprTree node, P p) {
163            throw new UnsupportedOperationException ("visitBracketExpr in TreeScanner");
164        }
165    
166        public R visitBracketStat(BracketStatTree node, P p) {
167            throw new UnsupportedOperationException ("visitBracketStat in TreeScanner");
168        }
169    
170        public R visitEscapeExpr(EscapeExprTree node, P p) {
171            throw new UnsupportedOperationException ("visitEscapeExpr in TreeScanner");
172        }
173    
174        public R visitEscapeStat(EscapeStatTree node, P p) {
175            throw new UnsupportedOperationException ("visitEscapeStat in TreeScanner");
176        }
177    
178        public R visitDoWhileLoop(DoWhileLoopTree node, P p) {
179            R r = scan(node.getStatement(), p);
180            r = scanAndReduce(node.getCondition(), p, r);
181            return r;
182        }
183    
184        public R visitWhileLoop(WhileLoopTree node, P p) {
185            R r = scan(node.getCondition(), p);
186            r = scanAndReduce(node.getStatement(), p, r);
187            return r;
188        }
189    
190        public R visitForLoop(ForLoopTree node, P p) {
191            R r = scan(node.getInitializer(), p);
192            r = scanAndReduce(node.getCondition(), p, r);
193            r = scanAndReduce(node.getUpdate(), p, r);
194            r = scanAndReduce(node.getStatement(), p, r);
195            return r;
196        }
197    
198        public R visitEnhancedForLoop(EnhancedForLoopTree node, P p) {
199            R r = scan(node.getVariable(), p);
200            r = scanAndReduce(node.getExpression(), p, r);
201            r = scanAndReduce(node.getStatement(), p, r);
202            return r;
203        }
204    
205        public R visitLabeledStatement(LabeledStatementTree node, P p) {
206            return scan(node.getStatement(), p);
207        }
208    
209        public R visitSwitch(SwitchTree node, P p) {
210            R r = scan(node.getExpression(), p);
211            r = scanAndReduce(node.getCases(), p, r);
212            return r;
213        }
214    
215        public R visitCase(CaseTree node, P p) {
216            R r = scan(node.getExpression(), p);
217            r = scanAndReduce(node.getStatements(), p, r);
218            return r;
219        }
220    
221        public R visitSynchronized(SynchronizedTree node, P p) {
222            R r = scan(node.getExpression(), p);
223            r = scanAndReduce(node.getBlock(), p, r);
224            return r;
225        }
226    
227        public R visitTry(TryTree node, P p) {
228            R r = scan(node.getBlock(), p);
229            r = scanAndReduce(node.getCatches(), p, r);
230            r = scanAndReduce(node.getFinallyBlock(), p, r);
231            return r;
232        }
233    
234        public R visitCatch(CatchTree node, P p) {
235            R r = scan(node.getParameter(), p);
236            r = scanAndReduce(node.getBlock(), p, r);
237            return r;
238        }
239    
240        public R visitConditionalExpression(ConditionalExpressionTree node, P p) {
241            R r = scan(node.getCondition(), p);
242            r = scanAndReduce(node.getTrueExpression(), p, r);
243            r = scanAndReduce(node.getFalseExpression(), p, r);
244            return r;
245        }
246    
247        public R visitIf(IfTree node, P p) {
248            R r = scan(node.getCondition(), p);
249            r = scanAndReduce(node.getThenStatement(), p, r);
250            r = scanAndReduce(node.getElseStatement(), p, r);
251            return r;
252        }
253    
254        public R visitExpressionStatement(ExpressionStatementTree node, P p) {
255            return scan(node.getExpression(), p);
256        }
257    
258        public R visitBreak(BreakTree node, P p) {
259            return null;
260        }
261    
262        public R visitContinue(ContinueTree node, P p) {
263            return null;
264        }
265    
266        public R visitReturn(ReturnTree node, P p) {
267            return scan(node.getExpression(), p);
268        }
269    
270        public R visitThrow(ThrowTree node, P p) {
271            return scan(node.getExpression(), p);
272        }
273    
274        public R visitAssert(AssertTree node, P p) {
275            R r = scan(node.getCondition(), p);
276            r = scanAndReduce(node.getDetail(), p, r);
277            return r;
278        }
279    
280        public R visitMethodInvocation(MethodInvocationTree node, P p) {
281            R r = scan(node.getTypeArguments(), p);
282            r = scanAndReduce(node.getMethodSelect(), p, r);
283            r = scanAndReduce(node.getArguments(), p, r);
284            return r;
285        }
286    
287        public R visitNewClass(NewClassTree node, P p) {
288            R r = scan(node.getEnclosingExpression(), p);
289            r = scanAndReduce(node.getIdentifier(), p, r);
290            r = scanAndReduce(node.getTypeArguments(), p, r);
291            r = scanAndReduce(node.getArguments(), p, r);
292            r = scanAndReduce(node.getClassBody(), p, r);
293            return r;
294        }
295    
296        public R visitNewArray(NewArrayTree node, P p) {
297            R r = scan(node.getType(), p);
298            r = scanAndReduce(node.getDimensions(), p, r);
299            r = scanAndReduce(node.getInitializers(), p, r);
300            return r;
301        }
302    
303        public R visitParenthesized(ParenthesizedTree node, P p) {
304            return scan(node.getExpression(), p);
305        }
306    
307        public R visitAssignment(AssignmentTree node, P p) {
308            R r = scan(node.getVariable(), p);
309            r = scanAndReduce(node.getExpression(), p, r);
310            return r;
311        }
312    
313        public R visitCompoundAssignment(CompoundAssignmentTree node, P p) {
314            R r = scan(node.getVariable(), p);
315            r = scanAndReduce(node.getExpression(), p, r);
316            return r;
317        }
318    
319        public R visitUnary(UnaryTree node, P p) {
320            return scan(node.getExpression(), p);
321        }
322    
323        public R visitBinary(BinaryTree node, P p) {
324            R r = scan(node.getLeftOperand(), p);
325            r = scanAndReduce(node.getRightOperand(), p, r);
326            return r;
327        }
328    
329        public R visitTypeCast(TypeCastTree node, P p) {
330            R r = scan(node.getType(), p);
331            r = scanAndReduce(node.getExpression(), p, r);
332            return r;
333        }
334    
335        public R visitInstanceOf(InstanceOfTree node, P p) {
336            R r = scan(node.getExpression(), p);
337            r = scanAndReduce(node.getType(), p, r);
338            return r;
339        }
340    
341        public R visitArrayAccess(ArrayAccessTree node, P p) {
342            R r = scan(node.getExpression(), p);
343            r = scanAndReduce(node.getIndex(), p, r);
344            return r;
345        }
346    
347        public R visitMemberSelect(MemberSelectTree node, P p) {
348            return scan(node.getExpression(), p);
349        }
350    
351        public R visitIdentifier(IdentifierTree node, P p) {
352            return null;
353        }
354    
355        public R visitLiteral(LiteralTree node, P p) {
356            return null;
357        }
358    
359        public R visitPrimitiveType(PrimitiveTypeTree node, P p) {
360            return null;
361        }
362    
363        public R visitArrayType(ArrayTypeTree node, P p) {
364            return scan(node.getType(), p);
365        }
366    
367        public R visitParameterizedType(ParameterizedTypeTree node, P p) {
368            R r = scan(node.getType(), p);
369            r = scanAndReduce(node.getTypeArguments(), p, r);
370            return r;
371        }
372    
373        public R visitTypeParameter(TypeParameterTree node, P p) {
374            return scan(node.getBounds(), p);
375        }
376    
377        public R visitWildcard(WildcardTree node, P p) {
378            return scan(node.getBound(), p);
379        }
380    
381        public R visitModifiers(ModifiersTree node, P p) {
382            return scan(node.getAnnotations(), p);
383        }
384    
385        public R visitAnnotation(AnnotationTree node, P p) {
386            R r = scan(node.getAnnotationType(), p);
387            r = scanAndReduce(node.getArguments(), p, r);
388            return r;
389        }
390    
391        public R visitOther(Tree node, P p) {
392            return null;
393        }
394    
395        public R visitErroneous(ErroneousTree node, P p) {
396            return null;
397        }
398    }