1 19 20 package org.netbeans.modules.debugger.jpda.projects; 21 22 import com.sun.source.tree.AnnotationTree; 23 import com.sun.source.tree.ArrayAccessTree; 24 import com.sun.source.tree.ArrayTypeTree; 25 import com.sun.source.tree.AssertTree; 26 import com.sun.source.tree.AssignmentTree; 27 import com.sun.source.tree.BinaryTree; 28 import com.sun.source.tree.BlockTree; 29 import com.sun.source.tree.BreakTree; 30 import com.sun.source.tree.CaseTree; 31 import com.sun.source.tree.CatchTree; 32 import com.sun.source.tree.ClassTree; 33 import com.sun.source.tree.CompilationUnitTree; 34 import com.sun.source.tree.CompoundAssignmentTree; 35 import com.sun.source.tree.ConditionalExpressionTree; 36 import com.sun.source.tree.ContinueTree; 37 import com.sun.source.tree.DoWhileLoopTree; 38 import com.sun.source.tree.EmptyStatementTree; 39 import com.sun.source.tree.EnhancedForLoopTree; 40 import com.sun.source.tree.ErroneousTree; 41 import com.sun.source.tree.ExpressionStatementTree; 42 import com.sun.source.tree.ExpressionTree; 43 import com.sun.source.tree.ForLoopTree; 44 import com.sun.source.tree.IdentifierTree; 45 import com.sun.source.tree.IfTree; 46 import com.sun.source.tree.ImportTree; 47 import com.sun.source.tree.InstanceOfTree; 48 import com.sun.source.tree.LabeledStatementTree; 49 import com.sun.source.tree.LineMap; 50 import com.sun.source.tree.LiteralTree; 51 import com.sun.source.tree.MemberSelectTree; 52 import com.sun.source.tree.MethodInvocationTree; 53 import com.sun.source.tree.MethodTree; 54 import com.sun.source.tree.ModifiersTree; 55 import com.sun.source.tree.NewArrayTree; 56 import com.sun.source.tree.NewClassTree; 57 import com.sun.source.tree.ParameterizedTypeTree; 58 import com.sun.source.tree.ParenthesizedTree; 59 import com.sun.source.tree.PrimitiveTypeTree; 60 import com.sun.source.tree.ReturnTree; 61 import com.sun.source.tree.StatementTree; 62 import com.sun.source.tree.SwitchTree; 63 import com.sun.source.tree.SynchronizedTree; 64 import com.sun.source.tree.ThrowTree; 65 import com.sun.source.tree.Tree; 66 import com.sun.source.tree.TreeVisitor; 67 import com.sun.source.tree.TryTree; 68 import com.sun.source.tree.TypeCastTree; 69 import com.sun.source.tree.TypeParameterTree; 70 import com.sun.source.tree.UnaryTree; 71 import com.sun.source.tree.VariableTree; 72 import com.sun.source.tree.WhileLoopTree; 73 import com.sun.source.tree.WildcardTree; 74 import com.sun.source.util.SourcePositions; 75 import com.sun.source.util.TreeScanner; 76 77 import java.util.ArrayList ; 78 import java.util.Collections ; 79 import java.util.Comparator ; 80 import java.util.HashMap ; 81 import java.util.HashSet ; 82 import java.util.List ; 83 import java.util.Map ; 84 import java.util.Set ; 85 import java.util.Stack ; 86 import java.util.TreeSet ; 87 88 93 class ExpressionScanner extends TreeScanner<List <Tree>, ExpressionScanner.ExpressionsInfo> { 94 95 private int lineNumber; 96 private CompilationUnitTree tree; 97 private SourcePositions positions; 98 private LineMap lineMap; 99 private boolean checkBounds = true; 100 101 public ExpressionScanner(int lineNumber, CompilationUnitTree tree, SourcePositions positions) { 102 this.tree = tree; 103 this.lineNumber = lineNumber; 104 this.positions = positions; 105 this.lineMap = tree.getLineMap(); 106 } 107 108 private boolean acceptsTree(Tree aTree) { 109 114 if (!checkBounds) return true; 115 int startLine = (int) lineMap.getLineNumber(positions.getStartPosition(tree, aTree)); 116 if (startLine == lineNumber) { 117 return true; 118 } else { 119 return false; 120 124 } 125 } 126 127 private boolean isCurrentTree(Tree aTree) { 128 int startLine = (int) lineMap.getLineNumber(positions.getStartPosition(tree, aTree)); 129 int endLine = (int) lineMap.getLineNumber(positions.getEndPosition(tree, aTree)); 130 return startLine <= lineNumber && lineNumber <= endLine; 131 } 132 133 public List <Tree> reduce(List <Tree> r1, List <Tree> r2) { 134 if (r1 == null || r1.size() == 0) { 135 return r2; 136 } 137 if (r2 == null || r2.size() == 0) { 138 return r1; 139 } 140 r1.addAll(r2); 141 return r1; 142 } 143 144 public List <Tree> scan(Iterable <? extends Tree> nodes, ExpressionScanner.ExpressionsInfo p) { 145 List <Tree> r = null; 146 if (nodes != null) { 147 boolean first = true; 148 for (Tree node : nodes) { 149 r = (first ? scan(node, p) : reduce(r, scan(node, p))); 150 first = false; 151 } 152 } 153 return r; 154 } 155 156 157 158 private List <Tree> scan(Tree t1, Tree t2, ExpressionScanner.ExpressionsInfo p) { 159 List <Tree> result = scan(t1, p); 160 result = reduce(result, scan(t2, p)); 161 return result; 162 } 163 164 public List <Tree> visitAnnotation(AnnotationTree node, ExpressionScanner.ExpressionsInfo p) { 165 return null; 166 } 167 168 public List <Tree> visitMethodInvocation(MethodInvocationTree node, ExpressionScanner.ExpressionsInfo p) { 169 List <Tree> result = scan(node.getTypeArguments(), p); 170 result = reduce(result, scan(node.getMethodSelect(), p)); 171 result = reduce(result, scan(node.getArguments(), p)); 172 if (result == null) { 173 result = new ArrayList (); 174 } 175 result.add(node); 176 return result; 177 } 178 179 public List <Tree> visitAssert(AssertTree node, ExpressionScanner.ExpressionsInfo p) { 180 List <Tree> result = scan(node.getCondition(), p); 181 result = reduce(result, scan(node.getDetail(), p)); 182 return result; 183 } 184 185 public List <Tree> visitAssignment(AssignmentTree node, ExpressionScanner.ExpressionsInfo p) { 186 return scan(node.getVariable(), node.getExpression(), p); 187 } 188 189 public List <Tree> visitCompoundAssignment(CompoundAssignmentTree node, ExpressionScanner.ExpressionsInfo p) { 190 return scan(node.getVariable(), node.getExpression(), p); 191 } 192 193 public List <Tree> visitBinary(BinaryTree node, ExpressionScanner.ExpressionsInfo p) { 194 return scan(node.getLeftOperand(), node.getRightOperand(), p); 195 } 196 197 200 203 public List <Tree> visitCase(CaseTree node, ExpressionScanner.ExpressionsInfo p) { 204 List <Tree> result = scan(node.getExpression(), p); 205 result = reduce(result, scan(node.getStatements(), p)); 206 return result; 207 } 208 209 212 215 public List <Tree> visitConditionalExpression(ConditionalExpressionTree node, ExpressionScanner.ExpressionsInfo p) { 216 List <Tree> cond = scan(node.getCondition(), p); 217 Tree lastCond = null; 218 if (cond != null) { 219 lastCond = cond.get(cond.size() - 1); 220 } 221 List <Tree> rT = scan(node.getTrueExpression(), p); 222 List <Tree> rF = scan(node.getFalseExpression(), p); 223 if (lastCond != null) { 224 if (rT != null) { 225 p.addNextExpression(lastCond, rT.get(0)); 226 } 227 if (rF != null) { 228 p.addNextExpression(lastCond, rF.get(0)); 229 } 230 } 231 return reduce(reduce(cond, rT), rF); 232 } 233 234 237 public List <Tree> visitDoWhileLoop(DoWhileLoopTree node, ExpressionScanner.ExpressionsInfo p) { 238 List <Tree> statements = scan(node.getStatement(), p); 239 List <Tree> cond = null; 240 Tree lastCond = null; 241 if (acceptsTree(node.getCondition())) { 242 cond = scan(node.getCondition(), p); 243 lastCond = cond.get(cond.size() - 1); 244 } 245 if (cond != null && statements != null && statements.size() > 0) { 246 p.addNextExpression(lastCond, statements.get(0)); 247 } 248 return reduce(statements, cond); 249 } 250 251 254 public List <Tree> visitExpressionStatement(ExpressionStatementTree node, ExpressionScanner.ExpressionsInfo p) { 255 if (acceptsTree(node)) { 256 return scan(node.getExpression(), p); 257 } else { 258 return null; 259 } 260 } 261 262 public List <Tree> visitEnhancedForLoop(EnhancedForLoopTree node, ExpressionScanner.ExpressionsInfo p) { 263 List <Tree> expr = null; 264 if (acceptsTree(node.getExpression())) { 265 expr = scan(node.getExpression(), p); 266 } 267 List <Tree> bodyr = scan(node.getStatement(), p); 268 if (expr != null && expr.size() > 0 && 269 bodyr != null && bodyr.size() > 0) { 270 p.addNextExpression(expr.get(expr.size() - 1), bodyr.get(0)); 271 p.addNextExpression(bodyr.get(bodyr.size() - 1), expr.get(0)); 272 } 273 return reduce(expr, bodyr); 274 } 275 276 public List <Tree> visitForLoop(ForLoopTree node, ExpressionScanner.ExpressionsInfo p) { 277 if (!isCurrentTree(node)) { 278 return null; 279 } 280 List <Tree> initr = scan(node.getInitializer(), p); 281 checkBounds = false; List <Tree> condra = scan(node.getCondition(), p); 283 List <Tree> updtra = scan(node.getUpdate(), p); 284 checkBounds = true; 286 287 List <Tree> condr = null; 289 if (acceptsTree(node.getCondition())) { 290 condr = scan(node.getCondition(), p); 291 } 292 List <Tree> updtr = scan(node.getUpdate(), p); 293 List <Tree> bodyr = scan(node.getStatement(), p); 294 295 if (initr != null) { 296 if (condra != null) { 297 p.addNextExpression(initr.get(initr.size() - 1), condra.get(0)); 298 } else if (bodyr != null) { 299 p.addNextExpression(initr.get(initr.size() - 1), bodyr.get(0)); 300 } else if (updtra != null) { 301 p.addNextExpression(initr.get(initr.size() - 1), updtra.get(0)); 302 } 303 } 304 if (condr != null) { 305 if (bodyr != null) { 306 p.addNextExpression(condr.get(condr.size() - 1), bodyr.get(0)); 307 } else if (updtra != null) { 308 p.addNextExpression(condr.get(condr.size() - 1), updtra.get(0)); 309 } 310 } 311 if (bodyr != null) { 312 if (updtra != null) { 313 p.addNextExpression(bodyr.get(bodyr.size() - 1), updtra.get(0)); 314 } else if (condra != null) { 315 p.addNextExpression(bodyr.get(bodyr.size() - 1), condra.get(0)); 316 } 317 } 318 if (updtr != null) { 319 if (condra != null) { 320 p.addNextExpression(updtr.get(updtr.size() - 1), condra.get(0)); 321 } else if (bodyr != null) { 322 p.addNextExpression(updtr.get(updtr.size() - 1), bodyr.get(0)); 323 } 324 } 325 return reduce(reduce(reduce(initr, condr), bodyr), updtr); 326 } 327 328 331 public List <Tree> visitIf(IfTree node, ExpressionScanner.ExpressionsInfo p) { 332 List <Tree> cond = null; 333 Tree lastCond = null; 334 if (acceptsTree(node)) { 335 cond = scan(node.getCondition(), p); 336 if (cond != null) { 337 lastCond = cond.get(cond.size() - 1); 338 } 339 } 340 StatementTree thent = node.getThenStatement(); 341 StatementTree elset = node.getElseStatement(); 342 List <Tree> thenr = null; 343 if (isCurrentTree(thent)) { 344 thenr = scan(thent, p); 345 if (lastCond != null && thenr != null) { 346 p.addNextExpression(lastCond, thenr.get(0)); 347 } 348 } 349 List <Tree> elser = null; 350 if (isCurrentTree(elset)) { 351 elser = scan(elset, p); 352 if (lastCond != null && elser != null) { 353 p.addNextExpression(lastCond, elser.get(0)); 354 } 355 } 356 return reduce(reduce(cond, thenr), elser); 357 } 358 359 362 public List <Tree> visitArrayAccess(ArrayAccessTree node, ExpressionScanner.ExpressionsInfo p) { 363 return scan(node.getExpression(), node.getIndex(), p); 364 } 365 366 369 372 375 public List <Tree> visitModifiers(ModifiersTree node, ExpressionScanner.ExpressionsInfo p) { 376 return null; 377 } 378 379 public List <Tree> visitNewArray(NewArrayTree node, ExpressionScanner.ExpressionsInfo p) { 380 List <Tree> result = scan(node.getType(), p); 381 result = reduce(result, scan(node.getDimensions(), p)); 382 result = reduce(result, scan(node.getInitializers(), p)); 383 return result; 384 } 385 386 public List <Tree> visitNewClass(NewClassTree node, ExpressionScanner.ExpressionsInfo p) { 387 List <Tree> result = scan(node.getEnclosingExpression(), node.getIdentifier(), p); 388 result = reduce(result, scan(node.getArguments(), p)); 389 result = reduce(result, scan(node.getClassBody(), p)); 390 if (result == null) { 391 result = new ArrayList (); 392 } 393 result.add(node); 394 return result; 395 } 396 397 400 403 406 409 public List <Tree> visitSwitch(SwitchTree node, ExpressionScanner.ExpressionsInfo p) { 410 List <Tree> result = null; 411 if (acceptsTree(node)) { 412 result = scan(node.getExpression(), p); 413 } 414 return reduce(result, scan(node.getCases(), p)); 415 } 416 417 public List <Tree> visitSynchronized(SynchronizedTree node, ExpressionScanner.ExpressionsInfo p) { 418 List <Tree> result = null; 419 if (acceptsTree(node)) { 420 result = scan(node.getExpression(), p); 421 } 422 return reduce(result, scan(node.getBlock(), p)); 423 } 424 425 428 431 434 public List <Tree> visitParameterizedType(ParameterizedTypeTree node, ExpressionScanner.ExpressionsInfo p) { 435 return null; 436 } 437 438 441 public List <Tree> visitTypeCast(TypeCastTree node, ExpressionScanner.ExpressionsInfo p) { 442 return scan(node.getExpression(), p); 443 } 444 445 448 451 public List <Tree> visitInstanceOf(InstanceOfTree node, ExpressionScanner.ExpressionsInfo p) { 452 return scan(node.getExpression(), node.getType(), p); 453 } 454 455 public List <Tree> visitUnary(UnaryTree node, ExpressionScanner.ExpressionsInfo p) { 456 return scan(node.getExpression(), p); 457 } 458 459 public List <Tree> visitVariable(VariableTree node, ExpressionScanner.ExpressionsInfo p) { 460 if (acceptsTree(node)) { 461 return scan(node.getInitializer(), p); 462 } else { 463 return null; 464 } 465 } 466 467 public List <Tree> visitWhileLoop(WhileLoopTree node, ExpressionScanner.ExpressionsInfo p) { 468 List <Tree> cond = null; 469 if (acceptsTree(node.getCondition())) { 470 cond = scan(node.getCondition(), p); 471 } 472 List <Tree> statements = scan(node.getStatement(), p); 473 if (cond != null && statements != null && statements.size() > 0) { 474 p.addNextExpression(statements.get(statements.size() - 1), cond.get(0)); 475 } 476 return reduce(cond, statements); 477 } 478 479 482 public List <Tree> visitOther(Tree node, ExpressionScanner.ExpressionsInfo p) { 483 return null; 484 } 485 486 487 488 489 public static final class ExpressionsInfo extends Object { 490 491 private Map<Tree, Set <Tree>> nextExpressions = new HashMap <Tree, Set <Tree>>(); 492 Stack <StatementTree> wrappingStatements = new Stack <StatementTree>(); 493 494 495 synchronized void addNextExpression(Tree expression, Tree next) { 496 Set <Tree> nexts = nextExpressions.get(expression); 497 if (nexts == null) { 498 nexts = new HashSet <Tree>(); 499 nextExpressions.put(expression, nexts); 500 } 501 nexts.add(next); 502 } 503 504 synchronized Set <Tree> getNextExpressions(Tree expression) { 505 Set <Tree> nexts = nextExpressions.get(expression); 506 if (nexts == null) { 507 return Collections.emptySet(); 508 } else { 509 return nexts; 510 } 511 } 512 } 513 } 514 | Popular Tags |