1 /* 2 * Copyright (c) 2005, 2013, 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 @jdk.Supported 72 public class TreeScanner<R,P> implements TreeVisitor<R,P> { 73 74 /** Scan a single node. 75 */ 76 public R scan(Tree node, P p) { 77 return (node == null) ? null : node.accept(this, p); 78 } 79 80 private R scanAndReduce(Tree node, P p, R r) { 81 return reduce(scan(node, p), r); 82 } 83 84 /** Scan a list of nodes. 85 */ 86 public R scan(Iterable<? extends Tree> nodes, P p) { 87 R r = null; 88 if (nodes != null) { 89 boolean first = true; 90 for (Tree node : nodes) { 91 r = (first ? scan(node, p) : scanAndReduce(node, p, r)); 92 first = false; 93 } 94 } 95 return r; 96 } 97 98 private R scanAndReduce(Iterable<? extends Tree> nodes, P p, R r) { 99 return reduce(scan(nodes, p), r); 100 } 101 102 /** 103 * Reduces two results into a combined result. 104 * The default implementation is to return the first parameter. 105 * The general contract of the method is that it may take any action whatsoever. 106 */ 107 public R reduce(R r1, R r2) { 108 return r1; 109 } 110 111 112 /* *************************************************************************** 113 * Visitor methods 114 ****************************************************************************/ 115 116 public R visitCompilationUnit(CompilationUnitTree node, P p) { 117 R r = scan(node.getPackageAnnotations(), p); 118 r = scanAndReduce(node.getPackageName(), p, r); 119 r = scanAndReduce(node.getImports(), p, r); 120 r = scanAndReduce(node.getTypeDecls(), p, r); 121 return r; 122 } 123 124 public R visitImport(ImportTree node, P p) { 125 return scan(node.getQualifiedIdentifier(), p); 126 } 127 128 public R visitClass(ClassTree node, P p) { 129 R r = scan(node.getModifiers(), p); 130 r = scanAndReduce(node.getTypeParameters(), p, r); 131 r = scanAndReduce(node.getExtendsClause(), p, r); 132 r = scanAndReduce(node.getImplementsClause(), p, r); 133 r = scanAndReduce(node.getMembers(), p, r); 134 return r; 135 } 136 137 public R visitMethod(MethodTree node, P p) { 138 R r = scan(node.getModifiers(), p); 139 r = scanAndReduce(node.getReturnType(), p, r); 140 r = scanAndReduce(node.getTypeParameters(), p, r); 141 r = scanAndReduce(node.getParameters(), p, r); 142 r = scanAndReduce(node.getReceiverParameter(), p, r); 143 r = scanAndReduce(node.getThrows(), p, r); 144 r = scanAndReduce(node.getBody(), p, r); 145 r = scanAndReduce(node.getDefaultValue(), p, r); 146 return r; 147 } 148 149 public R visitVariable(VariableTree node, P p) { 150 R r = scan(node.getModifiers(), p); 151 r = scanAndReduce(node.getType(), p, r); 152 r = scanAndReduce(node.getInitializer(), p, r); 153 return r; 154 } 155 156 public R visitEmptyStatement(EmptyStatementTree node, P p) { 157 return null; 158 } 159 160 public R visitBlock(BlockTree node, P p) { 161 return scan(node.getStatements(), p); 162 } 163 164 public R visitDoWhileLoop(DoWhileLoopTree node, P p) { 165 R r = scan(node.getStatement(), p); 166 r = scanAndReduce(node.getCondition(), p, r); 167 return r; 168 } 169 170 public R visitWhileLoop(WhileLoopTree node, P p) { 171 R r = scan(node.getCondition(), p); 172 r = scanAndReduce(node.getStatement(), p, r); 173 return r; 174 } 175 176 public R visitForLoop(ForLoopTree node, P p) { 177 R r = scan(node.getInitializer(), p); 178 r = scanAndReduce(node.getCondition(), p, r); 179 r = scanAndReduce(node.getUpdate(), p, r); 180 r = scanAndReduce(node.getStatement(), p, r); 181 return r; 182 } 183 184 public R visitEnhancedForLoop(EnhancedForLoopTree node, P p) { 185 R r = scan(node.getVariable(), p); 186 r = scanAndReduce(node.getExpression(), p, r); 187 r = scanAndReduce(node.getStatement(), p, r); 188 return r; 189 } 190 191 public R visitLabeledStatement(LabeledStatementTree node, P p) { 192 return scan(node.getStatement(), p); 193 } 194 195 public R visitSwitch(SwitchTree node, P p) { 196 R r = scan(node.getExpression(), p); 197 r = scanAndReduce(node.getCases(), p, r); 198 return r; 199 } 200 201 public R visitCase(CaseTree node, P p) { 202 R r = scan(node.getExpression(), p); 203 r = scanAndReduce(node.getStatements(), p, r); 204 return r; 205 } 206 207 public R visitSynchronized(SynchronizedTree node, P p) { 208 R r = scan(node.getExpression(), p); 209 r = scanAndReduce(node.getBlock(), p, r); 210 return r; 211 } 212 213 public R visitTry(TryTree node, P p) { 214 R r = scan(node.getResources(), p); 215 r = scanAndReduce(node.getBlock(), p, r); 216 r = scanAndReduce(node.getCatches(), p, r); 217 r = scanAndReduce(node.getFinallyBlock(), p, r); 218 return r; 219 } 220 221 public R visitCatch(CatchTree node, P p) { 222 R r = scan(node.getParameter(), p); 223 r = scanAndReduce(node.getBlock(), p, r); 224 return r; 225 } 226 227 public R visitConditionalExpression(ConditionalExpressionTree node, P p) { 228 R r = scan(node.getCondition(), p); 229 r = scanAndReduce(node.getTrueExpression(), p, r); 230 r = scanAndReduce(node.getFalseExpression(), p, r); 231 return r; 232 } 233 234 public R visitIf(IfTree node, P p) { 235 R r = scan(node.getCondition(), p); 236 r = scanAndReduce(node.getThenStatement(), p, r); 237 r = scanAndReduce(node.getElseStatement(), p, r); 238 return r; 239 } 240 241 public R visitExpressionStatement(ExpressionStatementTree node, P p) { 242 return scan(node.getExpression(), p); 243 } 244 245 public R visitBreak(BreakTree node, P p) { 246 return null; 247 } 248 249 public R visitContinue(ContinueTree node, P p) { 250 return null; 251 } 252 253 public R visitReturn(ReturnTree node, P p) { 254 return scan(node.getExpression(), p); 255 } 256 257 public R visitThrow(ThrowTree node, P p) { 258 return scan(node.getExpression(), p); 259 } 260 261 public R visitAssert(AssertTree node, P p) { 262 R r = scan(node.getCondition(), p); 263 r = scanAndReduce(node.getDetail(), p, r); 264 return r; 265 } 266 267 public R visitMethodInvocation(MethodInvocationTree node, P p) { 268 R r = scan(node.getTypeArguments(), p); 269 r = scanAndReduce(node.getMethodSelect(), p, r); 270 r = scanAndReduce(node.getArguments(), p, r); 271 return r; 272 } 273 274 public R visitNewClass(NewClassTree node, P p) { 275 R r = scan(node.getEnclosingExpression(), p); 276 r = scanAndReduce(node.getIdentifier(), p, r); 277 r = scanAndReduce(node.getTypeArguments(), p, r); 278 r = scanAndReduce(node.getArguments(), p, r); 279 r = scanAndReduce(node.getClassBody(), p, r); 280 return r; 281 } 282 283 public R visitNewArray(NewArrayTree node, P p) { 284 R r = scan(node.getType(), p); 285 r = scanAndReduce(node.getDimensions(), p, r); 286 r = scanAndReduce(node.getInitializers(), p, r); 287 return r; 288 } 289 290 public R visitLambdaExpression(LambdaExpressionTree node, P p) { 291 R r = scan(node.getParameters(), p); 292 r = scanAndReduce(node.getBody(), p, r); 293 return r; 294 } 295 296 public R visitParenthesized(ParenthesizedTree node, P p) { 297 return scan(node.getExpression(), p); 298 } 299 300 public R visitAssignment(AssignmentTree node, P p) { 301 R r = scan(node.getVariable(), p); 302 r = scanAndReduce(node.getExpression(), p, r); 303 return r; 304 } 305 306 public R visitCompoundAssignment(CompoundAssignmentTree node, P p) { 307 R r = scan(node.getVariable(), p); 308 r = scanAndReduce(node.getExpression(), p, r); 309 return r; 310 } 311 312 public R visitUnary(UnaryTree node, P p) { 313 return scan(node.getExpression(), p); 314 } 315 316 public R visitBinary(BinaryTree node, P p) { 317 R r = scan(node.getLeftOperand(), p); 318 r = scanAndReduce(node.getRightOperand(), p, r); 319 return r; 320 } 321 322 public R visitTypeCast(TypeCastTree node, P p) { 323 R r = scan(node.getType(), p); 324 r = scanAndReduce(node.getExpression(), p, r); 325 return r; 326 } 327 328 public R visitInstanceOf(InstanceOfTree node, P p) { 329 R r = scan(node.getExpression(), p); 330 r = scanAndReduce(node.getType(), p, r); 331 return r; 332 } 333 334 public R visitArrayAccess(ArrayAccessTree node, P p) { 335 R r = scan(node.getExpression(), p); 336 r = scanAndReduce(node.getIndex(), p, r); 337 return r; 338 } 339 340 public R visitMemberSelect(MemberSelectTree node, P p) { 341 return scan(node.getExpression(), p); 342 } 343 344 public R visitMemberReference(MemberReferenceTree node, P p) { 345 R r = scan(node.getQualifierExpression(), p); 346 r = scanAndReduce(node.getTypeArguments(), p, r); 347 return r; 348 } 349 350 public R visitIdentifier(IdentifierTree node, P p) { 351 return null; 352 } 353 354 public R visitLiteral(LiteralTree node, P p) { 355 return null; 356 } 357 358 public R visitPrimitiveType(PrimitiveTypeTree node, P p) { 359 return null; 360 } 361 362 public R visitArrayType(ArrayTypeTree node, P p) { 363 return scan(node.getType(), p); 364 } 365 366 public R visitParameterizedType(ParameterizedTypeTree node, P p) { 367 R r = scan(node.getType(), p); 368 r = scanAndReduce(node.getTypeArguments(), p, r); 369 return r; 370 } 371 372 public R visitUnionType(UnionTypeTree node, P p) { 373 return scan(node.getTypeAlternatives(), p); 374 } 375 376 public R visitIntersectionType(IntersectionTypeTree node, P p) { 377 return scan(node.getBounds(), p); 378 } 379 380 public R visitTypeParameter(TypeParameterTree node, P p) { 381 R r = scan(node.getAnnotations(), p); 382 r = scanAndReduce(node.getBounds(), p, r); 383 return r; 384 } 385 386 public R visitWildcard(WildcardTree node, P p) { 387 return scan(node.getBound(), p); 388 } 389 390 public R visitModifiers(ModifiersTree node, P p) { 391 return scan(node.getAnnotations(), p); 392 } 393 394 public R visitAnnotation(AnnotationTree node, P p) { 395 R r = scan(node.getAnnotationType(), p); 396 r = scanAndReduce(node.getArguments(), p, r); 397 return r; 398 } 399 400 public R visitAnnotatedType(AnnotatedTypeTree node, P p) { 401 R r = scan(node.getAnnotations(), p); 402 r = scanAndReduce(node.getUnderlyingType(), p, r); 403 return r; 404 } 405 406 public R visitOther(Tree node, P p) { 407 return null; 408 } 409 410 public R visitErroneous(ErroneousTree node, P p) { 411 return null; 412 } 413 }