1 19 package org.netbeans.modules.java.source.save; 20 21 import com.sun.source.tree.ClassTree; 22 import com.sun.source.tree.MethodTree; 23 import com.sun.source.tree.Tree.Kind; 24 import org.netbeans.api.java.lexer.JavaTokenId; 25 import org.netbeans.api.lexer.TokenSequence; 26 import org.netbeans.modules.java.source.builder.CommentHandlerService; 27 import org.netbeans.modules.java.source.builder.ASTService; 28 import org.netbeans.modules.java.source.builder.UndoListService; 29 import org.netbeans.api.java.source.transform.UndoList; 30 import org.netbeans.api.java.source.Comment; 31 import org.netbeans.api.java.source.query.CommentHandler; 32 import org.netbeans.api.java.source.query.CommentSet; 33 import org.netbeans.modules.java.source.engine.ASTModel; 34 import org.netbeans.api.java.source.query.Query; 35 36 import com.sun.tools.javac.code.*; 37 import com.sun.tools.javac.tree.JCTree; 38 import com.sun.tools.javac.tree.JCTree.*; 39 import com.sun.tools.javac.tree.Pretty; 40 import com.sun.tools.javac.tree.TreeInfo; 41 import com.sun.tools.javac.util.Context; 42 import com.sun.tools.javac.util.ListBuffer; 43 import com.sun.tools.javac.util.Name; 44 import com.sun.tools.javac.util.Position; 45 import java.util.ArrayList ; 46 47 import java.util.Iterator ; 48 import java.util.List ; 49 import org.netbeans.api.java.lexer.JavaTokenId; 50 import org.netbeans.api.java.source.WorkingCopy; 51 import org.netbeans.modules.java.source.save.TreeDiff.LineInsertionType; 52 import static org.netbeans.modules.java.source.save.ListMatcher.*; 53 import static com.sun.tools.javac.code.Flags.*; 54 import org.netbeans.modules.java.source.save.TreeDiff.ListType; 55 56 public class TreeDiff { 57 protected ListBuffer<Diff> diffs; 58 protected CommentHandler comments; 59 protected ASTModel model; 60 protected UndoList undo; 61 protected JCTree oldParent; 62 protected JCTree newParent; 63 protected JCCompilationUnit oldTopLevel; 64 65 private WorkingCopy workingCopy; 66 private TokenSequence<JavaTokenId> tokenSequence; 67 68 public static com.sun.tools.javac.util.List<Diff> diff(Context context, JCTree oldTree, JCTree newTree) { 69 return diff(context, null, oldTree, newTree); 70 } 71 72 public static com.sun.tools.javac.util.List<Diff> diff(Context context, 73 WorkingCopy copy, 74 JCTree oldTree, 75 JCTree newTree) 76 { 77 TreeDiff td = new TreeDiff(context, copy); 78 td.diffTree(oldTree, newTree); 79 return td.getDiffs(); 80 } 81 82 protected TreeDiff(Context context, WorkingCopy workingCopy) { 83 diffs = new ListBuffer<Diff>(); 84 comments = CommentHandlerService.instance(context); 85 model = ASTService.instance(context); 86 undo = UndoListService.instance(context); 87 this.workingCopy = workingCopy; 88 this.tokenSequence = workingCopy.getTokenHierarchy().tokenSequence(); 89 } 90 91 protected com.sun.tools.javac.util.List<Diff> getDiffs() { 92 return diffs.toList(); 93 } 94 95 private void append(Diff diff) { 96 for (Diff d : diffs) 99 if (d.equals(diff)) 100 return; 101 diffs.append(diff); 102 } 103 104 public static enum DiffTypes { 105 109 MODIFY("modify"), 110 111 115 INSERT("insert"), 116 117 121 DELETE("delete"), 122 123 126 NAME("name"), 127 128 131 FLAGS("flags"), 132 133 137 MODIFY_COMMENT("modify_comment"), 138 139 143 INSERT_COMMENT("insert_comment"), 144 145 149 DELETE_COMMENT("delete_comment"), 150 151 154 INSERT_OFFSET("insert_offset"), 155 DELETE_OFFSET("delete_offset"), 156 157 160 MODIFY_TOKEN("modify_token"), 161 162 165 INSERT_TOKEN("insert_token"), 166 167 170 DELETE_TOKEN("delete_token"); 171 172 DiffTypes(String name) { 173 this.name = name; 174 } 175 public final String name; 176 } 177 178 public static enum LineInsertionType { 179 BEFORE, AFTER, NONE 180 } 181 182 public static class Diff { 183 protected DiffTypes type; 184 int pos; 185 protected JCTree oldTree; 186 protected JCTree newTree; 187 protected LineInsertionType newLine; 188 protected Comment oldComment; 189 protected Comment newComment; 190 protected boolean trailing; 191 protected Name owningClassName; 192 193 static Diff name(int pos, Name oldName, Name newName) { 194 return new NameDiff(pos, oldName, newName); 195 } 196 197 static Diff name(int pos, String oldName, String newName) { 198 return new NameDiff(pos, oldName, newName); 199 } 200 201 static Diff flags(int pos, int endPos, long oldFlags, long newFlags) { 202 return new FlagsDiff(pos, endPos, oldFlags, newFlags); 203 } 204 205 static Diff delete(JCTree oldTree, int pos) { 206 return new Diff(DiffTypes.DELETE, pos, oldTree, null); 207 } 208 209 static Diff insert(JCTree newTree, int pos, LineInsertionType newLine) { 210 return new Diff(DiffTypes.INSERT, pos, null, newTree, newLine); 211 } 212 213 static Diff insert(JCTree newTree, int pos, LineInsertionType newLine, Name owningClassName) { 214 return new Diff(DiffTypes.INSERT, pos, null, newTree, newLine, null, null, false, owningClassName); 215 } 216 217 static Diff modify(JCTree oldTree, int oldPos, JCTree newTree) { 218 return new Diff(DiffTypes.MODIFY, oldPos, oldTree, newTree); 219 } 220 221 static Diff delete(JCTree oldTree, JCTree newTree, Comment oldC) { 222 return new Diff(DiffTypes.DELETE_COMMENT, oldC.pos(), oldTree, newTree, LineInsertionType.BEFORE, oldC, null, false, null); 223 } 224 225 static Diff insert(int pos, LineInsertionType newLine, JCTree oldTree, JCTree newTree, Comment newC, boolean trailing) { 226 return new Diff(DiffTypes.INSERT_COMMENT, pos, oldTree, newTree, newLine, null, newC, trailing, null); 227 } 228 229 static Diff modify(JCTree oldTree, JCTree newTree, Comment oldC, Comment newC) { 230 return new Diff(DiffTypes.MODIFY_COMMENT, oldC.pos(), oldTree, newTree, LineInsertionType.NONE, oldC, newC, false, null); 231 } 232 233 static Diff insert(String preceding, JCTree newTree, int pos, String tail, ListType itemType) { 237 return new TokenDiff(DiffTypes.INSERT_TOKEN, pos, preceding, null, newTree, tail, itemType); 238 } 239 240 static Diff delete(String preceding, JCTree oldTree, int pos, String tail) { 241 return new TokenDiff(DiffTypes.DELETE_TOKEN, pos, preceding, oldTree, null, tail, null); 242 } 243 244 static Diff modify(String preceding, int pos, JCTree oldTree, JCTree newTree, String tail, ListType itemType) { 245 return new TokenDiff(DiffTypes.MODIFY_TOKEN, pos, preceding, oldTree, newTree, tail, itemType); 246 } 247 249 static Diff insert(int pos, String head, JCTree newTree, String tail, LineInsertionType type, Name owningClassName) { 250 return new OffsetDiff(DiffTypes.INSERT_OFFSET, pos, Position.NOPOS , head, newTree, tail, type, owningClassName); 251 } 252 253 static Diff insert(int pos, String head, JCTree newTree, String tail, LineInsertionType type) { 254 return new OffsetDiff(DiffTypes.INSERT_OFFSET, pos, Position.NOPOS , head, newTree, tail, type, null); 255 } 256 257 static Diff delete(int startOffset, int endOffset) { 258 return new OffsetDiff(DiffTypes.DELETE_OFFSET, startOffset, endOffset, null, null, null, LineInsertionType.NONE, null); 259 } 260 261 Diff(DiffTypes type, int pos) { 262 this(type, pos, null, null); 263 } 264 265 Diff(DiffTypes type, int pos, JCTree oldTree, JCTree newTree) { 266 this(type, pos, oldTree, newTree, LineInsertionType.NONE, null, null, false, null); 267 } 268 269 Diff(DiffTypes type, int pos, JCTree oldTree, JCTree newTree, LineInsertionType newLine) { 270 this(type, pos, oldTree, newTree, newLine, null, null, false, null); 271 } 272 273 Diff(DiffTypes tape, int pos, JCTree oldTree, JCTree newTree, LineInsertionType newLine, 274 Comment oldComment, Comment newComment, boolean trailing, Name owningClassName) { 275 assert pos >= 0 : "invalid source offset"; 276 this.type = tape; 277 this.pos = pos; 278 this.oldTree = oldTree; 279 this.newTree = newTree; 280 this.newLine = newLine; 281 this.oldComment = oldComment; 282 this.newComment = newComment; 283 this.trailing = trailing; 284 this.owningClassName = owningClassName; 285 } 286 287 public JCTree getOld() { 288 return oldTree; 289 } 290 291 public JCTree getNew() { 292 return newTree; 293 } 294 295 public LineInsertionType needsNewLine() { 296 return newLine; 297 } 298 299 public int getPos() { 300 return pos; 301 } 302 303 public Comment getOldComment() { 304 return oldComment; 305 } 306 307 public Comment getNewComment() { 308 return newComment; 309 } 310 311 public boolean isTrailingComment() { 312 return trailing; 313 } 314 315 public boolean equals(Object obj) { 316 if (!(obj instanceof Diff)) 317 return false; 318 Diff d2 = (Diff)obj; 319 return type != d2.type && 320 pos != d2.pos && 321 oldTree != d2.oldTree && 322 newTree != d2.newTree && 323 newLine != d2.newLine && 324 oldComment != d2.oldComment && 325 newComment != d2.newComment && 326 trailing != d2.trailing; 327 } 328 329 public int hashCode() { 330 return type.hashCode() + pos + 331 (oldTree != null ? oldTree.hashCode() : 0) + 332 (newTree != null ? newTree.hashCode() : 0) + 333 newLine.hashCode() + 334 (oldComment != null ? oldComment.hashCode() : 0) + 335 (newComment != null ? newComment.hashCode() : 0) + 336 Boolean.valueOf(trailing).hashCode(); 337 } 338 339 public String toString() { 340 StringBuffer sb = new StringBuffer (); 341 sb.append("tree ("); 342 sb.append(type.toString()); 343 sb.append(") pos="); 344 sb.append(pos); 345 if (trailing) 346 sb.append(" trailing comment"); 347 sb.append("\n"); 348 349 if (type == DiffTypes.DELETE || type == DiffTypes.INSERT || type == DiffTypes.MODIFY) 350 addDiffString(sb, oldTree, newTree); 351 else 352 addDiffString(sb, oldComment, newComment); 353 return sb.toString(); 354 } 355 356 private void addDiffString(StringBuffer sb, Object o1, Object o2) { 357 if (o1 != null) { 358 sb.append("< "); 359 sb.append(o1.toString()); 360 sb.append((o2 != null) ? "\n---\n> " : "\n"); 361 } else 362 sb.append("> "); 363 if (o2 != null) { 364 sb.append(o2.toString()); 365 sb.append('\n'); 366 } 367 } 368 } 369 370 public static class NameDiff extends Diff { 371 private String oldName, newName; 372 NameDiff(int pos, Name oldName, Name newName) { 373 this(pos, oldName.toString(), newName.toString()); 374 } 375 NameDiff(int pos, String oldName, String newName) { 376 super(DiffTypes.NAME, pos); 377 this.oldName = oldName; 378 this.newName = newName; 379 } 380 public String getOldName() { 381 return oldName; 382 } 383 public String getNewName() { 384 return newName; 385 } 386 public boolean equals(Object obj) { 387 if (!(obj instanceof NameDiff)) 388 return false; 389 NameDiff nd = (NameDiff)obj; 390 return super.equals(obj) && oldName.equals(nd.oldName) && newName.equals(nd.newName); 391 } 392 public int hashCode() { 393 return super.hashCode() + oldName.hashCode() + newName.hashCode(); 394 } 395 } 396 397 public static class FlagsDiff extends Diff { 398 private long oldFlags, newFlags; 399 int endPos; 400 FlagsDiff(int pos, int endPos, long oldFlags, long newFlags) { 401 super(DiffTypes.FLAGS, pos); 402 this.oldFlags = oldFlags; 403 this.newFlags = newFlags; 404 this.endPos = endPos; 405 } 406 public long getOldFlags() { 407 return oldFlags; 408 } 409 public long getNewFlags() { 410 return newFlags; 411 } 412 public int getOldEndPos() { 413 return endPos; 414 } 415 public boolean equals(Object obj) { 416 if (!(obj instanceof FlagsDiff)) 417 return false; 418 FlagsDiff fd = (FlagsDiff)obj; 419 return super.equals(obj) && 420 oldFlags == fd.oldFlags && 421 newFlags == fd.newFlags && 422 endPos == fd.endPos; 423 } 424 public int hashCode() { 425 return super.hashCode() + Long.valueOf(oldFlags).hashCode() + 426 Long.valueOf(newFlags).hashCode() + endPos; 427 } 428 public String toString() { 429 StringBuffer sb = new StringBuffer (); 430 sb.append("tree ("); 431 sb.append(type.toString()); 432 sb.append(") pos="); 433 sb.append(pos); 434 if (trailing) 435 sb.append(" trailing comment"); 436 sb.append("\n< "); 437 sb.append(TreeInfo.flagNames(oldFlags)); 438 sb.append("\n---\n> "); 439 sb.append(TreeInfo.flagNames(newFlags)); 440 sb.append('\n'); 441 return sb.toString(); 442 } 443 } 444 445 public static class OffsetDiff extends Diff { 446 private final String head; 447 private final String tail; 448 private final int endOffset; 449 450 OffsetDiff(DiffTypes type, int startOffset, int endOffset, String head, JCTree newTree, String tail, LineInsertionType insType, Name owningClassName) { 453 super(type, startOffset, null, newTree, insType); 454 this.endOffset = endOffset; 455 this.head = head; 456 this.tail = tail; 457 this.owningClassName = owningClassName; 458 } 459 460 public int getStartOffset() { return getPos(); } 461 public int getEndOffset() { return endOffset; } 462 463 public String getHead() { return head; } 464 String getTail() { return tail; } 465 } 466 467 public static class TokenDiff extends Diff { 470 private String preceding; 471 private String tail; 472 private ListType itemType; 473 474 TokenDiff(DiffTypes type, int pos, String preceding, JCTree oldTree, JCTree newTree, String tail, ListType itemType) { 475 super(type, pos, oldTree, newTree); 476 this.preceding = preceding; 477 this.tail = tail; 478 this.itemType = itemType; 479 } 480 481 String getPreceding() { 482 return preceding; 483 } 484 485 String getTail() { 486 return tail; 487 } 488 489 ListType getItemType() { 490 return itemType; 491 } 492 } 493 494 private int endPos(JCTree t) { 498 return model.getEndPos(t, oldTopLevel); 499 } 500 501 protected void diffTopLevel(JCCompilationUnit oldT, JCCompilationUnit newT) { 502 oldTopLevel = oldT; 503 diffList(oldT.packageAnnotations, newT.packageAnnotations, LineInsertionType.NONE, 0); 504 int posHint; 505 if (oldT.pid == null) { 507 if (oldT.getImports().head != null) { 508 posHint = oldT.getImports().head.getStartPosition(); 509 } else if (oldT.getTypeDecls().head != null) { 510 posHint = oldT.getTypeDecls().head.getStartPosition(); 511 } else { 512 posHint = 1; 517 } 518 } else { 519 posHint = endPos(oldT.pid); 521 } 522 diffTreeToken("package ", posHint, oldT.pid, newT.pid, ";"); 523 if (oldT.getImports().isEmpty()) { 524 if (oldT.pid != null) { 530 posHint = TokenUtilities.moveFwdToToken(tokenSequence, posHint, JavaTokenId.SEMICOLON); 534 posHint += JavaTokenId.SEMICOLON.fixedText().length(); 535 } 536 } else { 537 posHint = oldT.getImports().head.pos; 538 546 } 547 diffList(oldT.getTypeDecls(), newT.getTypeDecls(), LineInsertionType.BEFORE, Position.NOPOS); 549 } 550 551 protected void diffImport(JCImport oldT, JCImport newT) { 552 if (TreeInfo.fullName(oldT.qualid) != TreeInfo.fullName(newT.qualid)) 553 append(Diff.modify(oldT, getOldPos(oldT), newT)); else if (oldT.staticImport != newT.staticImport) 555 append(Diff.flags(oldT.pos, endPos(oldT), 556 oldT.staticImport ? Flags.STATIC : 0L, 557 newT.staticImport ? Flags.STATIC : 0L)); 558 } 559 560 private Name origClassName = null; 565 566 protected void diffClassDef(JCClassDecl oldT, JCClassDecl newT) { 567 JCTree opar = oldParent; 568 oldParent = oldT; 569 JCTree npar = newParent; 570 newParent = newT; 571 tokenSequence.move(oldT.pos); 572 tokenSequence.moveNext(); 573 int insertHint = TokenUtilities.moveNext(tokenSequence, tokenSequence.offset()); 574 if (nameChanged(oldT.name, newT.name)) { 575 origClassName = oldT.name; 576 append(Diff.name(insertHint, oldT.name, newT.name)); 577 } 578 insertHint += oldT.name.length(); 579 diffModifiers(oldT.mods, newT.mods, oldT); 580 diffParameterList(oldT.typarams, newT.typarams); 581 if (oldT.typarams.nonEmpty()) { 582 insertHint = endPos(oldT.typarams.last()); 586 TokenUtilities.moveFwdToToken(tokenSequence, insertHint, JavaTokenId.GT); 587 insertHint = tokenSequence.offset() + JavaTokenId.GT.fixedText().length(); 588 } 589 diffTree(oldT.extending, newT.extending, insertHint, " extends "); 590 if (oldT.implementing.isEmpty()) { 593 if (oldT.extending != null) 597 insertHint = endPos(oldT.extending); 599 else { 600 } 603 } else { 604 insertHint = oldT.implementing.iterator().next().getStartPosition(); 609 } 610 long flags = oldT.sym != null ? oldT.sym.flags() : oldT.mods.flags; 611 PositionEstimator estimator = (flags & INTERFACE) == 0 ? 612 EstimatorFactory.implementz(((ClassTree) oldT).getImplementsClause(), ((ClassTree) newT).getImplementsClause(), workingCopy) : 613 EstimatorFactory.extendz(((ClassTree) oldT).getImplementsClause(), ((ClassTree) newT).getImplementsClause(), workingCopy); 614 diffList2(oldT.implementing, newT.implementing, insertHint, estimator); 615 insertHint = endPos(oldT) - 1; 616 617 if (oldT.defs.isEmpty()) { 618 insertHint = endPos(oldT) - 1; 623 } else { 624 JCTree t = oldT.defs.head.pos == oldT.pos ? oldT.defs.tail.head : oldT.defs.head; 629 if (t != null) insertHint = t.getStartPosition(); 630 } 631 PositionEstimator est = EstimatorFactory.members(filterHidden(oldT.defs), filterHidden(newT.defs), workingCopy); 632 diffList(filterHidden(oldT.defs), filterHidden(newT.defs), insertHint, est, Measure.MEMBER, newT.name); 633 oldParent = opar; 634 newParent = npar; 635 origClassName = null; 637 } 638 639 protected void diffMethodDef(JCMethodDecl oldT, JCMethodDecl newT) { 640 diffModifiers(oldT.mods, newT.mods, oldT); 641 diffTree(oldT.restype, newT.restype); 642 int posHint; 643 if (oldT.typarams.isEmpty()) { 644 posHint = oldT.restype != null ? oldT.restype.getStartPosition() : oldT.getStartPosition(); 645 } else { 646 posHint = oldT.typarams.iterator().next().getStartPosition(); 647 } 648 if (!oldT.sym.isConstructor() || origClassName != null) { 649 if (nameChanged(oldT.name, newT.name)) 650 if (oldT.sym.isConstructor() && (origClassName != null)) 652 append(Diff.name(oldT.pos, origClassName, newT.name)); 653 else 654 append(Diff.name(oldT.pos, oldT.name, newT.name)); 655 } 656 diffParameterList(oldT.typarams, newT.typarams, posHint, ListType.TYPE_PARAMETER); 657 if (oldT.params.isEmpty()) { 658 int startOffset = oldT.restype != null ? oldT.restype.getStartPosition() : oldT.getStartPosition(); 662 663 tokenSequence.move(startOffset); 664 TokenUtilities.moveFwdToToken(tokenSequence, startOffset, JavaTokenId.RPAREN); 665 posHint = tokenSequence.offset(); 666 } else { 667 posHint = oldT.params.iterator().next().getStartPosition(); 669 } 670 diffParameterList(oldT.params, newT.params, posHint, ListType.PARAMETER); 671 if (oldT.thrown.isEmpty()) { 673 posHint = (oldT.body == null ? endPos(oldT) : oldT.body.pos) - 1; 674 tokenSequence.move(posHint); 677 if (tokenSequence.token().id() != JavaTokenId.WHITESPACE) { 678 ++posHint; 679 } 680 } else { 681 posHint = oldT.thrown.iterator().next().getStartPosition(); 682 } 683 PositionEstimator est = EstimatorFactory.throwz(((MethodTree) oldT).getThrows(), ((MethodTree) newT).getThrows(), workingCopy); 684 diffList2(oldT.thrown, newT.thrown, posHint, est); 685 diffTree(oldT.body, newT.body); 686 diffTree(oldT.defaultValue, newT.defaultValue); 687 } 688 689 protected void diffVarDef(JCVariableDecl oldT, JCVariableDecl newT) { 690 if (nameChanged(oldT.name, newT.name)) 691 append(Diff.name(oldT.pos, oldT.name, newT.name)); 692 diffModifiers(oldT.mods, newT.mods, oldT); 693 diffTree(oldT.vartype, newT.vartype); 694 if (newT.init != null && oldT.init != null) { 695 diffTree(oldT.init, newT.init); 696 } else { 697 diffTreeToken("=", endPos(oldT.init), oldT.init, newT.init, ""); 698 } 699 } 700 701 protected void diffBlock(JCBlock oldT, JCBlock newT) { 702 if (oldT.flags != newT.flags) 703 append(Diff.flags(oldT.pos, endPos(oldT), oldT.flags, newT.flags)); 704 diffList(oldT.stats, newT.stats, LineInsertionType.BEFORE, oldT.pos + 1); } 706 707 protected void diffDoLoop(JCDoWhileLoop oldT, JCDoWhileLoop newT) { 708 diffTree(oldT.body, newT.body); 709 diffTree(oldT.cond, newT.cond); 710 } 711 712 protected void diffWhileLoop(JCWhileLoop oldT, JCWhileLoop newT) { 713 diffTree(oldT.cond, newT.cond); 714 diffTree(oldT.body, newT.body); 715 } 716 717 protected void diffForLoop(JCForLoop oldT, JCForLoop newT) { 718 int initListHint = oldT.cond != null ? oldT.cond.pos - 1 : Query.NOPOS; 719 int stepListHint = oldT.cond != null ? endPos(oldT.cond) + 1 : Query.NOPOS; 720 diffList(oldT.init, newT.init, LineInsertionType.NONE, initListHint); 721 diffTree(oldT.cond, newT.cond); 722 diffList(oldT.step, newT.step, LineInsertionType.NONE, stepListHint); 723 diffTree(oldT.body, newT.body); 724 } 725 726 protected void diffForeachLoop(JCEnhancedForLoop oldT, JCEnhancedForLoop newT) { 727 diffTree(oldT.var, newT.var); 728 diffTree(oldT.expr, newT.expr); 729 diffTree(oldT.body, newT.body); 730 } 731 732 protected void diffLabelled(JCLabeledStatement oldT, JCLabeledStatement newT) { 733 if (nameChanged(oldT.label, newT.label)) 734 append(Diff.name(oldT.pos, oldT.label, newT.label)); 735 diffTree(oldT.body, newT.body); 736 } 737 738 protected void diffSwitch(JCSwitch oldT, JCSwitch newT) { 739 diffTree(oldT.selector, newT.selector); 740 int castListHint = oldT.cases.size() > 0 ? oldT.cases.head.pos : Query.NOPOS; 741 diffList(oldT.cases, newT.cases, LineInsertionType.BEFORE, castListHint); 742 } 743 744 protected void diffCase(JCCase oldT, JCCase newT) { 745 diffTree(oldT.pat, newT.pat); 746 diffList(oldT.stats, newT.stats, LineInsertionType.BEFORE, endPos(oldT) + 1); } 748 749 protected void diffSynchronized(JCSynchronized oldT, JCSynchronized newT) { 750 diffTree(oldT.lock, newT.lock); 751 diffTree(oldT.body, newT.body); 752 } 753 754 protected void diffTry(JCTry oldT, JCTry newT) { 755 diffTree(oldT.body, newT.body); 756 diffList(oldT.catchers, newT.catchers, LineInsertionType.BEFORE, oldT.body.endpos + 1); 757 diffTree(oldT.finalizer, newT.finalizer); 758 } 759 760 protected void diffCatch(JCCatch oldT, JCCatch newT) { 761 diffTree(oldT.param, newT.param); 762 diffTree(oldT.body, newT.body); 763 } 764 765 protected void diffConditional(JCConditional oldT, JCConditional newT) { 766 diffTree(oldT.cond, newT.cond); 767 diffTree(oldT.truepart, newT.truepart); 768 diffTree(oldT.falsepart, newT.falsepart); 769 } 770 771 protected void diffIf(JCIf oldT, JCIf newT) { 772 if (oldT.elsepart == null && newT.elsepart != null || 773 oldT.elsepart != null && newT.elsepart == null) { 774 append(Diff.modify(oldT, getOldPos(oldT), newT)); 776 } else { 777 diffTree(oldT.cond, newT.cond); 778 diffTree(oldT.thenpart, newT.thenpart); 779 diffTree(oldT.elsepart, newT.elsepart); 780 } 781 } 782 783 protected void diffExec(JCExpressionStatement oldT, JCExpressionStatement newT) { 784 diffTree(oldT.expr, newT.expr); 785 } 786 787 protected void diffBreak(JCBreak oldT, JCBreak newT) { 788 if (nameChanged(oldT.label, newT.label)) 789 append(Diff.name(oldT.pos, oldT.label, newT.label)); 790 diffTree(oldT.target, newT.target); 791 } 792 793 protected void diffContinue(JCContinue oldT, JCContinue newT) { 794 if (nameChanged(oldT.label, newT.label)) 795 append(Diff.name(oldT.pos, oldT.label, newT.label)); 796 diffTree(oldT.target, newT.target); 797 } 798 799 protected void diffReturn(JCReturn oldT, JCReturn newT) { 800 diffTree(oldT.expr, newT.expr); 801 } 802 803 protected void diffThrow(JCThrow oldT, JCThrow newT) { 804 diffTree(oldT.expr, newT.expr); 805 } 806 807 protected void diffAssert(JCAssert oldT, JCAssert newT) { 808 diffTree(oldT.cond, newT.cond); 809 diffTree(oldT.detail, newT.detail); 810 } 811 812 protected void diffApply(JCMethodInvocation oldT, JCMethodInvocation newT) { 813 diffParameterList(oldT.typeargs, newT.typeargs); 814 diffTree(oldT.meth, newT.meth); 815 diffParameterList(oldT.args, newT.args); 816 } 817 818 protected void diffNewClass(JCNewClass oldT, JCNewClass newT) { 819 diffTree(oldT.encl, newT.encl); 820 diffParameterList(oldT.typeargs, newT.typeargs); 821 diffTree(oldT.clazz, newT.clazz); 822 diffParameterList(oldT.args, newT.args); 823 diffTree(oldT.def, newT.def); 824 if (oldT.constructor != newT.constructor) 825 append(Diff.name(oldT.pos, oldT.constructor.name, newT.constructor.name)); 826 } 827 828 protected void diffNewArray(JCNewArray oldT, JCNewArray newT) { 829 diffTree(oldT.elemtype, newT.elemtype); 830 diffParameterList(oldT.dims, newT.dims); 831 diffList(oldT.elems, newT.elems, LineInsertionType.NONE, Query.NOPOS); 832 } 833 834 protected void diffParens(JCParens oldT, JCParens newT) { 835 diffTree(oldT.expr, newT.expr); 836 } 837 838 protected void diffAssign(JCAssign oldT, JCAssign newT) { 839 diffTree(oldT.lhs, newT.lhs); 840 diffTree(oldT.rhs, newT.rhs); 841 } 842 843 protected void diffAssignop(JCAssignOp oldT, JCAssignOp newT) { 844 diffTree(oldT.lhs, newT.lhs); 845 diffTree(oldT.rhs, newT.rhs); 846 if (oldT.tag != newT.tag) 847 append(Diff.name(oldT.pos, operatorName(oldT.tag), operatorName(newT.tag))); 848 } 849 850 protected void diffUnary(JCUnary oldT, JCUnary newT) { 851 diffTree(oldT.arg, newT.arg); 852 if (oldT.tag != newT.tag) 853 append(Diff.name(oldT.pos, operatorName(oldT.tag), operatorName(newT.tag))); 854 } 855 856 protected void diffBinary(JCBinary oldT, JCBinary newT) { 857 diffTree(oldT.lhs, newT.lhs); 858 diffTree(oldT.rhs, newT.rhs); 859 if (oldT.tag != newT.tag) 860 append(Diff.name(oldT.pos, operatorName(oldT.tag), operatorName(newT.tag))); 861 } 862 863 private String operatorName(int tag) { 864 return new Pretty(null, false).operatorName(tag); 866 } 867 868 protected void diffTypeCast(JCTypeCast oldT, JCTypeCast newT) { 869 diffTree(oldT.clazz, newT.clazz); 870 diffTree(oldT.expr, newT.expr); 871 } 872 873 protected void diffTypeTest(JCInstanceOf oldT, JCInstanceOf newT) { 874 diffTree(oldT.expr, newT.expr); 875 diffTree(oldT.clazz, newT.clazz); 876 } 877 878 protected void diffIndexed(JCArrayAccess oldT, JCArrayAccess newT) { 879 diffTree(oldT.indexed, newT.indexed); 880 diffTree(oldT.index, newT.index); 881 } 882 883 protected void diffSelect(JCFieldAccess oldT, JCFieldAccess newT) { 884 diffTree(oldT.selected, newT.selected); 885 if (nameChanged(oldT.name, newT.name)) 886 append(Diff.name(oldT.pos, oldT.name, newT.name)); 887 } 888 889 protected void diffIdent(JCIdent oldT, JCIdent newT) { 890 if (nameChanged(oldT.name, newT.name)) 891 append(Diff.name(oldT.pos, oldT.name, newT.name)); 892 } 893 894 protected void diffLiteral(JCLiteral oldT, JCLiteral newT) { 895 if (oldT.typetag != newT.typetag || !oldT.value.equals(newT.value)) 896 append(Diff.modify(oldT, getOldPos(oldT), newT)); 897 } 898 899 protected void diffTypeIdent(JCPrimitiveTypeTree oldT, JCPrimitiveTypeTree newT) { 900 if (oldT.typetag != newT.typetag) 901 append(Diff.modify(oldT, getOldPos(oldT), newT)); 902 } 903 904 protected void diffTypeArray(JCArrayTypeTree oldT, JCArrayTypeTree newT) { 905 diffTree(oldT.elemtype, newT.elemtype); 906 } 907 908 protected void diffTypeApply(JCTypeApply oldT, JCTypeApply newT) { 909 diffTree(oldT.clazz, newT.clazz); 910 diffParameterList(oldT.arguments, newT.arguments); 911 } 912 913 protected void diffTypeParameter(JCTypeParameter oldT, JCTypeParameter newT) { 914 if (nameChanged(oldT.name, newT.name)) 915 append(Diff.name(oldT.pos, oldT.name, newT.name)); 916 diffParameterList(oldT.bounds, newT.bounds); 917 } 918 919 protected void diffWildcard(JCWildcard oldT, JCWildcard newT) { 920 if (oldT.kind != newT.kind) 921 append(Diff.name(oldT.pos, oldT.kind.toString(), newT.kind.toString())); 922 diffTree(oldT.inner, newT.inner); 923 } 924 925 protected void diffTypeBoundKind(TypeBoundKind oldT, TypeBoundKind newT) { 926 if (oldT.kind != newT.kind) 927 append(Diff.name(oldT.pos, oldT.kind.toString(), newT.kind.toString())); 928 } 929 930 protected void diffAnnotation(JCAnnotation oldT, JCAnnotation newT) { 931 diffTree(oldT.annotationType, newT.annotationType); 932 diffParameterList(oldT.args, newT.args); 933 } 934 935 protected void diffModifiers(JCModifiers oldT, JCModifiers newT, JCTree parent) { 936 int oldPos = oldT.pos != Position.NOPOS ? getOldPos(oldT) : getOldPos(parent); 937 if (oldT.flags != newT.flags) 938 append(Diff.flags(oldPos, 939 oldPos == oldT.pos ? endPos(oldT) : oldPos, 940 oldT.flags, newT.flags)); 941 LineInsertionType insertLine = oldT.annotations.nonEmpty() ? 942 LineInsertionType.BEFORE : LineInsertionType.AFTER; 943 diffList(oldT.annotations, newT.annotations, insertLine, oldPos); 944 } 945 946 protected void diffLetExpr(LetExpr oldT, LetExpr newT) { 947 diffList(oldT.defs, newT.defs, LineInsertionType.NONE, Query.NOPOS); 948 diffTree(oldT.expr, newT.expr); 949 } 950 951 protected void diffErroneous(JCErroneous oldT, JCErroneous newT) { 952 diffList(oldT.errs, newT.errs, LineInsertionType.BEFORE, Query.NOPOS); 953 } 954 955 protected boolean listContains(List<? extends JCTree> list, JCTree tree) { 956 for (JCTree t : list) 957 if (treesMatch(t, tree)) 958 return true; 959 return false; 960 } 961 962 protected boolean treesMatch(JCTree t1, JCTree t2) { 963 return treesMatch(t1, t2, true); 964 } 965 966 public boolean treesMatch(JCTree t1, JCTree t2, boolean deepMatch) { 967 if (t1 == t2) 968 return true; 969 if (t1 == null || t2 == null) 970 return false; 971 if (t1.tag != t2.tag) 972 return false; 973 if (!deepMatch) 974 return true; 975 976 switch (t1.tag) { 978 case JCTree.TOPLEVEL: 979 return ((JCCompilationUnit)t1).sourcefile.equals(((JCCompilationUnit)t2).sourcefile); 980 case JCTree.IMPORT: 981 return matchImport((JCImport)t1, (JCImport)t2); 982 case JCTree.CLASSDEF: 983 return ((JCClassDecl)t1).sym == ((JCClassDecl)t2).sym; 984 case JCTree.METHODDEF: 985 return ((JCMethodDecl)t1).sym == ((JCMethodDecl)t2).sym; 986 case JCTree.VARDEF: 987 return ((JCVariableDecl)t1).sym == ((JCVariableDecl)t2).sym; 988 case JCTree.SKIP: 989 return true; 990 case JCTree.BLOCK: 991 return matchBlock((JCBlock)t1, (JCBlock)t2); 992 case JCTree.DOLOOP: 993 return matchDoLoop((JCDoWhileLoop)t1, (JCDoWhileLoop)t2); 994 case JCTree.WHILELOOP: 995 return matchWhileLoop((JCWhileLoop)t1, (JCWhileLoop)t2); 996 case JCTree.FORLOOP: 997 return matchForLoop((JCForLoop)t1, (JCForLoop)t2); 998 case JCTree.FOREACHLOOP: 999 return matchForeachLoop((JCEnhancedForLoop)t1, (JCEnhancedForLoop)t2); 1000 case JCTree.LABELLED: 1001 return matchLabelled((JCLabeledStatement)t1, (JCLabeledStatement)t2); 1002 case JCTree.SWITCH: 1003 return matchSwitch((JCSwitch)t1, (JCSwitch)t2); 1004 case JCTree.CASE: 1005 return matchCase((JCCase)t1, (JCCase)t2); 1006 case JCTree.SYNCHRONIZED: 1007 return matchSynchronized((JCSynchronized)t1, (JCSynchronized)t2); 1008 case JCTree.TRY: 1009 return matchTry((JCTry)t1, (JCTry)t2); 1010 case JCTree.CATCH: 1011 return matchCatch((JCCatch)t1, (JCCatch)t2); 1012 case JCTree.CONDEXPR: 1013 return matchConditional((JCConditional)t1, (JCConditional)t2); 1014 case JCTree.IF: 1015 return matchIf((JCIf)t1, (JCIf)t2); 1016 case JCTree.EXEC: 1017 return treesMatch(((JCExpressionStatement)t1).expr, ((JCExpressionStatement)t2).expr); 1018 case JCTree.BREAK: 1019 return matchBreak((JCBreak)t1, (JCBreak)t2); 1020 case JCTree.CONTINUE: 1021 return matchContinue((JCContinue)t1, (JCContinue)t2); 1022 case JCTree.RETURN: 1023 return treesMatch(((JCReturn)t1).expr, ((JCReturn)t2).expr); 1024 case JCTree.THROW: 1025 return treesMatch(((JCThrow)t1).expr, ((JCThrow)t2).expr); 1026 case JCTree.ASSERT: 1027 return matchAssert((JCAssert)t1, (JCAssert)t2); 1028 case JCTree.APPLY: 1029 return matchApply((JCMethodInvocation)t1, (JCMethodInvocation)t2); 1030 case JCTree.NEWCLASS: 1031 return matchNewClass((JCNewClass)t1, (JCNewClass)t2); 1032 case JCTree.NEWARRAY: 1033 return matchNewArray((JCNewArray)t1, (JCNewArray)t2); 1034 case JCTree.PARENS: 1035 return treesMatch(((JCParens)t1).expr, ((JCParens)t2).expr); 1036 case JCTree.ASSIGN: 1037 return matchAssign((JCAssign)t1, (JCAssign)t2); 1038 case JCTree.TYPECAST: 1039 return matchTypeCast((JCTypeCast)t1, (JCTypeCast)t2); 1040 case JCTree.TYPETEST: 1041 return matchTypeTest((JCInstanceOf)t1, (JCInstanceOf)t2); 1042 case JCTree.INDEXED: 1043 return matchIndexed((JCArrayAccess)t1, (JCArrayAccess)t2); 1044 case JCTree.SELECT: 1045 return ((JCFieldAccess)t1).sym == ((JCFieldAccess)t2).sym; 1046 case JCTree.IDENT: 1047 return ((JCIdent)t1).sym == ((JCIdent)t2).sym; 1048 case JCTree.LITERAL: 1049 return matchLiteral((JCLiteral)t1, (JCLiteral)t2); 1050 case JCTree.TYPEIDENT: 1051 return ((JCPrimitiveTypeTree)t1).typetag == ((JCPrimitiveTypeTree)t2).typetag; 1052 case JCTree.TYPEARRAY: 1053 return treesMatch(((JCArrayTypeTree)t1).elemtype, ((JCArrayTypeTree)t2).elemtype); 1054 case JCTree.TYPEAPPLY: 1055 return matchTypeApply((JCTypeApply)t1, (JCTypeApply)t2); 1056 case JCTree.TYPEPARAMETER: 1057 return matchTypeParameter((JCTypeParameter)t1, (JCTypeParameter)t2); 1058 case JCTree.WILDCARD: 1059 return matchWildcard((JCWildcard)t1, (JCWildcard)t2); 1060 case JCTree.TYPEBOUNDKIND: 1061 return ((TypeBoundKind)t1).kind == ((TypeBoundKind)t2).kind; 1062 case JCTree.ANNOTATION: 1063 return matchAnnotation((JCAnnotation)t1, (JCAnnotation)t2); 1064 case JCTree.LETEXPR: 1065 return matchLetExpr((LetExpr)t1, (LetExpr)t2); 1066 case JCTree.POS: 1067 case JCTree.NEG: 1068 case JCTree.NOT: 1069 case JCTree.COMPL: 1070 case JCTree.PREINC: 1071 case JCTree.PREDEC: 1072 case JCTree.POSTINC: 1073 case JCTree.POSTDEC: 1074 case JCTree.NULLCHK: 1075 return matchUnary((JCUnary)t1, (JCUnary)t2); 1076 case JCTree.OR: 1077 case JCTree.AND: 1078 case JCTree.BITOR: 1079 case JCTree.BITXOR: 1080 case JCTree.BITAND: 1081 case JCTree.EQ: 1082 case JCTree.NE: 1083 case JCTree.LT: 1084 case JCTree.GT: 1085 case JCTree.LE: 1086 case JCTree.GE: 1087 case JCTree.SL: 1088 case JCTree.SR: 1089 case JCTree.USR: 1090 case JCTree.PLUS: 1091 case JCTree.MINUS: 1092 case JCTree.MUL: 1093 case JCTree.DIV: 1094 case JCTree.MOD: 1095 return matchBinary((JCBinary)t1, (JCBinary)t2); 1096 case JCTree.BITOR_ASG: 1097 case JCTree.BITXOR_ASG: 1098 case JCTree.BITAND_ASG: 1099 case JCTree.SL_ASG: 1100 case JCTree.SR_ASG: 1101 case JCTree.USR_ASG: 1102 case JCTree.PLUS_ASG: 1103 case JCTree.MINUS_ASG: 1104 case JCTree.MUL_ASG: 1105 case JCTree.DIV_ASG: 1106 case JCTree.MOD_ASG: 1107 return matchAssignop((JCAssignOp)t1, (JCAssignOp)t2); 1108 default: 1109 String msg = ((com.sun.source.tree.Tree)t1).getKind().toString() + 1110 " " + t1.getClass().getName(); 1111 throw new AssertionError (msg); 1112 } 1113 } 1114 1115 protected boolean nameChanged(Name oldName, Name newName) { 1116 if (oldName == newName) 1117 return false; 1118 byte[] arr1 = oldName.toUtf(); 1119 byte[] arr2 = newName.toUtf(); 1120 int len = arr1.length; 1121 if (len != arr2.length) 1122 return true; 1123 for (int i = 0; i < len; i++) 1124 if (arr1[i] != arr2[i]) 1125 return true; 1126 return false; 1127 } 1128 1129 1132 protected void diffList(List<? extends JCTree> oldList, 1133 List<? extends JCTree> newList, 1134 LineInsertionType newLine, int insertHint) { 1135 diffList(oldList, newList, newLine, insertHint, null); 1136 } 1137 1138 1142 protected void diffList(List<? extends JCTree> oldList, 1143 List<? extends JCTree> newList, 1144 LineInsertionType newLine, int insertHint, Name owningClassName) { 1145 if (oldList == newList) 1146 return; 1147 assert oldList != null && newList != null; 1148 int lastOldPos = insertHint; 1149 Iterator <? extends JCTree> oldIter = oldList.iterator(); 1150 Iterator <? extends JCTree> newIter = newList.iterator(); 1151 JCTree oldT = safeNext(oldIter); 1152 JCTree newT = safeNext(newIter); 1153 while (oldT != null && newT != null) { 1154 if (oldTopLevel != null) { 1155 int endPos = model.getEndPos(oldT, oldTopLevel); 1156 1157 if (endPos != Position.NOPOS) 1158 lastOldPos = endPos; 1159 } 1160 if (treesMatch(oldT, newT, false)) { 1161 diffTree(oldT, newT); 1162 oldT = safeNext(oldIter); 1163 newT = safeNext(newIter); 1164 } 1165 else if (!listContains(newList, oldT) && !listContains(oldList, newT)) { 1166 append(Diff.modify(oldT, getOldPos(oldT), newT)); 1167 oldT = safeNext(oldIter); 1168 newT = safeNext(newIter); 1169 } 1170 else if (!listContains(newList, oldT)) { 1171 if (!isHidden(oldT, oldParent)) 1172 append(Diff.delete(oldT, getOldPos(oldT))); 1173 oldT = safeNext(oldIter); 1174 } 1175 else { 1176 if (!isHidden(newT, newParent)) 1177 append(Diff.insert(newT, getOldPos(oldT), newLine, owningClassName)); 1178 newT = safeNext(newIter); 1179 } 1180 } 1181 while (oldT != null) { 1182 if (!isHidden(oldT, oldParent)) 1183 append(Diff.delete(oldT, getOldPos(oldT))); 1184 if (oldTopLevel != null) 1185 lastOldPos = model.getEndPos(oldT, oldTopLevel); 1186 oldT = safeNext(oldIter); 1187 } 1188 while (newT != null) { 1189 if (!isHidden(newT, newParent)) 1190 append(Diff.insert(newT, lastOldPos, newLine, owningClassName)); 1191 newT = safeNext(newIter); 1192 } 1193 } 1194 1195 private JCTree safeNext(Iterator <? extends JCTree> iter) { 1196 return iter.hasNext() ? iter.next() : null; 1197 } 1198 1199 protected void diffParameterList(List<? extends JCTree> oldList, List<? extends JCTree> newList) { 1202 if (oldList == newList) 1203 return; 1204 assert oldList != null && newList != null; 1205 int lastOldPos = Query.NOPOS; 1206 Iterator <? extends JCTree> oldIter = oldList.iterator(); 1207 Iterator <? extends JCTree> newIter = newList.iterator(); 1208 while (oldIter.hasNext() && newIter.hasNext()) { 1209 JCTree oldT = oldIter.next(); 1210 diffTree(oldT, newIter.next()); 1211 if (oldTopLevel != null) 1212 lastOldPos = model.getEndPos(oldT, oldTopLevel); 1213 } 1214 while (oldIter.hasNext()) { 1215 JCTree oldT = oldIter.next(); 1216 append(Diff.delete(oldT, getOldPos(oldT))); 1217 } 1218 while (newIter.hasNext()) { 1219 append(Diff.insert(newIter.next(), lastOldPos, LineInsertionType.BEFORE)); 1220 } 1221 } 1222 1223 1226 protected void diffList2( 1227 List<? extends JCTree> oldList, List<? extends JCTree> newList, 1228 int initialPos, PositionEstimator estimator) 1229 { 1230 if (oldList == newList) 1231 return; 1232 assert oldList != null && newList != null; 1233 int lastOldPos = initialPos; 1234 1235 ListMatcher<JCTree> matcher = ListMatcher.<JCTree>instance( 1236 (List<JCTree>) oldList, 1237 (List<JCTree>) newList 1238 ); 1239 if (!matcher.match()) { 1240 return; 1241 } 1242 Iterator <? extends JCTree> oldIter = oldList.iterator(); 1243 ResultItem<JCTree>[] result = matcher.getTransformedResult(); 1244 Separator s = matcher.separatorInstance(); 1245 s.compute(); 1246 int[][] matrix = estimator.getMatrix(); 1247 int testPos = initialPos; 1248 int i = 0; 1249 for (int j = 0; j < result.length; j++) { 1250 JCTree oldT; 1251 ResultItem<JCTree> item = result[j]; 1252 switch (item.operation) { 1253 case MODIFY: { 1254 tokenSequence.moveIndex(matrix[i][4]); 1255 if (tokenSequence.moveNext()) { 1256 testPos = tokenSequence.offset(); 1257 if (JavaTokenId.COMMA == tokenSequence.token().id()) 1258 testPos += JavaTokenId.COMMA.fixedText().length(); 1259 } 1260 oldT = oldIter.next(); ++i; 1261 append(Diff.modify("", lastOldPos, oldT, item.element, "", ListType.PARAMETER)); 1262 lastOldPos = endPos(oldT); 1263 break; 1264 } 1265 case INSERT: { 1266 String prec = s.head(j) ? estimator.head() : s.prev(j) ? estimator.sep() : null; 1267 String tail = s.next(j) ? estimator.sep() : null; 1268 if (estimator.getIndentString() != null && !estimator.getIndentString().equals(" ")) { 1269 prec += estimator.getIndentString(); 1270 } 1271 append(Diff.insert(testPos, prec, item.element, tail, LineInsertionType.NONE)); 1272 break; 1273 } 1274 case DELETE: { 1275 1280 int delta = 0; 1284 if (i == 0 && matrix[i+1][2] != -1 && matrix[i+1][2] == matrix[i+1][3]) { 1285 ++delta; 1286 } 1287 int startOffset = toOff(s.head(j) || s.prev(j) ? matrix[i][1] : matrix[i][2+delta]); 1288 int endOffset = toOff(s.tail(j) || s.next(j) ? matrix[i+1][2] : matrix[i][4]); 1289 assert startOffset != -1 && endOffset != -1 : "Invalid offset!"; 1290 append(Diff.delete(startOffset, endOffset)); 1291 tokenSequence.moveIndex(matrix[i][4]); 1292 if (tokenSequence.moveNext()) { 1293 testPos = tokenSequence.offset(); 1294 if (JavaTokenId.COMMA == tokenSequence.token().id()) 1295 testPos += JavaTokenId.COMMA.fixedText().length(); 1296 } 1297 oldT = oldIter.next(); ++i; 1298 lastOldPos = endPos(item.element); 1299 break; 1300 } 1301 case NOCHANGE: { 1302 tokenSequence.moveIndex(matrix[i][4]); 1303 if (tokenSequence.moveNext()) { 1304 testPos = tokenSequence.offset(); 1305 if (JavaTokenId.COMMA == tokenSequence.token().id()) 1306 testPos += JavaTokenId.COMMA.fixedText().length(); 1307 } 1308 oldT = oldIter.next(); ++i; 1309 lastOldPos = endPos(oldT); 1310 break; 1311 } 1312 } 1313 } 1314 } 1315 1316 private int toOff(int tokenIndex) { 1317 if (tokenIndex == -1) { 1318 return -1; 1319 } 1320 tokenSequence.moveIndex(tokenIndex); 1321 return tokenSequence.offset(); 1322 } 1323 1324 1327 protected void diffParameterList(List<? extends JCTree> oldList, 1328 List<? extends JCTree> newList, 1329 int where, ListType type) 1330 { 1331 if (oldList == newList) 1332 return; 1333 assert oldList != null && newList != null; 1334 int lastOldPos = where; 1335 1336 ListMatcher<JCExpression> matcher = ListMatcher.<JCExpression>instance( 1337 (List<JCExpression>) oldList, 1338 (List<JCExpression>) newList 1339 ); 1340 if (!matcher.match()) { 1341 return; 1342 } 1343 Iterator <? extends JCTree> oldIter = oldList.iterator(); 1344 ResultItem<JCExpression>[] result = matcher.getTransformedResult(); 1345 Separator s = matcher.separatorInstance(); 1346 s.compute(); 1347 for (int j = 0; j < result.length; j++) { 1348 JCTree oldT; 1349 ResultItem<JCExpression> item = result[j]; 1350 switch (item.operation) { 1351 case MODIFY: 1352 oldT = oldIter.next(); 1353 append(Diff.modify("", lastOldPos, oldT, item.element, "", ListType.PARAMETER)); 1354 lastOldPos = endPos(oldT); 1355 break; 1356 case INSERT: { 1357 String prec = s.head(j) ? type.head() : s.prev(j) ? type.sep() : null; 1358 String tail = s.tail(j) ? type.tail() : s.next(j) ? type.sep() : null; 1359 int pos = lastOldPos; 1367 if (oldIter.hasNext() && lastOldPos != where) { 1368 pos = TokenUtilities.moveFwdToToken(tokenSequence, lastOldPos, type.sep); 1369 if (pos > 0) { 1370 pos += type.sep.fixedText().length(); 1371 } 1372 } 1373 append(Diff.insert(prec, item.element, pos, tail, ListType.PARAMETER)); 1374 break; 1375 } 1376 case DELETE: { 1377 String prec = s.head(j) ? type.headToken() : s.prev(j) ? type.sepToken() : null; 1380 String tail = s.tail(j) ? type.tailToken() : s.next(j) ? type.sepToken() : null; 1381 append(Diff.delete(prec, item.element, lastOldPos, tail)); 1382 oldT = oldIter.next(); 1383 lastOldPos = endPos(item.element); 1384 break; 1385 } 1386 case NOCHANGE: 1387 oldT = oldIter.next(); 1388 lastOldPos = endPos(oldT); 1389 break; 1390 } 1391 } 1392 } 1393 1394 1398 protected void diffList( 1399 List<? extends JCTree> oldList, 1400 List<? extends JCTree> newList, 1401 int initialPos, 1402 PositionEstimator estimator, 1403 Measure measure) 1404 { 1405 diffList(oldList, newList, initialPos, estimator, measure, null); 1406 } 1407 1408 protected void diffList( 1409 List<? extends JCTree> oldList, 1410 List<? extends JCTree> newList, 1411 int initialPos, 1412 PositionEstimator estimator, 1413 Measure measure, 1414 Name owningClassName) 1415 { 1416 if (oldList == newList) 1417 return; 1418 assert oldList != null && newList != null; 1419 1420 ListMatcher<JCExpression> matcher = ListMatcher.<JCExpression>instance( 1421 (List<JCExpression>) oldList, 1422 (List<JCExpression>) newList, 1423 measure 1424 ); 1425 if (!matcher.match()) { 1426 return; 1427 } 1428 Iterator <? extends JCTree> oldIter = oldList.iterator(); 1429 ResultItem<JCExpression>[] result = matcher.getTransformedResult(); 1430 int posHint = initialPos; 1431 int i = 0; 1432 for (int j = 0; j < result.length; j++) { 1433 JCTree oldT = null; 1434 ResultItem<JCExpression> item = result[j]; 1435 switch (item.operation) { 1436 case MODIFY: 1437 oldT = oldIter.next(); 1438 if (treesMatch(oldT, item.element, false)) { 1439 diffTree(oldT, item.element); 1440 } else { 1441 append(Diff.modify(oldT, posHint, item.element)); 1442 } 1443 posHint = estimator.getPositions(i)[1]; 1444 ++i; 1445 break; 1446 case INSERT: { 1447 int pos = estimator.getInsertPos(i); 1448 if (pos < 0 && oldList.isEmpty() && i == 0) { 1451 pos = initialPos; 1452 StringBuilder aHead = new StringBuilder (), aTail = new StringBuilder (); 1453 pos = estimator.prepare(initialPos, aHead, aTail); 1454 String tail = null; 1455 if (j+1 == result.length) { 1456 tail = aTail.toString(); 1457 } 1458 append(Diff.insert(pos, aHead.toString(), item.element, tail, estimator.lineInsertType(), owningClassName)); 1459 } else { 1460 append(Diff.insert(item.element, pos, estimator.lineInsertType(), owningClassName)); 1461 } 1462 break; 1463 } 1464 case DELETE: { 1465 oldT = oldIter.next(); 1466 int[] pos = estimator.getPositions(i); 1467 ++i; 1468 posHint = pos[1]; 1469 append(Diff.delete(pos[0], pos[1])); 1470 break; 1471 } 1472 case NOCHANGE: 1473 oldT = oldIter.next(); 1474 posHint = estimator.getPositions(i)[1]; 1475 ++i; 1476 break; 1477 } 1478 } 1479 } 1480 1481 private List filterHidden(List<JCTree> list) { 1482 List<JCTree> result = new ArrayList <JCTree>(); for (JCTree tree : list) { 1484 if (Kind.METHOD == tree.getKind()) { 1485 CharSequence name = ((MethodTree) tree).getName(); 1486 if ("<init>".contentEquals(name) && tree.pos == oldParent.pos) 1487 continue; 1488 } 1489 result.add(tree); 1490 } 1491 return result; 1492 } 1493 1494 private boolean isHidden(JCTree t, JCTree parent) { 1495 if (parent == null) 1496 return false; 1497 if (t.pos == Query.NOPOS) 1500 return true; 1501 return model.isSynthetic(t); 1502 } 1503 1504 protected void diffPrecedingComments(JCTree oldT, JCTree newT) { 1505 CommentSet cs = comments.getComments(newT); 1506 if (!cs.hasChanges()) 1507 return; 1508 List<Comment> oldComments = comments.getComments(oldT).getPrecedingComments(); 1509 List<Comment> newComments = cs.getPrecedingComments(); 1510 diffCommentLists(oldT, newT, oldComments, newComments, false); 1511 } 1512 1513 protected void diffTrailingComments(JCTree oldT, JCTree newT) { 1514 CommentSet cs = comments.getComments(newT); 1515 if (!cs.hasChanges()) 1516 return; 1517 List<Comment> oldComments = comments.getComments(oldT).getTrailingComments(); 1518 List<Comment> newComments = cs.getTrailingComments(); 1519 diffCommentLists(oldT, newT, oldComments, newComments, true); 1520 } 1521 1522 private void diffCommentLists(JCTree oldT, JCTree newT, List<Comment>oldList, 1523 List<Comment>newList, boolean trailing) { 1524 int lastPos = getOldPos(oldT); 1525 Iterator <Comment> oldIter = oldList.iterator(); 1526 Iterator <Comment> newIter = newList.iterator(); 1527 Comment oldC = safeNext(oldIter); 1528 Comment newC = safeNext(newIter); 1529 while (oldC != null && newC != null) { 1530 lastPos = oldC.pos(); 1531 if (commentsMatch(oldC, newC)) { 1532 oldC = safeNext(oldIter); 1533 newC = safeNext(newIter); 1534 } 1535 else if (!listContains(newList, oldC)) { 1536 if (!listContains(oldList, newC)) { 1537 append(Diff.modify(oldT, newT, oldC, newC)); 1538 oldC = safeNext(oldIter); 1539 newC = safeNext(newIter); 1540 } else { 1541 append(Diff.delete(oldT, newT, oldC)); 1542 oldC = safeNext(oldIter); 1543 } 1544 } 1545 else { 1546 append(Diff.insert(lastPos, LineInsertionType.BEFORE, oldT, newT, newC, trailing)); 1547 newC = safeNext(newIter); 1548 } 1549 } 1550 while (oldC != null) { 1551 append(Diff.delete(oldT, newT, oldC)); 1552 oldC = safeNext(oldIter); 1553 } 1554 while (newC != null) { 1555 append(Diff.insert(lastPos, LineInsertionType.BEFORE, oldT, newT, newC, trailing)); 1556 lastPos += newC.endPos() - newC.pos(); 1557 newC = safeNext(oldIter); 1558 } 1559 } 1560 1561 private Comment safeNext(Iterator <Comment> iter) { 1562 return iter.hasNext() ? iter.next() : null; 1563 } 1564 1565 private boolean commentsMatch(Comment oldC, Comment newC) { 1566 if (oldC == null && newC == null) 1567 return true; 1568 if (oldC == null || newC == null) 1569 return false; 1570 return oldC.equals(newC); 1571 } 1572 1573 private boolean listContains(List<Comment>list, Comment comment) { 1574 for (Comment c : list) 1575 if (c.equals(comment)) 1576 return true; 1577 return false; 1578 } 1579 1580 private static JCTree leftMostTree(JCTree tree) { 1582 switch (tree.tag) { 1583 case(JCTree.APPLY): 1584 return leftMostTree(((JCMethodInvocation)tree).meth); 1585 case(JCTree.ASSIGN): 1586 return leftMostTree(((JCAssign)tree).lhs); 1587 case(JCTree.BITOR_ASG): case(JCTree.BITXOR_ASG): case(JCTree.BITAND_ASG): 1588 case(JCTree.SL_ASG): case(JCTree.SR_ASG): case(JCTree.USR_ASG): 1589 case(JCTree.PLUS_ASG): case(JCTree.MINUS_ASG): case(JCTree.MUL_ASG): 1590 case(JCTree.DIV_ASG): case(JCTree.MOD_ASG): 1591 return leftMostTree(((JCAssignOp)tree).lhs); 1592 case(JCTree.OR): case(JCTree.AND): case(JCTree.BITOR): 1593 case(JCTree.BITXOR): case(JCTree.BITAND): case(JCTree.EQ): 1594 case(JCTree.NE): case(JCTree.LT): case(JCTree.GT): 1595 case(JCTree.LE): case(JCTree.GE): case(JCTree.SL): 1596 case(JCTree.SR): case(JCTree.USR): case(JCTree.PLUS): 1597 case(JCTree.MINUS): case(JCTree.MUL): case(JCTree.DIV): 1598 case(JCTree.MOD): 1599 return leftMostTree(((JCBinary)tree).lhs); 1600 case(JCTree.CLASSDEF): { 1601 JCClassDecl node = (JCClassDecl)tree; 1602 if (node.mods.pos != Position.NOPOS) 1603 return node.mods; 1604 break; 1605 } 1606 case(JCTree.CONDEXPR): 1607 return leftMostTree(((JCConditional)tree).cond); 1608 case(JCTree.EXEC): 1609 return leftMostTree(((JCExpressionStatement)tree).expr); 1610 case(JCTree.INDEXED): 1611 return leftMostTree(((JCArrayAccess)tree).indexed); 1612 case(JCTree.METHODDEF): { 1613 JCMethodDecl node = (JCMethodDecl)tree; 1614 if (node.mods.pos != Position.NOPOS) 1615 return node.mods; 1616 if (node.restype != null) return leftMostTree(node.restype); 1618 return node; 1619 } 1620 case(JCTree.SELECT): 1621 return leftMostTree(((JCFieldAccess)tree).selected); 1622 case(JCTree.TYPEAPPLY): 1623 return leftMostTree(((JCTypeApply)tree).clazz); 1624 case(JCTree.TYPEARRAY): 1625 return leftMostTree(((JCArrayTypeTree)tree).elemtype); 1626 case(JCTree.TYPETEST): 1627 return leftMostTree(((JCInstanceOf)tree).expr); 1628 case(JCTree.POSTINC): 1629 case(JCTree.POSTDEC): 1630 return leftMostTree(((JCUnary)tree).arg); 1631 case(JCTree.VARDEF): { 1632 JCVariableDecl node = (JCVariableDecl)tree; 1633 if (node.mods.pos != Position.NOPOS) 1634 return node.mods; 1635 return leftMostTree(node.vartype); 1636 } 1637 case(JCTree.TOPLEVEL): { 1638 JCCompilationUnit node = (JCCompilationUnit)tree; 1639 assert node.defs.size() > 0; 1640 return node.pid != null ? node.pid : node.defs.head; 1641 } 1642 } 1643 return tree; 1644 } 1645 1646 private int getOldPos(JCTree oldT) { 1647 return getOldPos(oldT, model, undo); 1648 } 1649 1650 static int getOldPos(JCTree oldT, ASTModel model, UndoList undo) { 1651 int oldPos = model.getStartPos(oldT); 1652 if (oldPos == Query.NOPOS) { 1653 JCTree t = (JCTree)undo.getOld(leftMostTree(oldT)); 1655 if (t != null && t != oldT) 1656 oldPos = getOldPos(t, model, undo); 1658 } 1659 if (oldPos == Query.NOPOS) 1660 oldPos = oldT.pos == Query.NOPOS ? leftMostTree(oldT).pos : oldT.pos; 1661 return oldPos; 1662 } 1663 1664 1673 protected void diffTree(JCTree oldT, JCTree newT) { 1674 if (oldT == null && newT != null) 1675 throw new IllegalArgumentException ("Null is not allowed in parameters."); 1676 1677 diffTree(oldT, newT, Position.NOPOS, null); 1678 } 1679 1680 private void diffTree(JCTree oldT, JCTree newT, int startPos, String head) { 1681 if (oldT == newT) 1682 return; 1683 diffPrecedingComments(oldT, newT); 1684 1685 if (oldT == null) { 1686 append(Diff.insert(startPos, head, newT, "", LineInsertionType.NONE)); 1687 return; 1688 } 1689 int oldPos = getOldPos(oldT); 1690 1691 if (newT == null) { 1692 if (startPos == Position.NOPOS) 1696 append(Diff.delete(oldT, oldPos)); 1697 else 1698 append(Diff.delete(startPos, endPos(oldT))); 1699 return; 1700 } 1701 1702 if ((oldT.tag != JCTree.TOPLEVEL && oldT.tag != JCTree.METHODDEF && oldT.tag != JCTree.CLASSDEF && oldT.tag != JCTree.VARDEF) && 1703 (oldT.tag != newT.tag || newT.pos == Query.NOPOS || oldT.type != newT.type)) { 1704 append(Diff.modify(oldT, oldPos, newT)); 1705 return; 1706 } 1707 1708 switch (oldT.tag) { 1709 case JCTree.TOPLEVEL: 1710 diffTopLevel((JCCompilationUnit)oldT, (JCCompilationUnit)newT); 1711 break; 1712 case JCTree.IMPORT: 1713 diffImport((JCImport)oldT, (JCImport)newT); 1714 break; 1715 case JCTree.CLASSDEF: 1716 diffClassDef((JCClassDecl)oldT, (JCClassDecl)newT); 1717 break; 1718 case JCTree.METHODDEF: 1719 diffMethodDef((JCMethodDecl)oldT, (JCMethodDecl)newT); 1720 break; 1721 case JCTree.VARDEF: 1722 diffVarDef((JCVariableDecl)oldT, (JCVariableDecl)newT); 1723 break; 1724 case JCTree.SKIP: 1725 break; 1726 case JCTree.BLOCK: 1727 diffBlock((JCBlock)oldT, (JCBlock)newT); 1728 break; 1729 case JCTree.DOLOOP: 1730 diffDoLoop((JCDoWhileLoop)oldT, (JCDoWhileLoop)newT); 1731 break; 1732 case JCTree.WHILELOOP: 1733 diffWhileLoop((JCWhileLoop)oldT, (JCWhileLoop)newT); 1734 break; 1735 case JCTree.FORLOOP: 1736 diffForLoop((JCForLoop)oldT, (JCForLoop)newT); 1737 break; 1738 case JCTree.FOREACHLOOP: 1739 diffForeachLoop((JCEnhancedForLoop)oldT, (JCEnhancedForLoop)newT); 1740 break; 1741 case JCTree.LABELLED: 1742 diffLabelled((JCLabeledStatement)oldT, (JCLabeledStatement)newT); 1743 break; 1744 case JCTree.SWITCH: 1745 diffSwitch((JCSwitch)oldT, (JCSwitch)newT); 1746 break; 1747 case JCTree.CASE: 1748 diffCase((JCCase)oldT, (JCCase)newT); 1749 break; 1750 case JCTree.SYNCHRONIZED: 1751 diffSynchronized((JCSynchronized)oldT, (JCSynchronized)newT); 1752 break; 1753 case JCTree.TRY: 1754 diffTry((JCTry)oldT, (JCTry)newT); 1755 break; 1756 case JCTree.CATCH: 1757 diffCatch((JCCatch)oldT, (JCCatch)newT); 1758 break; 1759 case JCTree.CONDEXPR: 1760 diffConditional((JCConditional)oldT, (JCConditional)newT); 1761 break; 1762 case JCTree.IF: 1763 diffIf((JCIf)oldT, (JCIf)newT); 1764 break; 1765 case JCTree.EXEC: 1766 diffExec((JCExpressionStatement)oldT, (JCExpressionStatement)newT); 1767 break; 1768 case JCTree.BREAK: 1769 diffBreak((JCBreak)oldT, (JCBreak)newT); 1770 break; 1771 case JCTree.CONTINUE: 1772 diffContinue((JCContinue)oldT, (JCContinue)newT); 1773 break; 1774 case JCTree.RETURN: 1775 diffReturn((JCReturn)oldT, (JCReturn)newT); 1776 break; 1777 case JCTree.THROW: 1778 diffThrow((JCThrow)oldT, (JCThrow)newT); 1779 break; 1780 case JCTree.ASSERT: 1781 diffAssert((JCAssert)oldT, (JCAssert)newT); 1782 break; 1783 case JCTree.APPLY: 1784 diffApply((JCMethodInvocation)oldT, (JCMethodInvocation)newT); 1785 break; 1786 case JCTree.NEWCLASS: 1787 diffNewClass((JCNewClass)oldT, (JCNewClass)newT); 1788 break; 1789 case JCTree.NEWARRAY: 1790 diffNewArray((JCNewArray)oldT, (JCNewArray)newT); 1791 break; 1792 case JCTree.PARENS: 1793 diffParens((JCParens)oldT, (JCParens)newT); 1794 break; 1795 case JCTree.ASSIGN: 1796 diffAssign((JCAssign)oldT, (JCAssign)newT); 1797 break; 1798 case JCTree.TYPECAST: 1799 diffTypeCast((JCTypeCast)oldT, (JCTypeCast)newT); 1800 break; 1801 case JCTree.TYPETEST: 1802 diffTypeTest((JCInstanceOf)oldT, (JCInstanceOf)newT); 1803 break; 1804 case JCTree.INDEXED: 1805 diffIndexed((JCArrayAccess)oldT, (JCArrayAccess)newT); 1806 break; 1807 case JCTree.SELECT: 1808 diffSelect((JCFieldAccess)oldT, (JCFieldAccess)newT); 1809 break; 1810 case JCTree.IDENT: 1811 diffIdent((JCIdent)oldT, (JCIdent)newT); 1812 break; 1813 case JCTree.LITERAL: 1814 diffLiteral((JCLiteral)oldT, (JCLiteral)newT); 1815 break; 1816 case JCTree.TYPEIDENT: 1817 diffTypeIdent((JCPrimitiveTypeTree)oldT, (JCPrimitiveTypeTree)newT); 1818 break; 1819 case JCTree.TYPEARRAY: 1820 diffTypeArray((JCArrayTypeTree)oldT, (JCArrayTypeTree)newT); 1821 break; 1822 case JCTree.TYPEAPPLY: 1823 diffTypeApply((JCTypeApply)oldT, (JCTypeApply)newT); 1824 break; 1825 case JCTree.TYPEPARAMETER: 1826 diffTypeParameter((JCTypeParameter)oldT, (JCTypeParameter)newT); 1827 break; 1828 case JCTree.WILDCARD: 1829 diffWildcard((JCWildcard)oldT, (JCWildcard)newT); 1830 break; 1831 case JCTree.TYPEBOUNDKIND: 1832 diffTypeBoundKind((TypeBoundKind)oldT, (TypeBoundKind)newT); 1833 break; 1834 case JCTree.ANNOTATION: 1835 diffAnnotation((JCAnnotation)oldT, (JCAnnotation)newT); 1836 break; 1837 case JCTree.LETEXPR: 1838 diffLetExpr((LetExpr)oldT, (LetExpr)newT); 1839 break; 1840 case JCTree.POS: 1841 case JCTree.NEG: 1842 case JCTree.NOT: 1843 case JCTree.COMPL: 1844 case JCTree.PREINC: 1845 case JCTree.PREDEC: 1846 case JCTree.POSTINC: 1847 case JCTree.POSTDEC: 1848 case JCTree.NULLCHK: 1849 diffUnary((JCUnary)oldT, (JCUnary)newT); 1850 break; 1851 case JCTree.OR: 1852 case JCTree.AND: 1853 case JCTree.BITOR: 1854 case JCTree.BITXOR: 1855 case JCTree.BITAND: 1856 case JCTree.EQ: 1857 case JCTree.NE: 1858 case JCTree.LT: 1859 case JCTree.GT: 1860 case JCTree.LE: 1861 case JCTree.GE: 1862 case JCTree.SL: 1863 case JCTree.SR: 1864 case JCTree.USR: 1865 case JCTree.PLUS: 1866 case JCTree.MINUS: 1867 case JCTree.MUL: 1868 case JCTree.DIV: 1869 case JCTree.MOD: 1870 diffBinary((JCBinary)oldT, (JCBinary)newT); 1871 break; 1872 case JCTree.BITOR_ASG: 1873 case JCTree.BITXOR_ASG: 1874 case JCTree.BITAND_ASG: 1875 case JCTree.SL_ASG: 1876 case JCTree.SR_ASG: 1877 case JCTree.USR_ASG: 1878 case JCTree.PLUS_ASG: 1879 case JCTree.MINUS_ASG: 1880 case JCTree.MUL_ASG: 1881 case JCTree.DIV_ASG: 1882 case JCTree.MOD_ASG: 1883 diffAssignop((JCAssignOp)oldT, (JCAssignOp)newT); 1884 break; 1885 case JCTree.ERRONEOUS: 1886 diffErroneous((JCErroneous)oldT, (JCErroneous)newT); 1887 break; 1888 default: 1889 String msg = "Diff not implemented: " + 1890 ((com.sun.source.tree.Tree)oldT).getKind().toString() + 1891 " " + oldT.getClass().getName(); 1892 throw new AssertionError (msg); 1893 } 1894 diffTrailingComments(oldT, newT); 1895 } 1896 1897 protected boolean listsMatch(List<? extends JCTree> oldList, List<? extends JCTree> newList) { 1898 if (oldList == newList) 1899 return true; 1900 int n = oldList.size(); 1901 if (newList.size() != n) 1902 return false; 1903 for (int i = 0; i < n; i++) 1904 if (!treesMatch(oldList.get(i), newList.get(i))) 1905 return false; 1906 return true; 1907 } 1908 1909 private boolean matchImport(JCImport t1, JCImport t2) { 1910 return t1.staticImport == t2.staticImport && treesMatch(t1.qualid, t2.qualid); 1911 } 1912 1913 private boolean matchBlock(JCBlock t1, JCBlock t2) { 1914 return t1.flags == t2.flags && listsMatch(t1.stats, t2.stats); 1915 } 1916 1917 private boolean matchDoLoop(JCDoWhileLoop t1, JCDoWhileLoop t2) { 1918 return treesMatch(t1.cond, t2.cond) && treesMatch(t1.body, t2.body); 1919 } 1920 1921 private boolean matchWhileLoop(JCWhileLoop t1, JCWhileLoop t2) { 1922 return treesMatch(t1.cond, t2.cond) && treesMatch(t1.body, t2.body); 1923 } 1924 1925 private boolean matchForLoop(JCForLoop t1, JCForLoop t2) { 1926 return listsMatch(t1.init, t2.init) && treesMatch(t1.cond, t2.cond) && 1927 listsMatch(t1.step, t2.step) && treesMatch(t1.body, t2.body); 1928 } 1929 1930 private boolean matchForeachLoop(JCEnhancedForLoop t1, JCEnhancedForLoop t2) { 1931 return treesMatch(t1.var, t2.var) && treesMatch(t1.expr, t2.expr) && 1932 treesMatch(t1.body, t2.body); 1933 } 1934 1935 private boolean matchLabelled(JCLabeledStatement t1, JCLabeledStatement t2) { 1936 return t1.label == t2.label && treesMatch(t1.body, t2.body); 1937 } 1938 1939 private boolean matchSwitch(JCSwitch t1, JCSwitch t2) { 1940 return treesMatch(t1.selector, t2.selector) && listsMatch(t1.cases, t2.cases); 1941 } 1942 1943 private boolean matchCase(JCCase t1, JCCase t2) { 1944 return treesMatch(t1.pat, t2.pat) && listsMatch(t1.stats, t2.stats); 1945 } 1946 1947 private boolean matchSynchronized(JCSynchronized t1, JCSynchronized t2) { 1948 return treesMatch(t1.lock, t2.lock) && treesMatch(t1.body, t2.body); 1949 } 1950 1951 private boolean matchTry(JCTry t1, JCTry t2) { 1952 return treesMatch(t1.finalizer, t2.finalizer) && 1953 listsMatch(t1.catchers, t2.catchers) && 1954 treesMatch(t1.body, t2.body); 1955 } 1956 1957 private boolean matchCatch(JCCatch t1, JCCatch t2) { 1958 return treesMatch(t1.param, t2.param) && treesMatch(t1.body, t2.body); 1959 } 1960 1961 private boolean matchConditional(JCConditional t1, JCConditional t2) { 1962 return treesMatch(t1.cond, t2.cond) && treesMatch(t1.truepart, t2.truepart) && 1963 treesMatch(t1.falsepart, t2.falsepart); 1964 } 1965 1966 private boolean matchIf(JCIf t1, JCIf t2) { 1967 return treesMatch(t1.cond, t2.cond) && treesMatch(t1.thenpart, t2.thenpart) && 1968 treesMatch(t1.elsepart, t2.elsepart); 1969 } 1970 1971 private boolean matchBreak(JCBreak t1, JCBreak t2) { 1972 return t1.label == t2.label && treesMatch(t1.target, t2.target); 1973 } 1974 1975 private boolean matchContinue(JCContinue t1, JCContinue t2) { 1976 return t1.label == t2.label && treesMatch(t1.target, t2.target); 1977 } 1978 1979 private boolean matchAssert(JCAssert t1, JCAssert t2) { 1980 return treesMatch(t1.cond, t2.cond) && treesMatch(t1.detail, t2.detail); 1981 } 1982 1983 private boolean matchApply(JCMethodInvocation t1, JCMethodInvocation t2) { 1984 return t1.varargsElement == t2.varargsElement && 1985 listsMatch(t1.typeargs, t2.typeargs) && 1986 treesMatch(t1.meth, t2.meth) && 1987 listsMatch(t1.args, t2.args); 1988 } 1989 1990 private boolean matchNewClass(JCNewClass t1, JCNewClass t2) { 1991 return t1.constructor == t2.constructor && 1992 listsMatch(t1.typeargs, t2.typeargs) && 1993 listsMatch(t1.args, t2.args) && 1994 t1.varargsElement == t2.varargsElement; 1995 } 1996 1997 private boolean matchNewArray(JCNewArray t1, JCNewArray t2) { 1998 return treesMatch(t1.elemtype, t2.elemtype) && 1999 listsMatch(t1.dims, t2.dims) && listsMatch(t1.elems, t2.elems); 2000 } 2001 2002 private boolean matchAssign(JCAssign t1, JCAssign t2) { 2003 return treesMatch(t1.lhs, t2.lhs) && treesMatch(t1.rhs, t2.rhs); 2004 } 2005 2006 private boolean matchAssignop(JCAssignOp t1, JCAssignOp t2) { 2007 return t1.operator == t2.operator && 2008 treesMatch(t1.lhs, t2.lhs) && treesMatch(t1.rhs, t2.rhs); 2009 } 2010 2011 private boolean matchUnary(JCUnary t1, JCUnary t2) { 2012 return t1.operator == t2.operator && treesMatch(t1.arg, t2.arg); 2013 } 2014 2015 private boolean matchBinary(JCBinary t1, JCBinary t2) { 2016 return t1.operator == t2.operator && 2017 treesMatch(t1.lhs, t2.lhs) && treesMatch(t1.rhs, t2.rhs); 2018 } 2019 2020 private boolean matchTypeCast(JCTypeCast t1, JCTypeCast t2) { 2021 return treesMatch(t1.clazz, t2.clazz) && treesMatch(t1.expr, t2.expr); 2022 } 2023 2024 private boolean matchTypeTest(JCInstanceOf t1, JCInstanceOf t2) { 2025 return treesMatch(t1.clazz, t2.clazz) && treesMatch(t1.expr, t2.expr); 2026 } 2027 2028 private boolean matchIndexed(JCArrayAccess t1, JCArrayAccess t2) { 2029 return treesMatch(t1.indexed, t2.indexed) && treesMatch(t1.index, t2.index); 2030 } 2031 2032 private boolean matchLiteral(JCLiteral t1, JCLiteral t2) { 2033 return t1.typetag == t2.typetag && t1.value == t2.value; 2034 } 2035 2036 private boolean matchTypeApply(JCTypeApply t1, JCTypeApply t2) { 2037 return treesMatch(t1.clazz, t2.clazz) && 2038 listsMatch(t1.arguments, t2.arguments); 2039 } 2040 2041 private boolean matchTypeParameter(JCTypeParameter t1, JCTypeParameter t2) { 2042 return t1.name == t2.name && listsMatch(t1.bounds, t2.bounds); 2043 } 2044 2045 private boolean matchWildcard(JCWildcard t1, JCWildcard t2) { 2046 return t1.kind == t2.kind && treesMatch(t1.inner, t2.inner); 2047 } 2048 2049 private boolean matchAnnotation(JCAnnotation t1, JCAnnotation t2) { 2050 return treesMatch(t1.annotationType, t2.annotationType) && 2051 listsMatch(t1.args, t2.args); 2052 } 2053 2054 private boolean matchModifiers(JCModifiers t1, JCModifiers t2) { 2055 return t1.flags == t2.flags && listsMatch(t1.annotations, t2.annotations); 2056 } 2057 2058 private boolean matchLetExpr(LetExpr t1, LetExpr t2) { 2059 return listsMatch(t1.defs, t2.defs) && treesMatch(t1.expr, t2.expr); 2060 } 2061 2062 private void diffTreeToken(String preceding, int pos, JCTree t1, JCTree t2, String tail) { 2063 if (t1 == t2) { 2064 return; 2065 } else { 2066 append(Diff.modify(preceding, pos, t1, t2, tail, null)); 2067 } 2068 } 2069 2070 public static enum ListType { 2071 PARAMETER(null, JavaTokenId.COMMA, null, null, null, null), 2072 2073 TYPE_PARAMETER(JavaTokenId.LT, JavaTokenId.COMMA, JavaTokenId.GT, null, null, "> "); 2074 2075 public final JavaTokenId head; 2076 public final JavaTokenId sep; 2077 public final JavaTokenId tail; 2078 2079 private final String printHead; 2080 private final String printSepa; 2081 private final String printTail; 2082 2083 private ListType(JavaTokenId head, 2084 JavaTokenId separator, 2085 JavaTokenId tail, 2086 String printHead, 2087 String printSeparator, 2088 String printTail) 2089 { 2090 this.head = head; 2091 this.sep = separator; 2092 this.tail = tail; 2093 this.printHead = printHead; 2094 this.printSepa = printSeparator; 2095 this.printTail = printTail; 2096 } 2097 2098 public String head() { return p(head, printHead); } 2099 public String sep() { return p(sep, printSepa); } 2100 public String tail() { return p(tail, printTail); } 2101 2102 public String headToken() { return r(head); } 2103 public String sepToken() { return r(sep); } 2104 public String tailToken() { return r(tail); } 2105 2106 private String p(JavaTokenId token, String text) { 2107 if (text != null) { 2108 return text; 2109 } else { 2110 if (token == null) { 2111 return null; 2112 } else { 2113 return token.fixedText(); 2114 } 2115 } 2116 } 2117 2118 private String r(JavaTokenId head) { 2119 return head == null ? null : head.fixedText(); 2120 } 2121 } 2122} 2123 | Popular Tags |