1 19 20 package org.netbeans.api.java.source.transform; 21 22 import org.netbeans.modules.java.source.engine.EngineEnvironment; 23 import org.netbeans.modules.java.source.engine.RootTree; 24 import org.netbeans.modules.java.source.engine.ASTModel; 25 import org.netbeans.api.java.source.Comment; 26 import org.netbeans.api.java.source.query.CommentHandler; 27 import org.netbeans.modules.java.source.engine.RootTree; 28 import org.netbeans.modules.java.source.engine.ReattributionException; 29 import org.netbeans.modules.java.source.engine.EngineEnvironment; 30 import org.netbeans.api.java.source.query.QueryEnvironment; 31 import org.netbeans.api.java.source.query.Query; 32 import org.netbeans.api.java.source.query.SearchEntry; 33 import org.netbeans.modules.java.source.engine.TreeMakerInt; 34 35 import org.openide.util.NbBundle; 36 37 import com.sun.source.tree.*; 38 import com.sun.source.tree.Tree.Kind; 39 import javax.lang.model.element.Element; 40 import javax.lang.model.type.DeclaredType; 41 42 import java.util.ArrayList ; 43 import java.util.Arrays ; 44 import java.util.Collections ; 45 import java.util.List ; 46 import java.util.logging.*; 47 import javax.lang.model.type.TypeMirror; 48 49 54 public abstract class Transformer<R,P> extends Query<R,P> { 55 protected ASTModel model; 56 public TreeMakerInt make; 57 protected ChangeSet changes; 58 protected String refactoringDescription; 59 private String failureMessage; 60 61 static final Logger logger = Logger.getLogger("org.netbeans.modules.java.source"); 62 63 @Override 64 public void init() { 65 changes = new ChangeSet(getQueryDescription()); 66 result = new TransformResult(this, getRefactoringDescription(), changes); 67 } 68 69 73 @Override 74 public void attach(QueryEnvironment env) { 75 model = ((EngineEnvironment)env).getModel(); 76 make = env.getTreeMaker(); 77 changes.attach(env); 78 result.attach(env); 79 super.attach(env); 80 } 81 82 87 @Override 88 public void release() { 89 super.release(); 90 make = null; 93 types = null; 94 } 95 96 @Override 97 public void destroy() { 98 super.destroy(); 99 changes = null; 100 result = null; 101 } 102 103 public String getRefactoringDescription() { 104 return refactoringDescription != null ? refactoringDescription : "Unnamed Refactoring"; 105 } 106 107 public void setRefactoringDescription(String description) { 108 refactoringDescription = description; 109 } 110 111 @Override 112 public void apply(Tree t) { 113 try { 114 t.accept(getTranslator(), null); 115 RootTree newRoot = commit((RootTree)model.getRoot()); 116 if (!translationSuccessful()) { 117 result.clear(); String errTitle = 119 queryDescription != null ? queryDescription : getString("Transformer.failure"); env.setErrorMessage(failureMessage, errTitle); 121 } else if (changes.hasChanges()) { 122 model.setRoot(newRoot); 123 } 124 } catch (ReattributionException e) { 125 error(e); 126 } 127 } 128 129 String getString(String key) { 130 return NbBundle.getBundle(Transformer.class).getString(key); } 132 133 134 protected TransformResult makePreviewResult() { 135 TransformResult previewResult = new TransformResult(this, queryDescription, changes); 136 for (SearchEntry se : result.getResults()) 137 if (changes.hasOriginal(se.tree)) 138 previewResult.add(se); 139 return previewResult; 140 } 141 142 protected TreeVisitor getTranslator() { 143 return this; 144 } 145 146 149 public ChangeSet getChanges() { 150 return changes; 151 } 152 153 public void setChanges(ChangeSet changes) { 154 this.changes = changes; 155 } 156 157 161 public RootTree commit(RootTree oldRoot) { 162 return changes.commit(oldRoot); 163 } 164 165 public final void addResult(Tree t) { 166 addResult(t, null); 167 } 168 169 public final void addResult(Tree t, String msg) { 170 if(t != null) { 171 Element sym = getCurrentElement(); 172 lastAddition = new SearchEntry(this, sym, t, model.getPos(t), msg, 0); 173 result.add(lastAddition); 174 } 175 } 176 177 182 protected void translationFailure(String message) { 183 logger.severe(message); 184 if (failureMessage != null) 185 failureMessage += "\n" + message; 186 else 187 failureMessage = message; 188 } 189 190 protected String getFailureMessage() { 191 return failureMessage; 192 } 193 194 197 protected boolean translationSuccessful() { 198 return failureMessage == null; 199 } 200 201 public IdentifierTree ident(Element e) { 202 IdentifierTree id = make.Identifier(e.getSimpleName()); 203 model.setElement(id, e); 204 model.setType(id, e.asType()); 205 return id; 206 } 207 208 public MemberSelectTree select(ExpressionTree t, Element e) { 209 MemberSelectTree id = make.MemberSelect(t, e.getSimpleName()); 210 model.setElement(id, e); 211 model.setType(id, e.asType()); 212 return id; 213 } 214 215 public ExpressionTree rwSymbol(Tree old, Element nsym) { 216 if(old instanceof IdentifierTree) 217 return ident(nsym); 218 else if(old instanceof MemberSelectTree) 219 return select(((MemberSelectTree)old).getExpression(), nsym); 220 else { 221 error("Var ref expected "+old); 222 return ident(nsym); 223 } 224 } 225 226 public static <T extends Tree> List <T> sublist(List <T> t, int index, int len) { 227 if (t.isEmpty()) 228 return t; 229 if (len == 0 || index >= t.size()) 230 return Collections.<T>emptyList(); 231 int lastIndex = Math.min(index + len, t.size()); 232 return t.subList(index, lastIndex); 233 } 234 235 private static final int COPY_REST = 99999; 236 237 public StatementTree sublist(StatementTree t, int st) { 238 return sublist(t, st, COPY_REST); 239 } 240 241 public StatementTree sublist(StatementTree t, int st, int len) { 242 StatementTree ret; 243 if (t==null || len <= 1 || !(t instanceof BlockTree)) 244 ret = len<=0 ? null : getStatement(st, t); 245 else { 246 BlockTree block = (BlockTree)t; 247 List <? extends StatementTree> otail = block.getStatements(); 248 List <? extends StatementTree> ntail = sublist(otail,st,len); 249 ret = ntail==otail ? t : make.Block(ntail, false); 250 } 251 if (st==0) copyCommentTo(t, ret); 252 return ret; 253 } 254 255 259 public final void attach(Tree tree, Comment dc) { 260 env.getCommentHandler().addComment(tree, dc); 261 } 262 263 public final void attach(Tree tree, String c) { 264 if(tree!=null && c!=null) 265 env.getCommentHandler().addComment(tree, Comment.create(c)); 266 } 267 268 public final void copyCommentTo(Tree from1, Tree from2, Tree to) { 269 copyCommentTo(from1,to); 270 if(from1 != from2) copyCommentTo(from2,to); 271 } 272 273 public final void copyCommentTo(Tree from, Tree to) { 274 if(from != null && to!=null) { 275 CommentHandler commentHandler = env.getCommentHandler(); 276 commentHandler.copyComments(from, to); 277 } 278 } 279 280 public ExpressionTree Conditional(ExpressionTree cond, ExpressionStatementTree truepart, ExpressionStatementTree falsepart) { 281 if(isTrue(cond)) return truepart.getExpression(); 282 if(isFalse(cond)) return falsepart.getExpression(); 283 return make.ConditionalExpression(cond, 284 truepart.getExpression(), 285 falsepart.getExpression()); 286 } 287 288 public StatementTree If(ExpressionTree cond, StatementTree thenpart, StatementTree elsepart) { 289 if(isEmpty(thenpart)) 290 if(isEmpty(elsepart)) 291 if(sideEffectFree(cond)) return make.EmptyStatement(); 292 else {if(thenpart==null) thenpart = make.EmptyStatement();} else { cond = not(cond); thenpart = elsepart; elsepart = null; } 293 if(isTrue(cond)) return thenpart; 294 if(isFalse(cond)) return elsepart; 295 return make.If(cond,thenpart,elsepart); 296 } 297 298 public StatementTree If(ExpressionTree cond, StatementTree thenpart) { 299 return If(cond,thenpart,null); 300 } 301 302 public StatementTree statement(Tree t) { 303 if(t==null) return null; 304 if(t instanceof ConditionalExpressionTree) { 305 ConditionalExpressionTree ce = (ConditionalExpressionTree) t; 306 t = If(ce.getCondition(), 307 statement(ce.getTrueExpression()), 308 statement(ce.getFalseExpression())); 309 } else if (t instanceof ExpressionTree) 310 t = make.ExpressionStatement((ExpressionTree)t); 311 return (StatementTree)t; 312 } 313 314 public StatementTree block(StatementTree a, StatementTree b) { 315 a = statement(a); 316 b = statement(b); 317 if(isEmpty(a)) return b; 318 if(isEmpty(b)) return a; 319 List <StatementTree> stats = new ArrayList <StatementTree>(); 320 if(a instanceof BlockTree) { 321 stats.addAll(((BlockTree)a).getStatements()); 322 if (b instanceof BlockTree) 323 stats.addAll(((BlockTree)b).getStatements()); 324 else 325 stats.add(b); 326 } else { 327 stats.add(a); 328 if(b instanceof BlockTree) 329 stats.addAll(((BlockTree)b).getStatements()); 330 else 331 stats.add(b); 332 } 333 stats = chopUnreachable(stats); 334 return make.Block(stats, false); 335 } 336 337 public BlockTree block(List <StatementTree> stats, boolean isStatic) { 338 return make.Block(flatten(stats), isStatic); 339 } 340 341 private List <StatementTree> flatten(List <StatementTree> l) { 342 if(l==null || l.isEmpty()) 343 return Collections.<StatementTree>emptyList(); 344 List <StatementTree> newList = new ArrayList <StatementTree>(); 345 for (StatementTree stat : l) { 346 if (isEmpty(stat)) 347 continue; if (stat instanceof BlockTree) { 349 List <StatementTree> sub = 352 convert(StatementTree.class, ((BlockTree)stat).getStatements()); 353 sub = flatten(sub); 354 boolean hasVariable = false; 355 for(StatementTree t : sub) 356 if(t instanceof VariableTree) { 357 hasVariable = true; 358 break; 359 } 360 if (hasVariable) 361 newList.add(stat); 362 else 363 newList.addAll(sub); 364 } else 365 newList.add(stat); 366 } 367 return newList; 368 } 369 370 @SuppressWarnings ("unchecked") 372 private static <T> List <T> convert(Class <T> klass, List <?> list) { 373 if (list == null) 374 return null; 375 for (Object o : list) 376 klass.cast(o); 377 return (List <T>)list; 378 } 379 380 public BlockTree block(StatementTree a) { 381 if(a instanceof BlockTree) return (BlockTree) a; 382 if(a==null) return null; 383 return make.Block(Arrays.asList(statement(a)), false); 384 } 385 386 public int blockLength(Tree a) { 387 if (a==null) 388 return 0; 389 if (!(a instanceof BlockTree)) 390 return 1; 391 return ((BlockTree)a).getStatements().size(); 392 } 393 394 public StatementTree getStatement(int index, StatementTree a) { 395 if (a != null) 396 if (a instanceof BlockTree) { 397 java.util.List <? extends StatementTree> stats = ((BlockTree)a).getStatements(); 398 return index < stats.size() ? stats.get(index) : null; 399 } else 400 return index != 0 ? null : a; 401 return null; 402 } 403 404 public StatementTree lastStatement(StatementTree a) { 405 if(a instanceof BlockTree) { 406 java.util.List <? extends StatementTree> stats = ((BlockTree)a).getStatements(); 407 int n = stats.size(); 408 return n > 0 ? stats.get(n - 1) : a; 409 } else 410 return a; 411 } 412 413 public <T extends Tree> java.util.List <T> chopUnreachable(java.util.List <T> stats) { 414 List <T> newStats = new ArrayList <T>(); 415 boolean foundEndStatement = false; 416 for (T t : stats) { 417 switch (t.getKind()) { 418 case BREAK: 419 case CONTINUE: 420 case THROW: 421 case RETURN: 422 foundEndStatement = true; 423 break; 424 default: 425 if (foundEndStatement) 426 return newStats; 428 } 429 newStats.add(t); 430 } 431 return stats; } 433 434 public ExpressionTree and(ExpressionTree a, ExpressionTree b) { 435 Object ae = eval(a); 436 if(ae==Boolean.TRUE) return b; 437 if(ae==Boolean.FALSE) return a; 438 Object be = eval(b); 439 if(be==Boolean.TRUE) return a; 440 if(be==Boolean.FALSE && sideEffectFree(a)) return b; 441 return make.Binary(Kind.CONDITIONAL_AND,a,b); 442 } 443 444 public ExpressionTree or(ExpressionTree a, ExpressionTree b) { 445 Object ae = eval(a); 446 if(ae==Boolean.TRUE) return a; 447 if(ae==Boolean.FALSE) return b; 448 Object be = eval(b); 449 if(be==Boolean.TRUE && sideEffectFree(a)) return b; 450 if(be==Boolean.FALSE) return a; 451 return make.Binary(Kind.CONDITIONAL_OR,a,b); 452 } 453 454 public ExpressionTree not(ExpressionTree t) { 455 if(t==null) return null; 456 457 if (t instanceof LiteralTree) { 459 Object o = ((LiteralTree)t).getValue(); 460 if (o instanceof Boolean ) 461 return make.Literal(Boolean.valueOf(((Boolean )o).booleanValue())); 462 } 463 464 Kind kind = t.getKind(); 466 if (kind == Kind.LOGICAL_COMPLEMENT) 467 return ((UnaryTree)t).getExpression(); 468 469 Kind otherKind = relInvert.get(kind); 470 if (otherKind != null) { 471 BinaryTree op = (BinaryTree)t; 472 return make.Binary(otherKind, not(op.getLeftOperand()), not(op.getRightOperand())); 473 } else 474 return make.Unary(Kind.LOGICAL_COMPLEMENT, t); 475 } 476 477 private static java.util.Map <Kind,Kind> relInvert; 478 static { 479 relInvert = new java.util.EnumMap <Kind,Kind>(Kind.class); 480 relInvert.put(Kind.CONDITIONAL_AND, Kind.CONDITIONAL_OR); 481 relInvert.put(Kind.CONDITIONAL_OR, Kind.CONDITIONAL_AND); 482 relInvert.put(Kind.EQUAL_TO, Kind.NOT_EQUAL_TO); 483 relInvert.put(Kind.NOT_EQUAL_TO, Kind.EQUAL_TO); 484 relInvert.put(Kind.GREATER_THAN, Kind.LESS_THAN); 485 relInvert.put(Kind.LESS_THAN, Kind.GREATER_THAN); 486 relInvert.put(Kind.GREATER_THAN_EQUAL, Kind.LESS_THAN_EQUAL); 487 relInvert.put(Kind.LESS_THAN_EQUAL, Kind.GREATER_THAN_EQUAL); 488 } 489 490 public Object eval(ExpressionTree t) { 491 if(t==null) return t; 492 t = (ExpressionTree)deblock(t); 493 try { 494 if (t instanceof BinaryTree) { 495 BinaryTree tree = (BinaryTree)t; 496 Object lhs = eval(tree.getLeftOperand()); 497 if(lhs==null) return null; 498 switch(tree.getKind()) { 499 case OR: if(lhs==Boolean.TRUE) return lhs; break; 500 case AND: if(lhs==Boolean.FALSE) return lhs; break; 501 } 502 Object rhs = eval(tree.getRightOperand()); 503 if(rhs==null) return null; 504 switch(tree.getKind()) { 505 case CONDITIONAL_OR: return rhs; 506 case CONDITIONAL_AND: return rhs; 507 case EQUAL_TO: return Boolean.valueOf(compare(lhs,rhs)==0); 508 case NOT_EQUAL_TO: return Boolean.valueOf(compare(lhs,rhs)!=0); 509 case LESS_THAN: return Boolean.valueOf(compare(lhs,rhs)<0); 510 case LESS_THAN_EQUAL: return Boolean.valueOf(compare(lhs,rhs)<=0); 511 case GREATER_THAN: return Boolean.valueOf(compare(lhs,rhs)>0); 512 case GREATER_THAN_EQUAL: return Boolean.valueOf(compare(lhs,rhs)>=0); 513 } 514 if(lhs instanceof Integer && rhs instanceof Integer ) { 515 int ilhs = ((Integer )lhs).intValue(); 516 int irhs = ((Integer )rhs).intValue(); 517 int result; 518 switch(tree.getKind()) { 519 default: return null; 520 case OR: result = ilhs|irhs; break; 521 case AND: result = ilhs&irhs; break; 522 case XOR: result = ilhs^irhs; break; 523 case LEFT_SHIFT: result = ilhs<<irhs; break; 524 case RIGHT_SHIFT: result = ilhs>>irhs; break; 525 case UNSIGNED_RIGHT_SHIFT: result = ilhs>>>irhs; break; 526 case PLUS: result = ilhs+irhs; break; 527 case MINUS: result = ilhs-irhs; break; 528 case MULTIPLY: result = ilhs*irhs; break; 529 case DIVIDE: result = ilhs/irhs; break; 530 case REMAINDER: result = ilhs%irhs; break; 531 } 532 return new Integer (result); 533 } 534 } else if(t instanceof UnaryTree) { 535 Object arg = eval(((UnaryTree)t).getExpression()); 536 if(arg instanceof Integer ) { 537 int result; 538 int iarg = ((Integer )arg).intValue(); 539 switch(t.getKind()) { 540 case UNARY_PLUS: return arg; 541 case UNARY_MINUS: result = -iarg; break; 542 case LOGICAL_COMPLEMENT: 543 case BITWISE_COMPLEMENT: result = ~iarg; break; 544 default: return null; 545 } 546 return new Integer (result); 547 } else if(arg instanceof Float ) { 548 float result; 549 float farg = ((Float )arg).floatValue(); 550 switch(t.getKind()) { 551 case UNARY_PLUS: return arg; 552 case UNARY_MINUS: result = -farg; break; 553 default: return null; 554 } 555 return new Float (result); 556 } else if(arg instanceof Double ) { 557 double result; 558 double darg = ((Double )arg).doubleValue(); 559 switch(t.getKind()) { 560 case UNARY_PLUS: return arg; 561 case UNARY_MINUS: result = -darg; break; 562 default: return null; 563 } 564 return new Double (result); 565 } 566 } else if(t instanceof LiteralTree) return ((LiteralTree)t).getValue(); 567 } catch(Throwable err) {} 568 return null; 569 } 570 571 public int compare(Object a, Object b) { 572 if(a==b) return 0; 573 if(a==null) return -1; 574 if(b==null) return 1; 575 try { 576 if(a.getClass()==b.getClass()) return ((Comparable )a).compareTo(b); 577 if(a instanceof Double || b instanceof Double 578 || a instanceof Float || b instanceof Float ) { 579 double ad = ((Number )a).doubleValue(); 580 double bd = ((Number )b).doubleValue(); 581 return ad<bd ? -1 : ad>bd ? 1 : 0; 582 } 583 long al = ((Long )a).longValue(); 584 long bl = ((Long )b).longValue(); 585 return al<bl ? -1 : al>bl ? 1 : 0; 586 } catch(Throwable t) { return -2; } 587 } 588 589 595 protected ModifiersTree addAnnotation(ModifiersTree mods, DeclaredType annotationType) { 596 Element typeElement = annotationType.asElement(); 597 AnnotationTree a = make.Annotation(make.QualIdent(typeElement), 598 new ArrayList <ExpressionTree>()); 599 model.setType(a, annotationType); 600 return addAnnotation(mods, a); 601 } 602 603 606 protected ModifiersTree addAnnotation(ModifiersTree modifiers, AnnotationTree annotation) { 607 List <AnnotationTree> newAnns = new ArrayList <AnnotationTree>(); 608 newAnns.addAll(modifiers.getAnnotations()); 609 newAnns.add(annotation); 610 ModifiersTree newMods = 611 make.Modifiers(modifiers, newAnns); 612 copyCommentTo(modifiers, newMods); 613 return newMods; 614 } 615 616 623 public static Tree deblock(Tree t) { 624 while (t!=null) 625 switch(t.getKind()) { 626 case BLOCK: { 627 BlockTree b = (BlockTree)t; 628 if (b.isStatic()) 629 return t; 630 List <? extends StatementTree> stats = b.getStatements(); 631 if(stats.size() == 1) 632 t = stats.get(0); 633 else 634 return t; 635 break; 636 } 637 case PARENTHESIZED: 638 t = ((ParenthesizedTree)t).getExpression(); 639 break; 640 default: 641 return t; 642 } 643 return null; 644 } 645 646 653 public void setElement(Tree tree, Element element) { 654 model.setElement(tree, element); 655 } 656 657 664 public void setType(Tree tree, TypeMirror type) { 665 model.setType(tree, type); 666 } 667 } 668 | Popular Tags |