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().stream().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().stream().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 node.getStatement().accept(this, r); 170 return null; 171 } 172 173 @Override 174 public R visitFunctionCall(FunctionCallTree node, P r) { 175 node.getFunctionSelect().accept(this, r); 176 node.getArguments().stream().forEach((tree) -> { 177 tree.accept(this, r); 178 }); 179 return null; 180 } 181 182 @Override 183 public R visitFunctionDeclaration(FunctionDeclarationTree node, P r) { 184 node.getParameters().stream().forEach((tree) -> { 185 tree.accept(this, r); 186 }); 187 node.getBody().accept(this, r); 188 return null; 189 } 190 191 @Override 192 public R visitFunctionExpression(FunctionExpressionTree node, P r) { 193 node.getParameters().stream().forEach((tree) -> { 194 tree.accept(this, r); 195 }); 196 node.getBody().accept(this, r); 197 return null; 198 } 199 200 @Override 201 public R visitIdentifier(IdentifierTree node, P r) { 202 return null; 203 } 204 205 @Override 206 public R visitIf(IfTree node, P r) { 207 node.getCondition().accept(this, r); 208 node.getThenStatement().accept(this, r); 209 final Tree elseStat = node.getElseStatement(); 210 if (elseStat != null) { 211 elseStat.accept(this, r); 212 } 213 return null; 214 } 215 216 @Override 217 public R visitArrayAccess(ArrayAccessTree node, P r) { 218 node.getExpression().accept(this, r); 219 node.getIndex().accept(this, r); 220 return null; 221 } 222 223 @Override 224 public R visitArrayLiteral(ArrayLiteralTree node, P r) { 225 node.getElements().stream().filter((tree) -> (tree != null)).forEach((tree) -> { 226 tree.accept(this, r); 227 }); 228 return null; 229 } 230 231 @Override 232 public R visitLabeledStatement(LabeledStatementTree node, P r) { 233 node.getStatement().accept(this, r); 234 return null; 235 } 236 237 @Override 238 public R visitLiteral(LiteralTree node, P r) { 239 return null; 240 } 241 242 @Override 243 public R visitParenthesized(ParenthesizedTree node, P r) { 244 node.getExpression().accept(this, r); 245 return null; 246 } 247 248 @Override 249 public R visitReturn(ReturnTree node, P r) { 250 final Tree retExpr = node.getExpression(); 251 if (retExpr != null) { 252 retExpr.accept(this, r); 253 } 254 return null; 255 } 256 257 @Override 258 public R visitMemberSelect(MemberSelectTree node, P r) { 259 node.getExpression().accept(this, r); 260 return null; 261 } 262 263 @Override 264 public R visitNew(NewTree node, P r) { 265 node.getConstructorExpression().accept(this, r); 266 return null; 267 } 268 269 @Override 270 public R visitObjectLiteral(ObjectLiteralTree node, P r) { 271 node.getProperties().stream().forEach((tree) -> { 272 tree.accept(this, r); 273 }); 274 return null; 275 } 276 277 @Override 278 public R visitProperty(PropertyTree node, P r) { 279 FunctionExpressionTree getter = node.getGetter(); 280 if (getter != null) { 281 getter.accept(this, r); 282 } 283 ExpressionTree key = node.getKey(); 284 if (key != null) { 285 key.accept(this, r); 286 } 287 288 FunctionExpressionTree setter = node.getSetter(); 289 if (setter != null) { 290 setter.accept(this, r); 291 } 292 293 ExpressionTree value = node.getValue(); 294 if (value != null) { 295 value.accept(this, r); 296 } 297 return null; 298 } 299 300 @Override 301 public R visitRegExpLiteral(RegExpLiteralTree node, P r) { 302 return null; 303 } 304 305 @Override 306 public R visitEmptyStatement(EmptyStatementTree node, P r) { 307 return null; 308 } 309 310 @Override 311 public R visitSwitch(SwitchTree node, P r) { 312 node.getExpression().accept(this, r); 313 node.getCases().stream().forEach((tree) -> { 314 tree.accept(this, r); 315 }); 316 return null; 317 } 318 319 @Override 320 public R visitThrow(ThrowTree node, P r) { 321 node.getExpression().accept(this, r); 322 return null; 323 } 324 325 @Override 326 public R visitCompilationUnit(CompilationUnitTree node, P r) { 327 node.getSourceElements().stream().forEach((tree) -> { 328 tree.accept(this, r); 329 }); 330 return null; 331 } 332 333 @Override 334 public R visitTry(TryTree node, P r) { 335 node.getBlock().accept(this, r); 336 node.getCatches().stream().forEach((tree) -> { 337 tree.accept(this, r); 338 }); 339 340 final Tree finallyBlock = node.getFinallyBlock(); 341 if (finallyBlock != null) { 342 finallyBlock.accept(this, r); 343 } 344 return null; 345 } 346 347 @Override 348 public R visitInstanceOf(InstanceOfTree node, P r) { 349 node.getType().accept(this, r); 350 node.getExpression().accept(this, r); 351 return null; 352 } 353 354 @Override 355 public R visitUnary(UnaryTree node, P r) { 356 node.getExpression().accept(this, r); 357 return null; 358 } 359 360 @Override 361 public R visitVariable(VariableTree node, P r) { 362 if (node.getInitializer() != null) { 363 node.getInitializer().accept(this, r); 364 } 365 return null; 366 } 367 368 @Override 369 public R visitWhileLoop(WhileLoopTree node, P r) { 370 node.getCondition().accept(this, r); 371 node.getStatement().accept(this, r); 372 return null; 373 } 374 375 @Override 376 public R visitWith(WithTree node, P r) { 377 node.getScope().accept(this, r); 378 node.getStatement().accept(this, r); 379 return null; 380 } 381 382 @Override 383 public R visitUnknown(Tree node, P r) { 384 // unknown in ECMAScript 5.1 edition 385 throw new UnknownTreeException(node, r); 386 } 387 }