1 /* 2 * Copyright (c) 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 26 package jdk.nashorn.api.tree; 27 28 /** 29 * A simple implementation of the TreeVisitor for ECMAScript edition 5.1. 30 * 31 * <p>The visit methods corresponding to ES 5.1 language constructs walk the 32 * "components" of the given tree by calling accept method passing the 33 * current visitor and the additional parameter. 34 * 35 * <p>For constructs introduced in later versions, {@code visitUnknown} 36 * is called instead which throws {@link UnknownTreeException}. 37 * 38 * <p> Methods in this class may be overridden subject to their 39 * general contract. Note that annotating methods in concrete 40 * subclasses with {@link java.lang.Override @Override} will help 41 * ensure that methods are overridden as intended. 42 * 43 * @param <R> the return type of this visitor's methods. Use {@link 44 * Void} for visitors that do not need to return results. 45 * @param <P> the type of the additional parameter to this visitor's 46 * methods. Use {@code Void} for visitors that do not need an 47 * additional parameter. 48 */ 49 public class SimpleTreeVisitorES5_1<R, P> implements TreeVisitor<R, P> { 50 @Override 51 public R visitAssignment(AssignmentTree node, P r) { 52 node.getVariable().accept(this, r); 53 node.getExpression().accept(this, r); 54 return null; 55 } 56 57 @Override 58 public R visitCompoundAssignment(CompoundAssignmentTree node, P r) { 59 node.getVariable().accept(this, r); 60 node.getExpression().accept(this, r); 61 return null; 62 } 63 64 @Override 65 public R visitBinary(BinaryTree node, P r) { 66 node.getLeftOperand().accept(this, r); 67 node.getRightOperand().accept(this, r); 68 return null; 69 } 70 71 @Override 72 public R visitBlock(BlockTree node, P r) { 73 node.getStatements().forEach((tree) -> { 74 tree.accept(this, r); 75 }); 76 return null; 77 } 78 79 @Override 80 public R visitBreak(BreakTree node, P r) { 81 return null; 82 } 83 84 @Override 85 public R visitCase(CaseTree node, P r) { 86 final Tree caseVal = node.getExpression(); 87 if (caseVal != null) { 88 caseVal.accept(this, r); 89 } 90 91 node.getStatements().forEach((tree) -> { 92 tree.accept(this, r); 93 }); 94 return null; 95 } 96 97 @Override 98 public R visitCatch(CatchTree node, P r) { 99 final Tree cond = node.getCondition(); 100 if (cond != null) { 101 cond.accept(this, r); 102 } 103 node.getParameter().accept(this, r); 104 node.getBlock().accept(this, r); 105 return null; 106 } 107 108 @Override 109 public R visitConditionalExpression(ConditionalExpressionTree node, P r) { 110 node.getCondition().accept(this, r); 111 node.getTrueExpression().accept(this, r); 112 node.getFalseExpression().accept(this, r); 113 return null; 114 } 115 116 @Override 117 public R visitContinue(ContinueTree node, P r) { 118 return null; 119 } 120 121 @Override 122 public R visitDebugger(DebuggerTree node, P r) { 123 return null; 124 } 125 126 @Override 127 public R visitDoWhileLoop(DoWhileLoopTree node, P r) { 128 node.getStatement().accept(this, r); 129 node.getCondition().accept(this, r); 130 return null; 131 } 132 133 @Override 134 public R visitErroneous(ErroneousTree node, P r) { 135 return null; 136 } 137 138 @Override 139 public R visitExpressionStatement(ExpressionStatementTree node, P r) { 140 node.getExpression().accept(this, r); 141 return null; 142 } 143 144 @Override 145 public R visitForLoop(ForLoopTree node, P r) { 146 final Tree init = node.getInitializer(); 147 if (init != null) { 148 init.accept(this, r); 149 } 150 151 final Tree cond = node.getCondition(); 152 if (cond != null) { 153 cond.accept(this, r); 154 } 155 156 final Tree update = node.getUpdate(); 157 if (update != null) { 158 update.accept(this, r); 159 } 160 161 node.getStatement().accept(this, r); 162 return null; 163 } 164 165 @Override 166 public R visitForInLoop(ForInLoopTree node, P r) { 167 node.getVariable().accept(this, r); 168 node.getExpression().accept(this, r); 169 final StatementTree stat = node.getStatement(); 170 if (stat != null) { 171 stat.accept(this, r); 172 } 173 return null; 174 } 175 176 @Override 177 public R visitFunctionCall(FunctionCallTree node, P r) { 178 node.getFunctionSelect().accept(this, r); 179 node.getArguments().forEach((tree) -> { 180 tree.accept(this, r); 181 }); 182 return null; 183 } 184 185 @Override 186 public R visitFunctionDeclaration(FunctionDeclarationTree node, P r) { 187 node.getParameters().forEach((tree) -> { 188 tree.accept(this, r); 189 }); 190 node.getBody().accept(this, r); 191 return null; 192 } 193 194 @Override 195 public R visitFunctionExpression(FunctionExpressionTree node, P r) { 196 node.getParameters().forEach((tree) -> { 197 tree.accept(this, r); 198 }); 199 node.getBody().accept(this, r); 200 return null; 201 } 202 203 @Override 204 public R visitIdentifier(IdentifierTree node, P r) { 205 return null; 206 } 207 208 @Override 209 public R visitIf(IfTree node, P r) { 210 node.getCondition().accept(this, r); 211 node.getThenStatement().accept(this, r); 212 final Tree elseStat = node.getElseStatement(); 213 if (elseStat != null) { 214 elseStat.accept(this, r); 215 } 216 return null; 217 } 218 219 @Override 220 public R visitArrayAccess(ArrayAccessTree node, P r) { 221 node.getExpression().accept(this, r); 222 node.getIndex().accept(this, r); 223 return null; 224 } 225 226 @Override 227 public R visitArrayLiteral(ArrayLiteralTree node, P r) { 228 node.getElements().stream().filter((tree) -> (tree != null)).forEach((tree) -> { 229 tree.accept(this, r); 230 }); 231 return null; 232 } 233 234 @Override 235 public R visitLabeledStatement(LabeledStatementTree node, P r) { 236 node.getStatement().accept(this, r); 237 return null; 238 } 239 240 @Override 241 public R visitLiteral(LiteralTree node, P r) { 242 return null; 243 } 244 245 @Override 246 public R visitParenthesized(ParenthesizedTree node, P r) { 247 node.getExpression().accept(this, r); 248 return null; 249 } 250 251 @Override 252 public R visitReturn(ReturnTree node, P r) { 253 final Tree retExpr = node.getExpression(); 254 if (retExpr != null) { 255 retExpr.accept(this, r); 256 } 257 return null; 258 } 259 260 @Override 261 public R visitMemberSelect(MemberSelectTree node, P r) { 262 node.getExpression().accept(this, r); 263 return null; 264 } 265 266 @Override 267 public R visitNew(NewTree node, P r) { 268 node.getConstructorExpression().accept(this, r); 269 return null; 270 } 271 272 @Override 273 public R visitObjectLiteral(ObjectLiteralTree node, P r) { 274 node.getProperties().forEach((tree) -> { 275 tree.accept(this, r); 276 }); 277 return null; 278 } 279 280 @Override 281 public R visitProperty(PropertyTree node, P r) { 282 FunctionExpressionTree getter = node.getGetter(); 283 if (getter != null) { 284 getter.accept(this, r); 285 } 286 ExpressionTree key = node.getKey(); 287 if (key != null) { 288 key.accept(this, r); 289 } 290 291 FunctionExpressionTree setter = node.getSetter(); 292 if (setter != null) { 293 setter.accept(this, r); 294 } 295 296 ExpressionTree value = node.getValue(); 297 if (value != null) { 298 value.accept(this, r); 299 } 300 return null; 301 } 302 303 @Override 304 public R visitRegExpLiteral(RegExpLiteralTree node, P r) { 305 return null; 306 } 307 308 @Override 309 public R visitEmptyStatement(EmptyStatementTree node, P r) { 310 return null; 311 } 312 313 @Override 314 public R visitSwitch(SwitchTree node, P r) { 315 node.getExpression().accept(this, r); 316 node.getCases().forEach((tree) -> { 317 tree.accept(this, r); 318 }); 319 return null; 320 } 321 322 @Override 323 public R visitThrow(ThrowTree node, P r) { 324 node.getExpression().accept(this, r); 325 return null; 326 } 327 328 @Override 329 public R visitCompilationUnit(CompilationUnitTree node, P r) { 330 node.getSourceElements().forEach((tree) -> { 331 tree.accept(this, r); 332 }); 333 return null; 334 } 335 336 @Override 337 public R visitTry(TryTree node, P r) { 338 node.getBlock().accept(this, r); 339 node.getCatches().forEach((tree) -> { 340 tree.accept(this, r); 341 }); 342 343 final Tree finallyBlock = node.getFinallyBlock(); 344 if (finallyBlock != null) { 345 finallyBlock.accept(this, r); 346 } 347 return null; 348 } 349 350 @Override 351 public R visitInstanceOf(InstanceOfTree node, P r) { 352 node.getType().accept(this, r); 353 node.getExpression().accept(this, r); 354 return null; 355 } 356 357 @Override 358 public R visitUnary(UnaryTree node, P r) { 359 node.getExpression().accept(this, r); 360 return null; 361 } 362 363 @Override 364 public R visitVariable(VariableTree node, P r) { 365 if (node.getInitializer() != null) { 366 node.getInitializer().accept(this, r); 367 } 368 return null; 369 } 370 371 @Override 372 public R visitWhileLoop(WhileLoopTree node, P r) { 373 node.getCondition().accept(this, r); 374 node.getStatement().accept(this, r); 375 return null; 376 } 377 378 @Override 379 public R visitWith(WithTree node, P r) { 380 node.getScope().accept(this, r); 381 node.getStatement().accept(this, r); 382 return null; 383 } 384 385 @Override 386 public R visitUnknown(Tree node, P r) { 387 // unknown in ECMAScript 5.1 edition 388 throw new UnknownTreeException(node, r); 389 } 390 }