1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package signature.compare; 18 19 import signature.compare.model.IAnnotationDelta; 20 import signature.compare.model.IAnnotationElementDelta; 21 import signature.compare.model.IAnnotationFieldDelta; 22 import signature.compare.model.IApiDelta; 23 import signature.compare.model.IClassDefinitionDelta; 24 import signature.compare.model.IConstructorDelta; 25 import signature.compare.model.IDelta; 26 import signature.compare.model.IEnumConstantDelta; 27 import signature.compare.model.IFieldDelta; 28 import signature.compare.model.IGenericDeclarationDelta; 29 import signature.compare.model.IMethodDelta; 30 import signature.compare.model.IModifierDelta; 31 import signature.compare.model.IPackageDelta; 32 import signature.compare.model.IParameterDelta; 33 import signature.compare.model.IParameterizedTypeDelta; 34 import signature.compare.model.IPrimitiveTypeDelta; 35 import signature.compare.model.ITypeReferenceDelta; 36 import signature.compare.model.ITypeVariableDefinitionDelta; 37 import signature.compare.model.IUpperBoundsDelta; 38 import signature.compare.model.IValueDelta; 39 import signature.compare.model.IWildcardTypeDelta; 40 import signature.compare.model.impl.SigAnnotationDelta; 41 import signature.compare.model.impl.SigAnnotationElementDelta; 42 import signature.compare.model.impl.SigAnnotationFieldDelta; 43 import signature.compare.model.impl.SigApiDelta; 44 import signature.compare.model.impl.SigArrayTypeDelta; 45 import signature.compare.model.impl.SigClassDefinitionDelta; 46 import signature.compare.model.impl.SigClassReferenceDelta; 47 import signature.compare.model.impl.SigConstructorDelta; 48 import signature.compare.model.impl.SigEnumConstantDelta; 49 import signature.compare.model.impl.SigFieldDelta; 50 import signature.compare.model.impl.SigGenericDeclarationDelta; 51 import signature.compare.model.impl.SigMethodDelta; 52 import signature.compare.model.impl.SigModifierDelta; 53 import signature.compare.model.impl.SigPackageDelta; 54 import signature.compare.model.impl.SigParameterDelta; 55 import signature.compare.model.impl.SigParameterizedTypeDelta; 56 import signature.compare.model.impl.SigPrimitiveTypeDelta; 57 import signature.compare.model.impl.SigTypeDelta; 58 import signature.compare.model.impl.SigTypeVariableDefinitionDelta; 59 import signature.compare.model.impl.SigTypeVariableReferenceDelta; 60 import signature.compare.model.impl.SigUpperBoundsDelta; 61 import signature.compare.model.impl.SigValueDelta; 62 import signature.compare.model.impl.SigWildcardTypeDelta; 63 import signature.compare.model.subst.ClassProjection; 64 import signature.compare.model.subst.ViewpointAdapter; 65 import signature.model.IAnnotation; 66 import signature.model.IAnnotationElement; 67 import signature.model.IAnnotationField; 68 import signature.model.IApi; 69 import signature.model.IArrayType; 70 import signature.model.IClassDefinition; 71 import signature.model.IClassReference; 72 import signature.model.IConstructor; 73 import signature.model.IEnumConstant; 74 import signature.model.IExecutableMember; 75 import signature.model.IField; 76 import signature.model.IGenericDeclaration; 77 import signature.model.IMethod; 78 import signature.model.IPackage; 79 import signature.model.IParameter; 80 import signature.model.IParameterizedType; 81 import signature.model.IPrimitiveType; 82 import signature.model.ITypeReference; 83 import signature.model.ITypeVariableDefinition; 84 import signature.model.ITypeVariableReference; 85 import signature.model.IWildcardType; 86 import signature.model.Kind; 87 import signature.model.Modifier; 88 import signature.model.impl.SigAnnotationElement; 89 import signature.model.impl.SigArrayType; 90 91 import java.util.Arrays; 92 import java.util.HashMap; 93 import java.util.HashSet; 94 import java.util.Iterator; 95 import java.util.LinkedList; 96 import java.util.List; 97 import java.util.Set; 98 99 /** 100 * {@code ApiComparator} takes two signature models as input and creates a delta 101 * model describing the differences between those. 102 */ 103 public class ApiComparator implements IApiComparator { 104 105 public IApiDelta compare(IApi from, IApi to) { 106 assert from.getVisibility() == to.getVisibility(); 107 108 Set<IPackage> fromPackages = from.getPackages(); 109 Set<IPackage> toPackages = to.getPackages(); 110 111 Set<IPackageDelta> packageDeltas = compareSets(fromPackages, 112 toPackages, new SigComparator<IPackage, IPackageDelta>() { 113 public IPackageDelta createChangedDelta(IPackage from, 114 IPackage to) { 115 return comparePackage(from, to); 116 } 117 118 public IPackageDelta createAddRemoveDelta(IPackage from, 119 IPackage to) { 120 return new SigPackageDelta(from, to); 121 } 122 123 public boolean considerEqualElement(IPackage from, 124 IPackage to) { 125 return from.getName().equals(to.getName()); 126 } 127 }); 128 129 SigApiDelta delta = null; 130 if (packageDeltas != null) { 131 delta = new SigApiDelta(from, to); 132 delta.setPackageDeltas(packageDeltas); 133 } 134 return delta; 135 } 136 137 private IPackageDelta comparePackage(IPackage from, IPackage to) { 138 assert from.getName().equals(to.getName()); 139 140 Set<IClassDefinition> fromClasses = from.getClasses(); 141 Set<IClassDefinition> toClasses = to.getClasses(); 142 143 Set<IClassDefinitionDelta> classDeltas = compareSets(fromClasses, 144 toClasses, 145 new SigComparator<IClassDefinition, IClassDefinitionDelta>() { 146 public boolean considerEqualElement(IClassDefinition from, 147 IClassDefinition to) { 148 return sameClassDefinition(from, to); 149 } 150 151 public IClassDefinitionDelta createChangedDelta( 152 IClassDefinition from, IClassDefinition to) { 153 return compareClass(from, to); 154 } 155 156 public IClassDefinitionDelta createAddRemoveDelta( 157 IClassDefinition from, IClassDefinition to) { 158 return new SigClassDefinitionDelta(from, to); 159 } 160 }); 161 162 SigPackageDelta delta = null; 163 if (classDeltas != null) { 164 delta = new SigPackageDelta(from, to); 165 delta.setClassDeltas(classDeltas); 166 } 167 168 // Annotations 169 Set<IAnnotationDelta> annotationDeltas = compareAnnotations(from 170 .getAnnotations(), to.getAnnotations()); 171 if (annotationDeltas != null) { 172 if (delta != null) { 173 delta = new SigPackageDelta(from, to); 174 } 175 delta.setAnnotationDeltas(annotationDeltas); 176 } 177 return delta; 178 } 179 180 private IClassDefinitionDelta compareClass(IClassDefinition from, 181 IClassDefinition to) { 182 assert from.getKind() == to.getKind(); 183 assert from.getName().equals(to.getName()); 184 assert from.getPackageName().equals(to.getPackageName()); 185 186 SigClassDefinitionDelta classDelta = null; 187 188 // modifiers 189 Set<IModifierDelta> modifierDeltas = compareModifiers(from 190 .getModifiers(), to.getModifiers()); 191 if (modifierDeltas != null) { 192 if (classDelta == null) { 193 classDelta = new SigClassDefinitionDelta(from, to); 194 } 195 classDelta.setModifierDeltas(modifierDeltas); 196 } 197 198 // super class 199 ITypeReferenceDelta<?> superTypeDelta = compareType(from 200 .getSuperClass(), to.getSuperClass(), false); 201 if (superTypeDelta != null) { 202 if (classDelta == null) { 203 classDelta = new SigClassDefinitionDelta(from, to); 204 } 205 classDelta.setSuperClassDelta(superTypeDelta); 206 } 207 208 // interfaces 209 Set<ITypeReferenceDelta<?>> interfaceDeltas = compareInterfaces(from, 210 to); 211 if (interfaceDeltas != null) { 212 if (classDelta == null) { 213 classDelta = new SigClassDefinitionDelta(from, to); 214 } 215 classDelta.setInterfaceDeltas(interfaceDeltas); 216 } 217 218 // type variables 219 Set<ITypeVariableDefinitionDelta> typeVariableDeltas = 220 compareTypeVariableSequence(from.getTypeParameters(), 221 to.getTypeParameters()); 222 if (typeVariableDeltas != null) { 223 if (classDelta == null) { 224 classDelta = new SigClassDefinitionDelta(from, to); 225 } 226 classDelta.setTypeVariableDeltas(typeVariableDeltas); 227 } 228 229 // constructors 230 Set<IConstructorDelta> constructorDeltas = compareConstructors(from 231 .getConstructors(), to.getConstructors()); 232 if (constructorDeltas != null) { 233 if (classDelta == null) { 234 classDelta = new SigClassDefinitionDelta(from, to); 235 } 236 classDelta.setConstructorDeltas(constructorDeltas); 237 } 238 239 // methods 240 Set<IMethodDelta> methodDeltas = compareMethods(from, to); 241 if (methodDeltas != null) { 242 if (classDelta == null) { 243 classDelta = new SigClassDefinitionDelta(from, to); 244 } 245 classDelta.setMethodDeltas(methodDeltas); 246 } 247 248 // fields 249 Set<IFieldDelta> fieldDeltas = compareFields(from.getFields(), to 250 .getFields()); 251 if (fieldDeltas != null) { 252 if (classDelta == null) { 253 classDelta = new SigClassDefinitionDelta(from, to); 254 } 255 classDelta.setFieldDeltas(fieldDeltas); 256 } 257 258 // enum constants 259 if (from.getKind() == Kind.ENUM) { 260 Set<IEnumConstantDelta> enumDeltas = compareEnumConstants(from 261 .getEnumConstants(), to.getEnumConstants()); 262 if (enumDeltas != null) { 263 if (classDelta == null) { 264 classDelta = new SigClassDefinitionDelta(from, to); 265 } 266 classDelta.setEnumConstantDeltas(enumDeltas); 267 } 268 } else if (from.getKind() == Kind.ANNOTATION) { 269 Set<IAnnotationFieldDelta> annotationFieldDeltas = 270 compareAnnotationFields(from.getAnnotationFields(), 271 to.getAnnotationFields()); 272 if (annotationFieldDeltas != null) { 273 if (classDelta == null) { 274 classDelta = new SigClassDefinitionDelta(from, to); 275 } 276 classDelta.setAnnotationFieldDeltas(annotationFieldDeltas); 277 } 278 } 279 280 Set<IAnnotationDelta> annotationDeltas = compareAnnotations(from 281 .getAnnotations(), to.getAnnotations()); 282 if (annotationDeltas != null) { 283 if (classDelta == null) { 284 classDelta = new SigClassDefinitionDelta(from, to); 285 } 286 classDelta.setAnnotationDeltas(annotationDeltas); 287 } 288 return classDelta; 289 } 290 291 private Set<ITypeReferenceDelta<?>> compareInterfaces( 292 IClassDefinition from, IClassDefinition to) { 293 Set<ITypeReference> fromClosure = getInterfaceClosure(from); 294 Set<ITypeReference> toClosure = getInterfaceClosure(to); 295 296 Set<ITypeReference> fromInterfaces = from.getInterfaces(); 297 Set<ITypeReference> toInterfaces = to.getInterfaces(); 298 299 Set<ITypeReferenceDelta<?>> deltas = 300 new HashSet<ITypeReferenceDelta<?>>(); 301 302 // check whether all from interfaces are directly or indirectly 303 // implemented by the to method 304 for (ITypeReference type : fromInterfaces) { 305 if (!containsType(type, toInterfaces)) { 306 if (!(containsType(type, toClosure) /* 307 * && !containsType(type, 308 * toInterfaces) 309 */)) { 310 deltas.add(new SigTypeDelta<ITypeReference>(type, null)); 311 } 312 } 313 } 314 315 // check whether all interfaces to are directly or indirectly 316 // implemented by the from method 317 for (ITypeReference type : toInterfaces) { 318 if (!containsType(type, fromInterfaces)) { 319 if (!(containsType(type, fromClosure) /* 320 * && !containsType(type, 321 * fromInterfaces) 322 */)) { 323 deltas.add(new SigTypeDelta<ITypeReference>(null, type)); 324 } 325 } 326 } 327 return deltas.isEmpty() ? null : deltas; 328 } 329 330 331 private boolean containsType(ITypeReference type, 332 Set<ITypeReference> setOfTypes) { 333 for (ITypeReference other : setOfTypes) { 334 if (compareType(type, other, false) == null) { 335 return true; 336 } 337 } 338 return false; 339 } 340 341 private Set<ITypeReference> getInterfaceClosure(IClassDefinition clazz) { 342 Set<ITypeReference> closure = new HashSet<ITypeReference>(); 343 collectInterfaceClosure(ViewpointAdapter.getReferenceTo(clazz), 344 closure); 345 return closure; 346 } 347 348 private void collectInterfaceClosure(ITypeReference clazz, 349 Set<ITypeReference> closure) { 350 351 IClassDefinition classDefinition = getClassDefinition(clazz); 352 Set<ITypeReference> interfaces = classDefinition.getInterfaces(); 353 if (interfaces == null) { 354 return; 355 } 356 for (ITypeReference interfaze : interfaces) { 357 closure.add(interfaze); 358 } 359 360 ITypeReference superclass = classDefinition.getSuperClass(); 361 if (superclass != null) { 362 if (superclass instanceof IParameterizedType) { 363 collectInterfaceClosure(((IParameterizedType) superclass) 364 .getRawType(), closure); 365 } else { 366 collectInterfaceClosure(superclass, closure); 367 } 368 } 369 for (ITypeReference interfaze : interfaces) { 370 if (interfaze instanceof IParameterizedType) { 371 collectInterfaceClosure(((IParameterizedType) interfaze) 372 .getRawType(), closure); 373 } else { 374 collectInterfaceClosure(interfaze, closure); 375 } 376 } 377 } 378 379 private Set<IAnnotationDelta> compareAnnotations(Set<IAnnotation> from, 380 Set<IAnnotation> to) { 381 return compareSets(from, to, 382 new SigComparator<IAnnotation, IAnnotationDelta>() { 383 public IAnnotationDelta createAddRemoveDelta( 384 IAnnotation from, IAnnotation to) { 385 return new SigAnnotationDelta(from, to); 386 } 387 388 public boolean considerEqualElement(IAnnotation from, 389 IAnnotation to) { 390 return sameClassDefinition(from.getType() 391 .getClassDefinition(), to.getType() 392 .getClassDefinition()); 393 } 394 395 public IAnnotationDelta createChangedDelta( 396 IAnnotation from, IAnnotation to) { 397 return compareAnnotation(from, to); 398 } 399 }); 400 } 401 402 private Set<IAnnotationFieldDelta> compareAnnotationFields( 403 Set<IAnnotationField> from, Set<IAnnotationField> to) { 404 return compareSets(from, to, 405 new SigComparator<IAnnotationField, IAnnotationFieldDelta>() { 406 public boolean considerEqualElement(IAnnotationField from, 407 IAnnotationField to) { 408 return from.getName().equals(to.getName()); 409 } 410 411 public IAnnotationFieldDelta createAddRemoveDelta( 412 IAnnotationField from, IAnnotationField to) { 413 return new SigAnnotationFieldDelta(from, to); 414 } 415 416 public IAnnotationFieldDelta createChangedDelta( 417 IAnnotationField from, IAnnotationField to) { 418 return compareAnnotationField(from, to); 419 } 420 }); 421 } 422 423 private Set<IEnumConstantDelta> compareEnumConstants( 424 Set<IEnumConstant> from, Set<IEnumConstant> to) { 425 return compareSets(from, to, 426 new SigComparator<IEnumConstant, IEnumConstantDelta>() { 427 public boolean considerEqualElement(IEnumConstant from, 428 IEnumConstant to) { 429 return from.getName().equals(to.getName()); 430 } 431 432 public IEnumConstantDelta createAddRemoveDelta( 433 IEnumConstant from, IEnumConstant to) { 434 return new SigEnumConstantDelta(from, to); 435 } 436 437 public IEnumConstantDelta createChangedDelta( 438 IEnumConstant from, IEnumConstant to) { 439 return compareEnumConstant(from, to); 440 } 441 }); 442 } 443 444 private Set<IFieldDelta> compareFields(Set<IField> from, Set<IField> to) { 445 return compareSets(from, to, new SigComparator<IField, IFieldDelta>() { 446 public boolean considerEqualElement(IField from, IField to) { 447 return from.getName().equals(to.getName()); 448 } 449 450 public IFieldDelta createAddRemoveDelta(IField from, IField to) { 451 return new SigFieldDelta(from, to); 452 } 453 454 public IFieldDelta createChangedDelta(IField from, IField to) { 455 return compareField(from, to); 456 } 457 }); 458 } 459 460 private Set<IMethodDelta> compareMethods(IClassDefinition from, 461 IClassDefinition to) { 462 assert from != null; 463 assert to != null; 464 465 Set<IMethod> toMethods = new HashSet<IMethod>(to.getMethods()); 466 Set<IMethod> toClosure = getMethodClosure(to); 467 Set<IMethod> fromMethods = new HashSet<IMethod>(from.getMethods()); 468 Set<IMethod> fromClosure = getMethodClosure(from); 469 470 Set<IMethodDelta> deltas = new HashSet<IMethodDelta>(); 471 472 for (IMethod method : fromMethods) { 473 IMethod compatibleMethod = findCompatibleMethod(method, toMethods); 474 if (compatibleMethod == null) { 475 compatibleMethod = findCompatibleMethod(method, toClosure); 476 if (compatibleMethod == null) { 477 deltas.add(new SigMethodDelta(method, null)); 478 } 479 } 480 481 if (compatibleMethod != null) { 482 IMethodDelta delta = compareMethod(method, compatibleMethod); 483 if (delta != null) { 484 deltas.add(delta); 485 } 486 } 487 } 488 489 for (IMethod method : toMethods) { 490 IMethod compatibleMethod = findCompatibleMethod(method, fromMethods); 491 if (compatibleMethod == null) { 492 compatibleMethod = findCompatibleMethod(method, fromClosure); 493 if (compatibleMethod == null) { 494 deltas.add(new SigMethodDelta(null, method)); 495 } 496 } 497 } 498 return deltas.isEmpty() ? null : deltas; 499 } 500 501 private IMethod findCompatibleMethod(IMethod method, Set<IMethod> set) { 502 for (IMethod methodFromSet : set) { 503 if (equalsSignature(method, methodFromSet)) { 504 return methodFromSet; 505 } 506 } 507 return null; 508 } 509 510 511 private Set<IMethod> getMethodClosure(IClassDefinition clazz) { 512 Set<IMethod> closure = new HashSet<IMethod>(); 513 collectMethods(new ClassProjection(clazz, 514 new HashMap<ITypeVariableDefinition, ITypeReference>()), 515 closure); 516 return closure; 517 } 518 519 private void collectMethods(IClassDefinition clazz, Set<IMethod> closure) { 520 if (clazz == null) { 521 return; 522 } 523 if (clazz.getMethods() != null) { 524 closure.addAll(clazz.getMethods()); 525 } 526 if (clazz.getSuperClass() != null) { 527 collectMethods(getClassDefinition(clazz.getSuperClass()), closure); 528 } 529 if (clazz.getInterfaces() != null) { 530 for (ITypeReference interfaze : clazz.getInterfaces()) { 531 collectMethods(getClassDefinition(interfaze), closure); 532 } 533 } 534 } 535 536 private Set<IConstructorDelta> compareConstructors(Set<IConstructor> from, 537 Set<IConstructor> to) { 538 return compareSets(from, to, 539 new SigComparator<IConstructor, IConstructorDelta>() { 540 public boolean considerEqualElement(IConstructor from, 541 IConstructor to) { 542 return equalsSignature(from, to); 543 } 544 545 public IConstructorDelta createAddRemoveDelta( 546 IConstructor from, IConstructor to) { 547 return new SigConstructorDelta(from, to); 548 } 549 550 public IConstructorDelta createChangedDelta( 551 IConstructor from, IConstructor to) { 552 return compareConstructor(from, to); 553 } 554 }); 555 } 556 557 // compares names and parameter types 558 private boolean equalsSignature(IExecutableMember from, 559 IExecutableMember to) { 560 if (from.getName().equals(to.getName())) { 561 return compareTypeSequence(getParameterList(from.getParameters()), 562 getParameterList(to.getParameters()), true) == null; 563 } 564 return false; 565 } 566 567 private List<ITypeReference> getParameterList(List<IParameter> parameters) { 568 List<ITypeReference> parameterTypes = new LinkedList<ITypeReference>(); 569 for (IParameter parameter : parameters) { 570 parameterTypes.add(parameter.getType()); 571 } 572 return parameterTypes; 573 } 574 575 private IAnnotationDelta compareAnnotation(IAnnotation from, 576 IAnnotation to) { 577 assert sameClassDefinition(from.getType().getClassDefinition(), to 578 .getType().getClassDefinition()); 579 580 Set<IAnnotationElement> fromAnnotationElement = 581 getNormalizedAnnotationElements(from); 582 Set<IAnnotationElement> toAnnotationElement = 583 getNormalizedAnnotationElements(to); 584 585 Set<IAnnotationElementDelta> annotationElementDeltas = 586 compareAnnotationElements( 587 fromAnnotationElement, toAnnotationElement); 588 SigAnnotationDelta delta = null; 589 590 if (annotationElementDeltas != null) { 591 delta = new SigAnnotationDelta(from, to); 592 delta.setAnnotationElementDeltas(annotationElementDeltas); 593 } 594 return delta; 595 } 596 597 /** 598 * Returns the annotation elements for the given annotation. The returned 599 * set contains all declared elements plus all elements with default values. 600 * 601 * @param annotation 602 * the annotation to return the elements for 603 * @return the default enriched annotation elements 604 */ 605 private Set<IAnnotationElement> getNormalizedAnnotationElements( 606 IAnnotation annotation) { 607 Set<IAnnotationElement> elements = new HashSet<IAnnotationElement>( 608 annotation.getElements()); 609 610 Set<String> names = new HashSet<String>(); 611 for (IAnnotationElement annotationElement : elements) { 612 names.add(annotationElement.getDeclaringField().getName()); 613 } 614 615 for (IAnnotationField field : annotation.getType().getClassDefinition() 616 .getAnnotationFields()) { 617 if (!names.contains(field.getName())) { 618 SigAnnotationElement sigAnnotationElement = 619 new SigAnnotationElement(); 620 sigAnnotationElement.setDeclaringField(field); 621 sigAnnotationElement.setValue(field.getDefaultValue()); 622 elements.add(sigAnnotationElement); 623 } 624 } 625 return elements; 626 } 627 628 private Set<IAnnotationElementDelta> compareAnnotationElements( 629 Set<IAnnotationElement> from, Set<IAnnotationElement> to) { 630 return compareSets(from, to, 631 new SigComparator<IAnnotationElement, IAnnotationElementDelta>() { 632 public boolean considerEqualElement( 633 IAnnotationElement from, IAnnotationElement to) { 634 return from.getDeclaringField().getName().equals( 635 to.getDeclaringField().getName()); 636 } 637 638 public IAnnotationElementDelta createAddRemoveDelta( 639 IAnnotationElement from, IAnnotationElement to) { 640 return new SigAnnotationElementDelta(from, to); 641 } 642 643 public IAnnotationElementDelta createChangedDelta( 644 IAnnotationElement from, IAnnotationElement to) { 645 return compareAnnotationElement(from, to); 646 } 647 }); 648 } 649 650 private IAnnotationElementDelta compareAnnotationElement( 651 IAnnotationElement from, IAnnotationElement to) { 652 SigAnnotationElementDelta delta = null; 653 SigValueDelta valueDelta = compareValue(from.getValue(), to.getValue()); 654 655 if (valueDelta != null) { 656 delta = new SigAnnotationElementDelta(from, to); 657 delta.setValueDelta(valueDelta); 658 } 659 return delta; 660 } 661 662 /** 663 * Removes the {@link Modifier#ABSTRACT} modifier. 664 */ 665 private Set<Modifier> prepareMethodModifiers(IMethod method) { 666 Set<Modifier> modifierCopy = new HashSet<Modifier>(method 667 .getModifiers()); 668 modifierCopy.remove(Modifier.ABSTRACT); 669 return modifierCopy; 670 } 671 672 private IMethodDelta compareMethod(IMethod from, IMethod to) { 673 assert from != null && to != null; 674 675 SigMethodDelta methodDelta = null; 676 Set<IModifierDelta> modiferDeltas = compareModifiers( 677 prepareMethodModifiers(from), prepareMethodModifiers(to)); 678 if (modiferDeltas != null) { 679 methodDelta = new SigMethodDelta(from, to); 680 methodDelta.setModifierDeltas(modiferDeltas); 681 } 682 683 Set<IParameterDelta> parameterDeltas = compareParameterSequence(from 684 .getParameters(), to.getParameters()); 685 if (parameterDeltas != null) { 686 if (methodDelta == null) { 687 methodDelta = new SigMethodDelta(from, to); 688 } 689 methodDelta.setParameterDeltas(parameterDeltas); 690 } 691 692 Set<IAnnotationDelta> annotationDeltas = compareAnnotations(from 693 .getAnnotations(), to.getAnnotations()); 694 if (annotationDeltas != null) { 695 if (methodDelta == null) { 696 methodDelta = new SigMethodDelta(from, to); 697 } 698 methodDelta.setAnnotationDeltas(annotationDeltas); 699 } 700 701 Set<ITypeVariableDefinitionDelta> typeParameterDeltas = 702 compareTypeVariableSequence(from.getTypeParameters(), 703 to.getTypeParameters()); 704 if (typeParameterDeltas != null) { 705 if (methodDelta == null) { 706 methodDelta = new SigMethodDelta(from, to); 707 } 708 methodDelta.setTypeVariableDeltas(typeParameterDeltas); 709 } 710 711 Set<ITypeReferenceDelta<?>> exceptionDeltas = compareTypes( 712 normalizeExceptions(from.getExceptions()), 713 normalizeExceptions(to.getExceptions())); 714 if (exceptionDeltas != null) { 715 if (methodDelta == null) { 716 methodDelta = new SigMethodDelta(from, to); 717 } 718 methodDelta.setExceptionDeltas(exceptionDeltas); 719 } 720 721 ITypeReferenceDelta<?> returnTypeDelta = compareType(from 722 .getReturnType(), to.getReturnType(), false); 723 if (returnTypeDelta != null) { 724 if (methodDelta == null) { 725 methodDelta = new SigMethodDelta(from, to); 726 } 727 methodDelta.setReturnTypeDelta(returnTypeDelta); 728 } 729 730 return methodDelta; 731 } 732 733 // remove runtime exceptions, 734 // remove sub types of containing exception 735 private Set<ITypeReference> normalizeExceptions( 736 Set<ITypeReference> exceptions) { 737 Set<ITypeReference> exceptionCopy = new HashSet<ITypeReference>( 738 exceptions); 739 740 Iterator<ITypeReference> iterator = exceptionCopy.iterator(); 741 while (iterator.hasNext()) { 742 ITypeReference exception = iterator.next(); 743 if (isRuntimeExceptionOrErrorSubtype(exception)) { 744 iterator.remove(); 745 } 746 } 747 exceptionCopy = removeSpecializations(exceptionCopy); 748 return exceptionCopy; 749 } 750 751 private Set<ITypeReference> removeSpecializations( 752 Set<ITypeReference> exceptions) { 753 Set<ITypeReference> exceptionCopy = new HashSet<ITypeReference>( 754 exceptions); 755 for (ITypeReference type : exceptions) { 756 Iterator<ITypeReference> it = exceptionCopy.iterator(); 757 while (it.hasNext()) { 758 ITypeReference subType = it.next(); 759 if (isSuperClass(getClassDefinition(type), 760 getClassDefinition(subType))) { 761 it.remove(); 762 } 763 } 764 } 765 return exceptionCopy; 766 } 767 768 /** 769 * Returns true if superC is a super class of subC. 770 */ 771 private boolean isSuperClass(IClassDefinition superC, 772 IClassDefinition subC) { 773 if (superC == null || subC == null) { 774 return false; 775 } 776 777 if (subC.getSuperClass() == null) { 778 return false; 779 } else { 780 if (getClassDefinition(subC.getSuperClass()).equals(superC)) { 781 return true; 782 } else { 783 return isSuperClass(superC, getClassDefinition(subC 784 .getSuperClass())); 785 } 786 } 787 } 788 789 private boolean isSuperInterface(IClassDefinition superClass, 790 IClassDefinition subClass) { 791 if (superClass == null || subClass == null) { 792 return false; 793 } 794 795 if (subClass.getInterfaces() == null) { 796 return false; 797 } else { 798 if (getClassDefinitions(subClass.getInterfaces()).contains( 799 superClass)) { 800 return true; 801 } else { 802 for (ITypeReference subType : subClass.getInterfaces()) { 803 if (isSuperInterface(superClass, 804 getClassDefinition(subType))) { 805 return true; 806 } 807 } 808 return false; 809 } 810 } 811 } 812 813 private Set<IClassDefinition> getClassDefinitions( 814 Set<ITypeReference> references) { 815 Set<IClassDefinition> definitions = new HashSet<IClassDefinition>(); 816 for (ITypeReference ref : references) { 817 definitions.add(getClassDefinition(ref)); 818 } 819 return definitions; 820 } 821 822 /** 823 * Returns null if type is not one of: 824 * <ul> 825 * <li>IClassReference</li> 826 * <li>IParameterizedType</li> 827 * </ul> 828 */ 829 private IClassDefinition getClassDefinition(ITypeReference type) { 830 assert type != null; 831 832 IClassDefinition returnValue = null; 833 if (type instanceof IClassReference) { 834 returnValue = ((IClassReference) type).getClassDefinition(); 835 } else if (type instanceof IParameterizedType) { 836 returnValue = ((IParameterizedType) type).getRawType() 837 .getClassDefinition(); 838 } 839 return returnValue; 840 } 841 842 private boolean isRuntimeExceptionOrErrorSubtype(ITypeReference exception) { 843 844 IClassDefinition clazz = getClassDefinition(exception); 845 if (clazz != null) { 846 if (isRuntimeExceptionOrError(clazz)) { 847 return true; 848 } else if (clazz.getSuperClass() != null) { 849 return isRuntimeExceptionOrErrorSubtype(clazz.getSuperClass()); 850 } else { 851 return false; 852 } 853 } 854 return false; 855 } 856 857 private boolean isRuntimeExceptionOrError(IClassDefinition exception) { 858 if (exception == null) { 859 return false; 860 } 861 String packageName = exception.getPackageName(); 862 String className = exception.getName(); 863 864 if (packageName != null && className != null 865 && "java.lang".equals(packageName)) { 866 return "RuntimeException".equals(className) 867 || "Error".equals(className); 868 } 869 return false; 870 } 871 872 private IConstructorDelta compareConstructor(IConstructor from, 873 IConstructor to) { 874 SigConstructorDelta constructorDelta = null; 875 Set<IModifierDelta> modiferDeltas = compareModifiers(from 876 .getModifiers(), to.getModifiers()); 877 if (modiferDeltas != null) { 878 constructorDelta = new SigConstructorDelta(from, to); 879 constructorDelta.setModifierDeltas(modiferDeltas); 880 } 881 882 Set<IParameterDelta> parameterDeltas = compareParameterSequence(from 883 .getParameters(), to.getParameters()); 884 if (parameterDeltas != null) { 885 if (constructorDelta == null) { 886 constructorDelta = new SigConstructorDelta(from, to); 887 } 888 constructorDelta.setParameterDeltas(parameterDeltas); 889 } 890 891 Set<IAnnotationDelta> annotationDeltas = compareAnnotations(from 892 .getAnnotations(), to.getAnnotations()); 893 if (annotationDeltas != null) { 894 if (constructorDelta == null) { 895 constructorDelta = new SigConstructorDelta(from, to); 896 } 897 constructorDelta.setAnnotationDeltas(annotationDeltas); 898 } 899 900 Set<ITypeVariableDefinitionDelta> typeParameterDeltas = 901 compareTypeVariableSequence(from.getTypeParameters(), 902 to.getTypeParameters()); 903 if (typeParameterDeltas != null) { 904 if (constructorDelta == null) { 905 constructorDelta = new SigConstructorDelta(from, to); 906 } 907 constructorDelta.setTypeVariableDeltas(typeParameterDeltas); 908 } 909 910 Set<ITypeReferenceDelta<?>> exceptionDeltas = compareTypes( 911 normalizeExceptions(from.getExceptions()), 912 normalizeExceptions(to.getExceptions())); 913 if (exceptionDeltas != null) { 914 if (constructorDelta == null) { 915 constructorDelta = new SigConstructorDelta(from, to); 916 } 917 constructorDelta.setExceptionDeltas(exceptionDeltas); 918 } 919 return constructorDelta; 920 } 921 922 private Set<IParameterDelta> compareParameterSequence( 923 List<IParameter> from, List<IParameter> to) { 924 assert from.size() == to.size(); 925 Set<IParameterDelta> deltas = new HashSet<IParameterDelta>(); 926 Iterator<IParameter> fromIterator = from.iterator(); 927 Iterator<IParameter> toIterator = to.iterator(); 928 while (fromIterator.hasNext() && toIterator.hasNext()) { 929 IParameterDelta delta = compareParameter(fromIterator.next(), 930 toIterator.next()); 931 if (delta != null) { 932 deltas.add(delta); 933 } 934 } 935 return deltas.isEmpty() ? null : deltas; 936 } 937 938 private IParameterDelta compareParameter(IParameter from, IParameter to) { 939 SigParameterDelta delta = null; 940 ITypeReferenceDelta<?> typeDelta = compareType(from.getType(), to 941 .getType(), false); 942 if (typeDelta != null) { 943 if (delta == null) { 944 delta = new SigParameterDelta(from, to); 945 } 946 delta.setTypeDelta(typeDelta); 947 } 948 949 Set<IAnnotationDelta> annotationDeltas = compareAnnotations(from 950 .getAnnotations(), to.getAnnotations()); 951 if (annotationDeltas != null) { 952 if (delta == null) { 953 delta = new SigParameterDelta(from, to); 954 } 955 delta.setAnnotationDeltas(annotationDeltas); 956 } 957 return delta; 958 } 959 960 private Set<ITypeVariableDefinitionDelta> compareTypeVariableSequence( 961 List<ITypeVariableDefinition> from, 962 List<ITypeVariableDefinition> to) { 963 Set<ITypeVariableDefinitionDelta> deltas = 964 new HashSet<ITypeVariableDefinitionDelta>(); 965 if (from.size() != to.size()) { 966 for (ITypeVariableDefinition fromVariable : from) { 967 deltas.add(new SigTypeVariableDefinitionDelta(fromVariable, 968 null)); 969 } 970 for (ITypeVariableDefinition toVariable : to) { 971 deltas 972 .add(new SigTypeVariableDefinitionDelta(null, 973 toVariable)); 974 } 975 } 976 977 Iterator<ITypeVariableDefinition> fromIterator = from.iterator(); 978 Iterator<ITypeVariableDefinition> toIterator = to.iterator(); 979 while (fromIterator.hasNext() && toIterator.hasNext()) { 980 ITypeVariableDefinitionDelta delta = compareTypeVariableDefinition( 981 fromIterator.next(), toIterator.next()); 982 if (delta != null) { 983 deltas.add(delta); 984 } 985 } 986 return deltas.isEmpty() ? null : deltas; 987 } 988 989 private ITypeVariableDefinitionDelta compareTypeVariableDefinition( 990 ITypeVariableDefinition from, ITypeVariableDefinition to) { 991 IGenericDeclarationDelta declarationDelta = compareGenericDeclaration( 992 from, to); 993 994 if (declarationDelta != null) { 995 SigTypeVariableDefinitionDelta delta = 996 new SigTypeVariableDefinitionDelta(from, to); 997 delta.setGenericDeclarationDelta(declarationDelta); 998 return delta; 999 } 1000 IUpperBoundsDelta upperBoundDelta = compareUpperBounds(from 1001 .getUpperBounds(), to.getUpperBounds()); 1002 1003 if (upperBoundDelta != null) { 1004 SigTypeVariableDefinitionDelta delta = 1005 new SigTypeVariableDefinitionDelta(from, to); 1006 delta.setUpperBoundsDelta(upperBoundDelta); 1007 return delta; 1008 } 1009 return null; 1010 } 1011 1012 private ITypeReferenceDelta<ITypeVariableReference> compareTypeVariableReference( 1013 ITypeVariableReference from, ITypeVariableReference to) { 1014 IGenericDeclarationDelta declarationDelta = compareGenericDeclaration( 1015 from.getTypeVariableDefinition(), to 1016 .getTypeVariableDefinition()); 1017 if (declarationDelta != null) { 1018 SigTypeVariableReferenceDelta delta = 1019 new SigTypeVariableReferenceDelta(from, to); 1020 delta.setGenericDeclarationDelta(declarationDelta); 1021 return delta; 1022 } 1023 return null; 1024 } 1025 1026 private Set<IModifierDelta> compareModifiers(Set<Modifier> from, 1027 Set<Modifier> to) { 1028 return compareSets(from, to, 1029 new SigComparator<Modifier, IModifierDelta>() { 1030 public boolean considerEqualElement(Modifier from, 1031 Modifier to) { 1032 return from.equals(to); 1033 } 1034 1035 public IModifierDelta createAddRemoveDelta(Modifier from, 1036 Modifier to) { 1037 return new SigModifierDelta(from, to); 1038 } 1039 1040 public IModifierDelta createChangedDelta(Modifier from, 1041 Modifier to) { 1042 return null; 1043 } 1044 }); 1045 } 1046 1047 1048 private IFieldDelta compareField(IField from, IField to) { 1049 SigFieldDelta fieldDelta = null; 1050 1051 Set<IModifierDelta> modiferDeltas = compareModifiers(from 1052 .getModifiers(), to.getModifiers()); 1053 if (modiferDeltas != null) { 1054 fieldDelta = new SigFieldDelta(from, to); 1055 fieldDelta.setModifierDeltas(modiferDeltas); 1056 } 1057 1058 Set<IAnnotationDelta> annotationDeltas = compareAnnotations(from 1059 .getAnnotations(), to.getAnnotations()); 1060 if (annotationDeltas != null) { 1061 if (fieldDelta == null) { 1062 fieldDelta = new SigFieldDelta(from, to); 1063 } 1064 fieldDelta.setAnnotationDeltas(annotationDeltas); 1065 } 1066 1067 ITypeReferenceDelta<?> typeDelta = compareType(from.getType(), to 1068 .getType(), false); 1069 if (typeDelta != null) { 1070 if (fieldDelta == null) { 1071 fieldDelta = new SigFieldDelta(from, to); 1072 } 1073 fieldDelta.setTypeDelta(typeDelta); 1074 } 1075 return fieldDelta; 1076 } 1077 1078 private IEnumConstantDelta compareEnumConstant(IEnumConstant from, 1079 IEnumConstant to) { 1080 SigEnumConstantDelta enumConstantDelta = null; 1081 1082 Set<IModifierDelta> modiferDeltas = compareModifiers(from 1083 .getModifiers(), to.getModifiers()); 1084 if (modiferDeltas != null) { 1085 enumConstantDelta = new SigEnumConstantDelta(from, to); 1086 enumConstantDelta.setModifierDeltas(modiferDeltas); 1087 } 1088 1089 Set<IAnnotationDelta> annotationDeltas = compareAnnotations(from 1090 .getAnnotations(), to.getAnnotations()); 1091 if (annotationDeltas != null) { 1092 if (enumConstantDelta == null) { 1093 enumConstantDelta = new SigEnumConstantDelta(from, to); 1094 } 1095 enumConstantDelta.setAnnotationDeltas(annotationDeltas); 1096 } 1097 1098 ITypeReferenceDelta<?> typeDelta = compareType(from.getType(), to 1099 .getType(), false); 1100 if (typeDelta != null) { 1101 if (enumConstantDelta == null) { 1102 enumConstantDelta = new SigEnumConstantDelta(from, to); 1103 } 1104 enumConstantDelta.setTypeDelta(typeDelta); 1105 } 1106 1107 // FIXME ordinal not supported in dex 1108 // ValueDelta ordinalDelta = compareValue(from.getOrdinal(), 1109 // to.getOrdinal()); 1110 // if (ordinalDelta != null) { 1111 // if (enumConstantDelta == null) { 1112 // enumConstantDelta = new SigEnumConstantDelta(from, to); 1113 // } 1114 // enumConstantDelta.setOrdinalDelta(ordinalDelta); 1115 // } 1116 1117 return enumConstantDelta; 1118 } 1119 1120 private IAnnotationFieldDelta compareAnnotationField(IAnnotationField from, 1121 IAnnotationField to) { 1122 SigAnnotationFieldDelta annotationFieldDelta = null; 1123 1124 Set<IModifierDelta> modiferDeltas = compareModifiers(from 1125 .getModifiers(), to.getModifiers()); 1126 if (modiferDeltas != null) { 1127 annotationFieldDelta = new SigAnnotationFieldDelta(from, to); 1128 annotationFieldDelta.setModifierDeltas(modiferDeltas); 1129 } 1130 1131 Set<IAnnotationDelta> annotationDeltas = compareAnnotations(from 1132 .getAnnotations(), to.getAnnotations()); 1133 if (annotationDeltas != null) { 1134 if (annotationFieldDelta == null) { 1135 annotationFieldDelta = new SigAnnotationFieldDelta(from, to); 1136 } 1137 annotationFieldDelta.setAnnotationDeltas(annotationDeltas); 1138 } 1139 1140 ITypeReferenceDelta<?> typeDelta = compareType(from.getType(), to 1141 .getType(), false); 1142 if (typeDelta != null) { 1143 if (annotationFieldDelta == null) { 1144 annotationFieldDelta = new SigAnnotationFieldDelta(from, to); 1145 } 1146 annotationFieldDelta.setTypeDelta(typeDelta); 1147 } 1148 1149 IValueDelta defaultValueDelta = compareValue(from.getDefaultValue(), to 1150 .getDefaultValue()); 1151 if (defaultValueDelta != null) { 1152 if (annotationFieldDelta == null) { 1153 annotationFieldDelta = new SigAnnotationFieldDelta(from, to); 1154 } 1155 annotationFieldDelta.setDefaultValueDelta(defaultValueDelta); 1156 } 1157 1158 return annotationFieldDelta; 1159 } 1160 1161 private SigValueDelta compareValue(Object from, Object to) { 1162 // same value 1163 if (from == null && to == null) { 1164 return null; 1165 } 1166 1167 // one of both is null and other is not 1168 if (from == null || to == null) { 1169 return new SigValueDelta(from, to); 1170 } 1171 1172 SigValueDelta delta = null; 1173 // different types 1174 if (from.getClass() == to.getClass()) { 1175 if (from.getClass().isArray()) { 1176 Object[] fromArray = (Object[]) from; 1177 Object[] toArray = (Object[]) from; 1178 if (!Arrays.equals(fromArray, toArray)) { 1179 delta = new SigValueDelta(from, to); 1180 } 1181 } else if (from instanceof IEnumConstant) { 1182 IEnumConstantDelta enumConstantDelta = compareEnumConstant( 1183 (IEnumConstant) from, (IEnumConstant) to); 1184 if (enumConstantDelta != null) { 1185 delta = new SigValueDelta(from, to); 1186 } 1187 } else if (from instanceof IAnnotation) { 1188 IAnnotationDelta annotationDelta = compareAnnotation( 1189 (IAnnotation) from, (IAnnotation) to); 1190 if (annotationDelta != null) { 1191 delta = new SigValueDelta(from, to); 1192 } 1193 } else if (from instanceof IField) { 1194 IFieldDelta fieldDelta = compareField((IField) from, 1195 (IField) to); 1196 if (fieldDelta != null) { 1197 delta = new SigValueDelta(from, to); 1198 } 1199 } else if (from instanceof ITypeReference) { 1200 ITypeReferenceDelta<? extends ITypeReference> typeDelta = 1201 compareType((ITypeReference) from, (ITypeReference) to, 1202 false); 1203 if (typeDelta != null) { 1204 delta = new SigValueDelta(from, to); 1205 } 1206 } else if (!from.equals(to)) { 1207 delta = new SigValueDelta(from, to); 1208 } 1209 1210 } else if (!(from == null && to == null)) { 1211 delta = new SigValueDelta(from, to); 1212 } 1213 return delta; 1214 } 1215 1216 private boolean considerEqualTypes(ITypeReference from, ITypeReference to) { 1217 assert from != null && to != null; 1218 1219 if (implementInterface(from, to, IPrimitiveType.class)) { 1220 return comparePrimitiveType((IPrimitiveType) from, 1221 (IPrimitiveType) to) == null; 1222 } 1223 if (implementInterface(from, to, IClassReference.class)) { 1224 return sameClassDefinition(((IClassReference) from) 1225 .getClassDefinition(), ((IClassReference) to) 1226 .getClassDefinition()); 1227 } 1228 if (implementInterface(from, to, IArrayType.class)) { 1229 return considerEqualTypes(((IArrayType) from).getComponentType(), 1230 ((IArrayType) to).getComponentType()); 1231 } 1232 if (implementInterface(from, to, IParameterizedType.class)) { 1233 return compareClassReference(((IParameterizedType) from) 1234 .getRawType(), ((IParameterizedType) to) 1235 .getRawType()) == null; 1236 } 1237 if (implementInterface(from, to, ITypeVariableReference.class)) { 1238 return compareTypeVariableReference((ITypeVariableReference) from, 1239 (ITypeVariableReference) to) == null; 1240 } 1241 1242 return false; 1243 } 1244 1245 private Set<ITypeReference> fromComparison = new HashSet<ITypeReference>(); 1246 private Set<ITypeReference> toComparison = new HashSet<ITypeReference>(); 1247 1248 1249 private boolean areInComparison(ITypeReference from, ITypeReference to) { 1250 return fromComparison.contains(from) && toComparison.contains(to); 1251 } 1252 1253 private void markInComparison(ITypeReference from, ITypeReference to) { 1254 fromComparison.add(from); 1255 toComparison.add(to); 1256 } 1257 1258 private void markFinishedComparison(ITypeReference from, 1259 ITypeReference to) { 1260 fromComparison.remove(from); 1261 toComparison.remove(to); 1262 } 1263 1264 private ITypeReferenceDelta<? extends ITypeReference> compareType( 1265 ITypeReference from, ITypeReference to, boolean acceptErasedTypes) { 1266 1267 if (from == null && to == null) { 1268 return null; 1269 } 1270 if ((from == null && to != null) || (from != null && to == null)) { 1271 return new SigTypeDelta<ITypeReference>(from, to); 1272 } 1273 if (areInComparison(from, to)) { 1274 return null; 1275 } 1276 try { 1277 markInComparison(from, to); 1278 1279 if (implementInterface(from, to, IPrimitiveType.class)) { 1280 return comparePrimitiveType((IPrimitiveType) from, 1281 (IPrimitiveType) to); 1282 } 1283 if (implementInterface(from, to, IClassReference.class)) { 1284 return compareClassReference((IClassReference) from, 1285 (IClassReference) to); 1286 } 1287 if (implementInterface(from, to, IArrayType.class)) { 1288 return compareArrayType((IArrayType) from, (IArrayType) to); 1289 } 1290 if (implementInterface(from, to, IParameterizedType.class)) { 1291 return compareParameterizedType((IParameterizedType) from, 1292 (IParameterizedType) to, acceptErasedTypes); 1293 } 1294 if (implementInterface(from, to, ITypeVariableReference.class)) { 1295 return compareTypeVariableReference( 1296 (ITypeVariableReference) from, 1297 (ITypeVariableReference) to); 1298 } 1299 if (implementInterface(from, to, IWildcardType.class)) { 1300 return compareWildcardType((IWildcardType) from, 1301 (IWildcardType) to); 1302 } 1303 1304 if (acceptErasedTypes) { 1305 if (isGeneric(from) && !isGeneric(to)) { 1306 return compareType(getErasedType(from), to, false); 1307 } 1308 1309 if (!isGeneric(from) && isGeneric(to)) { 1310 return compareType(from, getErasedType(to), false); 1311 } 1312 } 1313 return new SigTypeDelta<ITypeReference>(from, to); 1314 } finally { 1315 markFinishedComparison(from, to); 1316 } 1317 } 1318 1319 private boolean isGeneric(ITypeReference reference) { 1320 if (reference instanceof IParameterizedType 1321 || reference instanceof ITypeVariableReference 1322 || reference instanceof IWildcardType) { 1323 return true; 1324 } 1325 if (reference instanceof IArrayType) { 1326 return isGeneric(((IArrayType) reference).getComponentType()); 1327 } 1328 return false; 1329 } 1330 1331 private ITypeReference getErasedType(ITypeReference reference) { 1332 1333 if (reference instanceof IParameterizedType) { 1334 return ((IParameterizedType) reference).getRawType(); 1335 } 1336 if (reference instanceof ITypeVariableReference) { 1337 ITypeVariableDefinition typeVariableDefinition = 1338 ((ITypeVariableReference) reference) 1339 .getTypeVariableDefinition(); 1340 return getErasedType( 1341 typeVariableDefinition.getUpperBounds().get(0)); 1342 } 1343 if (reference instanceof IWildcardType) { 1344 return getErasedType(((IWildcardType) reference).getUpperBounds() 1345 .get(0)); 1346 } 1347 if (reference instanceof IArrayType) { 1348 // FIXME implement with erasure projection? 1349 return new SigArrayType(getErasedType(((IArrayType) reference) 1350 .getComponentType())); 1351 } 1352 if (reference instanceof IPrimitiveType) { 1353 return reference; 1354 } 1355 if (reference instanceof IClassReference) { 1356 return reference; 1357 } 1358 throw new IllegalArgumentException("Unexpected type: " + reference); 1359 } 1360 1361 private boolean implementInterface(ITypeReference from, ITypeReference to, 1362 Class<?> check) { 1363 return check.isAssignableFrom(from.getClass()) 1364 && check.isAssignableFrom(to.getClass()); 1365 } 1366 1367 private IWildcardTypeDelta compareWildcardType(IWildcardType from, 1368 IWildcardType to) { 1369 SigWildcardTypeDelta delta = null; 1370 1371 ITypeReference fromLowerBound = from.getLowerBound(); 1372 ITypeReference toLowerBound = to.getLowerBound(); 1373 1374 ITypeReferenceDelta<?> lowerBoundDelta = compareType(fromLowerBound, 1375 toLowerBound, false); 1376 if (lowerBoundDelta != null) { 1377 delta = new SigWildcardTypeDelta(from, to); 1378 delta.setLowerBoundDelta(lowerBoundDelta); 1379 } 1380 1381 IUpperBoundsDelta upperBoundsDelta = compareUpperBounds(from 1382 .getUpperBounds(), to.getUpperBounds()); 1383 if (upperBoundsDelta != null) { 1384 if (delta == null) { 1385 delta = new SigWildcardTypeDelta(from, to); 1386 } 1387 delta.setUpperBoundDelta(upperBoundsDelta); 1388 } 1389 return delta; 1390 } 1391 1392 private IGenericDeclarationDelta compareGenericDeclaration( 1393 ITypeVariableDefinition fromVariable, 1394 ITypeVariableDefinition toVariable) { 1395 IGenericDeclarationDelta delta = null; 1396 1397 IGenericDeclaration from = fromVariable.getGenericDeclaration(); 1398 IGenericDeclaration to = toVariable.getGenericDeclaration(); 1399 1400 if (from != null && to != null) { 1401 1402 if (from.getClass() != to.getClass()) { 1403 delta = new SigGenericDeclarationDelta(from, to); 1404 } else if (from instanceof IClassDefinition) { 1405 IClassDefinition fromDeclaringClass = (IClassDefinition) from; 1406 IClassDefinition toDeclaringClass = (IClassDefinition) to; 1407 1408 if (!sameClassDefinition(fromDeclaringClass, 1409 toDeclaringClass)) { 1410 delta = new SigGenericDeclarationDelta(from, to); 1411 } 1412 1413 } else if (from instanceof IConstructor) { 1414 IConstructor fromConstructor = (IConstructor) from; 1415 IConstructor toConstructor = (IConstructor) from; 1416 1417 String fromConstructorName = fromConstructor.getName(); 1418 String fromClassName = fromConstructor.getDeclaringClass() 1419 .getQualifiedName(); 1420 1421 String toConstructorName = toConstructor.getName(); 1422 String toClassName = toConstructor.getDeclaringClass() 1423 .getQualifiedName(); 1424 1425 if ((!fromConstructorName.equals(toConstructorName)) 1426 || (!fromClassName.equals(toClassName))) { 1427 delta = new SigGenericDeclarationDelta(from, to); 1428 } 1429 1430 } else if (from instanceof IMethod) { 1431 IMethod fromMethod = (IMethod) from; 1432 IMethod toMethod = (IMethod) from; 1433 1434 String fromConstructorName = fromMethod.getName(); 1435 String fromClassName = fromMethod.getDeclaringClass() 1436 .getQualifiedName(); 1437 1438 String toConstructorName = toMethod.getName(); 1439 String toClassName = toMethod.getDeclaringClass() 1440 .getQualifiedName(); 1441 1442 if ((!fromConstructorName.equals(toConstructorName)) 1443 || (!fromClassName.equals(toClassName))) { 1444 delta = new SigGenericDeclarationDelta(from, to); 1445 } 1446 } else { 1447 throw new IllegalStateException("Invlaid eclaration site: " 1448 + from); 1449 } 1450 1451 // check position 1452 int fromPosition = getPositionOf(fromVariable, from); 1453 int toPosition = getPositionOf(toVariable, to); 1454 1455 if (fromPosition != toPosition) { 1456 delta = new SigGenericDeclarationDelta(from, to); 1457 } 1458 1459 1460 } else { 1461 // one of both is null 1462 delta = new SigGenericDeclarationDelta(from, to); 1463 } 1464 return delta; 1465 } 1466 1467 private int getPositionOf(ITypeVariableDefinition variable, 1468 IGenericDeclaration declaration) { 1469 return declaration.getTypeParameters().indexOf(variable); 1470 } 1471 1472 private IUpperBoundsDelta compareUpperBounds(List<ITypeReference> from, 1473 List<ITypeReference> to) { 1474 if (from.isEmpty() && to.isEmpty()) { 1475 return null; 1476 } 1477 SigUpperBoundsDelta delta = null; 1478 1479 ITypeReference fromFirstUpperBound = from.get(0); 1480 ITypeReference toFirstUpperBound = to.get(0); 1481 1482 ITypeReferenceDelta<?> firstUpperBoundDelta = compareType( 1483 fromFirstUpperBound, toFirstUpperBound, false); 1484 if (firstUpperBoundDelta != null) { 1485 delta = new SigUpperBoundsDelta(from, to); 1486 delta.setFirstUpperBoundDelta(firstUpperBoundDelta); 1487 } else { 1488 // normalize 1489 Set<ITypeReference> normalizedfrom = removeGeneralizations( 1490 new HashSet<ITypeReference>(from)); 1491 Set<ITypeReference> normalizedto = removeGeneralizations( 1492 new HashSet<ITypeReference>(to)); 1493 1494 Set<ITypeReferenceDelta<?>> remainingUpperBoundsDelta = 1495 compareTypes(normalizedfrom, normalizedto); 1496 if (remainingUpperBoundsDelta != null) { 1497 delta = new SigUpperBoundsDelta(from, to); 1498 delta.setRemainingUpperBoundDeltas(remainingUpperBoundsDelta); 1499 } 1500 } 1501 return delta; 1502 } 1503 1504 private Set<ITypeReference> removeGeneralizations( 1505 Set<ITypeReference> bounds) { 1506 Set<ITypeReference> boundsCopy = new HashSet<ITypeReference>(bounds); 1507 for (ITypeReference type : bounds) { 1508 Iterator<ITypeReference> it = boundsCopy.iterator(); 1509 while (it.hasNext()) { 1510 ITypeReference superType = it.next(); 1511 if (isSuperClass(getClassDefinition(superType), 1512 getClassDefinition(type)) 1513 || isSuperInterface(getClassDefinition(superType), 1514 getClassDefinition(type))) { 1515 it.remove(); 1516 } 1517 } 1518 } 1519 return boundsCopy; 1520 } 1521 1522 private IParameterizedTypeDelta compareParameterizedType( 1523 IParameterizedType from, IParameterizedType to, 1524 boolean ignoreTypeArguments) { 1525 1526 SigParameterizedTypeDelta delta = null; 1527 // check raw type 1528 ITypeReferenceDelta<?> rawTypeDelta = compareType(from.getRawType(), to 1529 .getRawType(), false); 1530 if (rawTypeDelta != null) { 1531 delta = new SigParameterizedTypeDelta(from, to); 1532 delta.setRawTypeDelta(rawTypeDelta); 1533 } else { 1534 // check owner type 1535 ITypeReferenceDelta<?> ownerTypeDelta = compareType(from 1536 .getOwnerType(), to.getOwnerType(), false); 1537 if (ownerTypeDelta != null) { 1538 delta = new SigParameterizedTypeDelta(from, to); 1539 delta.setOwnerTypeDelta(ownerTypeDelta); 1540 } else { 1541 // check argument type 1542 if (!ignoreTypeArguments) { 1543 Set<ITypeReferenceDelta<?>> argumentTypeDeltas = 1544 compareTypeSequence(from.getTypeArguments(), 1545 to.getTypeArguments(), false); 1546 if (argumentTypeDeltas != null) { 1547 delta = new SigParameterizedTypeDelta(from, to); 1548 delta.setArgumentTypeDeltas(argumentTypeDeltas); 1549 } 1550 } 1551 } 1552 } 1553 return delta; 1554 } 1555 1556 private Set<ITypeReferenceDelta<? extends ITypeReference>> compareTypeSequence( 1557 List<ITypeReference> from, List<ITypeReference> to, 1558 boolean ignoreTypeArguments) { 1559 Set<ITypeReferenceDelta<?>> deltas = 1560 new HashSet<ITypeReferenceDelta<?>>(); 1561 if (from.size() != to.size()) { 1562 1563 for (ITypeReference type : from) { 1564 deltas.add(new SigTypeDelta<ITypeReference>(type, null)); 1565 } 1566 for (ITypeReference type : to) { 1567 deltas.add(new SigTypeDelta<ITypeReference>(null, type)); 1568 } 1569 return deltas; 1570 } 1571 1572 Iterator<? extends ITypeReference> fromIterator = from.iterator(); 1573 Iterator<? extends ITypeReference> toIterator = to.iterator(); 1574 while (fromIterator.hasNext() && toIterator.hasNext()) { 1575 ITypeReferenceDelta<?> delta = compareType(fromIterator.next(), 1576 toIterator.next(), ignoreTypeArguments); 1577 if (delta != null) { 1578 deltas.add(delta); 1579 } 1580 } 1581 return deltas.isEmpty() ? null : deltas; 1582 } 1583 1584 private Set<ITypeReferenceDelta<? extends ITypeReference>> compareTypes( 1585 Set<ITypeReference> from, Set<ITypeReference> to) { 1586 return compareSets(from, to, 1587 new SigComparator<ITypeReference, ITypeReferenceDelta<? extends ITypeReference>>() { 1588 public ITypeReferenceDelta<? extends ITypeReference> createAddRemoveDelta( 1589 ITypeReference from, ITypeReference to) { 1590 return new SigTypeDelta<ITypeReference>(from, to); 1591 } 1592 1593 public boolean considerEqualElement(ITypeReference from, 1594 ITypeReference to) { 1595 return considerEqualTypes(from, to); 1596 } 1597 1598 public ITypeReferenceDelta<? extends ITypeReference> createChangedDelta( 1599 ITypeReference from, ITypeReference to) { 1600 return compareType(from, to, false); 1601 } 1602 }); 1603 } 1604 1605 private static interface SigComparator<T, S extends IDelta<? extends T>> { 1606 boolean considerEqualElement(T from, T to); 1607 1608 S createChangedDelta(T from, T to); 1609 1610 /** 1611 * If null is returned, it will be ignored. 1612 */ 1613 S createAddRemoveDelta(T from, T to); 1614 } 1615 1616 1617 private <T, S extends IDelta<? extends T>> Set<S> compareSets(Set<T> from, 1618 Set<T> to, SigComparator<T, S> comparator) { 1619 1620 Set<T> toCopy = new HashSet<T>(to); 1621 Set<S> deltas = new HashSet<S>(); 1622 1623 for (T fromType : from) { 1624 Iterator<T> toIterator = toCopy.iterator(); 1625 boolean equals = false; 1626 boolean hasNext = toIterator.hasNext(); 1627 1628 while (hasNext && !equals) { 1629 T toElement = toIterator.next(); 1630 equals = comparator.considerEqualElement(fromType, toElement); 1631 if (equals) { 1632 S compare = comparator.createChangedDelta(fromType, 1633 toElement); 1634 if (compare != null) { 1635 deltas.add(compare); 1636 } 1637 } 1638 hasNext = toIterator.hasNext(); 1639 } 1640 1641 if (equals) { 1642 toIterator.remove(); 1643 } else { 1644 S delta = comparator.createAddRemoveDelta(fromType, null); 1645 if (delta != null) { 1646 deltas.add(delta); 1647 } 1648 } 1649 } 1650 1651 for (T type : toCopy) { 1652 S delta = comparator.createAddRemoveDelta(null, type); 1653 if (delta != null) { 1654 deltas.add(delta); 1655 } 1656 } 1657 return deltas.isEmpty() ? null : deltas; 1658 } 1659 1660 1661 private ITypeReferenceDelta<?> compareArrayType(IArrayType from, 1662 IArrayType to) { 1663 ITypeReferenceDelta<?> componentTypeDelta = compareType(from 1664 .getComponentType(), to.getComponentType(), false); 1665 if (componentTypeDelta != null) { 1666 SigArrayTypeDelta delta = new SigArrayTypeDelta(from, to); 1667 delta.setComponentTypeDelta(componentTypeDelta); 1668 return delta; 1669 } 1670 return null; 1671 } 1672 1673 private ITypeReferenceDelta<IClassReference> compareClassReference( 1674 IClassReference fromRef, IClassReference toRef) { 1675 IClassDefinition from = fromRef.getClassDefinition(); 1676 IClassDefinition to = toRef.getClassDefinition(); 1677 1678 if (!sameClassDefinition(from, to)) { 1679 return new SigClassReferenceDelta(fromRef, toRef); 1680 } 1681 return null; 1682 } 1683 1684 1685 private boolean sameClassDefinition(IClassDefinition from, 1686 IClassDefinition to) { 1687 boolean sameName = from.getName().equals(to.getName()); 1688 boolean samePackage = from.getPackageName().equals(to.getPackageName()); 1689 1690 Kind fromKind = from.getKind(); 1691 Kind toKind = to.getKind(); 1692 boolean sameKind = (fromKind == null || toKind == null) 1693 || fromKind.equals(toKind); 1694 1695 return sameName && samePackage && sameKind; 1696 } 1697 1698 private IPrimitiveTypeDelta comparePrimitiveType(IPrimitiveType from, 1699 IPrimitiveType to) { 1700 if (!from.equals(to)) { 1701 return new SigPrimitiveTypeDelta(from, to); 1702 } 1703 return null; 1704 } 1705 } 1706