1 /* 2 * Copyright (c) 2005, 2006, 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.tree.*; 29 30 /** 31 * A TreeVisitor that visits all the child tree nodes. 32 * To visit nodes of a particular type, just override the 33 * corresponding visitXYZ method. 34 * Inside your method, call super.visitXYZ to visit descendant 35 * nodes. 36 * 37 * <p>The default implementation of the visitXYZ methods will determine 38 * a result as follows: 39 * <ul> 40 * <li>If the node being visited has no children, the result will be null. 41 * <li>If the node being visited has one child, the result will be the 42 * result of calling {@code scan} on that child. The child may be a simple node 43 * or itself a list of nodes. 44 * <li> If the node being visited has more than one child, the result will 45 * be determined by calling {@code scan} each child in turn, and then combining the 46 * result of each scan after the first with the cumulative result 47 * so far, as determined by the {@link #reduce} method. Each child may be either 48 * a simple node of a list of nodes. The default behavior of the {@code reduce} 49 * method is such that the result of the visitXYZ method will be the result of 50 * the last child scanned. 51 * </ul> 52 * 53 * <p>Here is an example to count the number of identifier nodes in a tree: 54 * <pre> 55 * class CountIdentifiers extends TreeScanner<Integer,Void> { 56 * {@literal @}Override 57 * public Integer visitIdentifier(IdentifierTree node, Void p) { 58 * return 1; 59 * } 60 * {@literal @}Override 61 * public Integer reduce(Integer r1, Integer r2) { 62 * return (r1 == null ? 0 : r1) + (r2 == null ? 0 : r2); 63 * } 64 * } 65 * </pre> 66 * 67 * @author Peter von der Ahé 68 * @author Jonathan Gibbons 69 * @since 1.6 70 */ 71 public class TreeScanner<R,P> implements TreeVisitor<R,P> { 72 73 /** Scan a single node. 74 */ 75 public R scan(Tree node, P p) { 76 return (node == null) ? null : node.accept(this, p); 77 } 78 79 private R scanAndReduce(Tree node, P p, R r) { 80 return reduce(scan(node, p), r); 81 } 82 83 /** Scan a list of nodes. 84 */ 85 public R scan(Iterable<? extends Tree> nodes, P p) { 86 R r = null; 87 if (nodes != null) { 88 boolean first = true; 89 for (Tree node : nodes) { 90 r = (first ? scan(node, p) : scanAndReduce(node, p, r)); 91 first = false; 92 } 93 } 94 return r; 95 } 96 97 private R scanAndReduce(Iterable<? extends Tree> nodes, P p, R r) { 98 return reduce(scan(nodes, p), r); 99 } 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.getReceiverAnnotations(), p, r); 142 r = scanAndReduce(node.getThrows(), p, r); 143 r = scanAndReduce(node.getBody(), p, r); 144 return r; 145 } 146 147 public R visitVariable(VariableTree node, P p) { 148 R r = scan(node.getModifiers(), p); 149 r = scanAndReduce(node.getType(), p, r); 150 r = scanAndReduce(node.getInitializer(), p, r); 151 return r; 152 } 153 154 public R visitEmptyStatement(EmptyStatementTree node, P p) { 155 return null; 156 } 157 158 public R visitBlock(BlockTree node, P p) { 159 return scan(node.getStatements(), p); 160 } 161 162 public R visitDoWhileLoop(DoWhileLoopTree node, P p) { 163 R r = scan(node.getStatement(), p); 164 r = scanAndReduce(node.getCondition(), p, r); 165 return r; 166 } 167 168 public R visitWhileLoop(WhileLoopTree node, P p) { 169 R r = scan(node.getCondition(), p); 170 r = scanAndReduce(node.getStatement(), p, r); 171 return r; 172 } 173 174 public R visitForLoop(ForLoopTree node, P p) { 175 R r = scan(node.getInitializer(), p); 176 r = scanAndReduce(node.getCondition(), p, r); 177 r = scanAndReduce(node.getUpdate(), p, r); 178 r = scanAndReduce(node.getStatement(), p, r); 179 return r; 180 } 181 182 public R visitEnhancedForLoop(EnhancedForLoopTree node, P p) { 183 R r = scan(node.getVariable(), p); 184 r = scanAndReduce(node.getExpression(), p, r); 185 r = scanAndReduce(node.getStatement(), p, r); 186 return r; 187 } 188 189 public R visitLabeledStatement(LabeledStatementTree node, P p) { 190 return scan(node.getStatement(), p); 191 } 192 193 public R visitSwitch(SwitchTree node, P p) { 194 R r = scan(node.getExpression(), p); 195 r = scanAndReduce(node.getCases(), p, r); 196 return r; 197 } 198 199 public R visitCase(CaseTree node, P p) { 200 R r = scan(node.getExpression(), p); 201 r = scanAndReduce(node.getStatements(), p, r); 202 return r; 203 } 204 205 public R visitSynchronized(SynchronizedTree node, P p) { 206 R r = scan(node.getExpression(), p); 207 r = scanAndReduce(node.getBlock(), p, r); 208 return r; 209 } 210 211 public R visitTry(TryTree node, P p) { 212 R r = scan(node.getResources(), p); 213 r = scanAndReduce(node.getBlock(), p, r); 214 r = scanAndReduce(node.getCatches(), p, r); 215 r = scanAndReduce(node.getFinallyBlock(), p, r); 216 return r; 217 } 218 219 public R visitCatch(CatchTree node, P p) { 220 R r = scan(node.getParameter(), p); 221 r = scanAndReduce(node.getBlock(), p, r); 222 return r; 223 } 224 225 public R visitConditionalExpression(ConditionalExpressionTree node, P p) { 226 R r = scan(node.getCondition(), p); 227 r = scanAndReduce(node.getTrueExpression(), p, r); 228 r = scanAndReduce(node.getFalseExpression(), p, r); 229 return r; 230 } 231 232 public R visitIf(IfTree node, P p) { 233 R r = scan(node.getCondition(), p); 234 r = scanAndReduce(node.getThenStatement(), p, r); 235 r = scanAndReduce(node.getElseStatement(), p, r); 236 return r; 237 } 238 239 public R visitExpressionStatement(ExpressionStatementTree node, P p) { 240 return scan(node.getExpression(), p); 241 } 242 243 public R visitBreak(BreakTree node, P p) { 244 return null; 245 } 246 247 public R visitContinue(ContinueTree node, P p) { 248 return null; 249 } 250 251 public R visitReturn(ReturnTree node, P p) { 252 return scan(node.getExpression(), p); 253 } 254 255 public R visitThrow(ThrowTree node, P p) { 256 return scan(node.getExpression(), p); 257 } 258 259 public R visitAssert(AssertTree node, P p) { 260 R r = scan(node.getCondition(), p); 261 r = scanAndReduce(node.getDetail(), p, r); 262 return r; 263 } 264 265 public R visitMethodInvocation(MethodInvocationTree node, P p) { 266 R r = scan(node.getTypeArguments(), p); 267 r = scanAndReduce(node.getMethodSelect(), p, r); 268 r = scanAndReduce(node.getArguments(), p, r); 269 return r; 270 } 271 272 public R visitNewClass(NewClassTree node, P p) { 273 R r = scan(node.getEnclosingExpression(), p); 274 r = scanAndReduce(node.getIdentifier(), p, r); 275 r = scanAndReduce(node.getTypeArguments(), p, r); 276 r = scanAndReduce(node.getArguments(), p, r); 277 r = scanAndReduce(node.getClassBody(), p, r); 278 return r; 279 } 280 281 public R visitNewArray(NewArrayTree node, P p) { 282 R r = scan(node.getType(), p); 283 r = scanAndReduce(node.getDimensions(), p, r); 284 r = scanAndReduce(node.getInitializers(), p, r); 285 return r; 286 } 287 288 public R visitParenthesized(ParenthesizedTree node, P p) { 289 return scan(node.getExpression(), p); 290 } 291 292 public R visitAssignment(AssignmentTree node, P p) { 293 R r = scan(node.getVariable(), p); 294 r = scanAndReduce(node.getExpression(), p, r); 295 return r; 296 } 297 298 public R visitCompoundAssignment(CompoundAssignmentTree node, P p) { 299 R r = scan(node.getVariable(), p); 300 r = scanAndReduce(node.getExpression(), p, r); 301 return r; 302 } 303 304 public R visitUnary(UnaryTree node, P p) { 305 return scan(node.getExpression(), p); 306 } 307 308 public R visitBinary(BinaryTree node, P p) { 309 R r = scan(node.getLeftOperand(), p); 310 r = scanAndReduce(node.getRightOperand(), p, r); 311 return r; 312 } 313 314 public R visitTypeCast(TypeCastTree node, P p) { 315 R r = scan(node.getType(), p); 316 r = scanAndReduce(node.getExpression(), p, r); 317 return r; 318 } 319 320 public R visitInstanceOf(InstanceOfTree node, P p) { 321 R r = scan(node.getExpression(), p); 322 r = scanAndReduce(node.getType(), p, r); 323 return r; 324 } 325 326 public R visitArrayAccess(ArrayAccessTree node, P p) { 327 R r = scan(node.getExpression(), p); 328 r = scanAndReduce(node.getIndex(), p, r); 329 return r; 330 } 331 332 public R visitMemberSelect(MemberSelectTree node, P p) { 333 return scan(node.getExpression(), p); 334 } 335 336 public R visitIdentifier(IdentifierTree node, P p) { 337 return null; 338 } 339 340 public R visitLiteral(LiteralTree node, P p) { 341 return null; 342 } 343 344 public R visitPrimitiveType(PrimitiveTypeTree node, P p) { 345 return null; 346 } 347 348 public R visitArrayType(ArrayTypeTree node, P p) { 349 return scan(node.getType(), p); 350 } 351 352 public R visitParameterizedType(ParameterizedTypeTree node, P p) { 353 R r = scan(node.getType(), p); 354 r = scanAndReduce(node.getTypeArguments(), p, r); 355 return r; 356 } 357 358 public R visitDisjointType(DisjointTypeTree node, P p) { 359 return scan(node.getTypeComponents(), p); 360 } 361 362 public R visitTypeParameter(TypeParameterTree node, P p) { 363 R r = scan(node.getAnnotations(), p); 364 r = scanAndReduce(node.getBounds(), p, r); 365 return r; 366 } 367 368 public R visitWildcard(WildcardTree node, P p) { 369 return scan(node.getBound(), p); 370 } 371 372 public R visitModifiers(ModifiersTree node, P p) { 373 return scan(node.getAnnotations(), p); 374 } 375 376 public R visitAnnotation(AnnotationTree node, P p) { 377 R r = scan(node.getAnnotationType(), p); 378 r = scanAndReduce(node.getArguments(), p, r); 379 return r; 380 } 381 382 public R visitAnnotatedType(AnnotatedTypeTree node, P p) { 383 R r = scan(node.getAnnotations(), p); 384 r = scanAndReduce(node.getUnderlyingType(), p, r); 385 return r; 386 } 387 388 public R visitOther(Tree node, P p) { 389 return null; 390 } 391 392 public R visitErroneous(ErroneousTree node, P p) { 393 return null; 394 } 395 }