Skip to content

Commit

Permalink
#110 exceptions thrown by methods/constructors are evaluated regardin…
Browse files Browse the repository at this point in the history
…g source compatibility, extended reports
  • Loading branch information
siom79 committed Feb 24, 2016
1 parent 690a92a commit dc2f010
Show file tree
Hide file tree
Showing 14 changed files with 186 additions and 60 deletions.
4 changes: 2 additions & 2 deletions japicmp/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.15</version>
<version>2.17</version>
</plugin>
<plugin>
<groupId>com.github.siom79.japicmp</groupId>
Expand All @@ -99,7 +99,7 @@
<dependency>
<groupId>com.github.siom79.japicmp</groupId>
<artifactId>japicmp</artifactId>
<version>0.6.0</version>
<version>0.7.0</version>
</dependency>
</oldVersion>
<newVersion>
Expand Down
6 changes: 3 additions & 3 deletions japicmp/src/main/java/japicmp/cmp/ClassesComparator.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ private void sortIntoLists(Map<String, CtClass> oldClassesMap, Map<String, CtCla
CtClass newCtClass = newClassesMap.get(oldCtClass.getName());
if (newCtClass == null) {
JApiClassType classType = new JApiClassType(Optional.of(ClassHelper.getType(oldCtClass)), Optional.<JApiClassType.ClassType>absent(), JApiChangeStatus.REMOVED);
JApiClass jApiClass = new JApiClass(this.jarArchiveComparator, oldCtClass.getName(), Optional.of(oldCtClass), Optional.<CtClass>absent(), JApiChangeStatus.REMOVED, classType, options);
JApiClass jApiClass = new JApiClass(this.jarArchiveComparator, oldCtClass.getName(), Optional.of(oldCtClass), Optional.<CtClass>absent(), JApiChangeStatus.REMOVED, classType);
if (includeClass(jApiClass)) {
classes.add(jApiClass);
}
Expand All @@ -47,7 +47,7 @@ private void sortIntoLists(Map<String, CtClass> oldClassesMap, Map<String, CtCla
changeStatus = JApiChangeStatus.MODIFIED;
}
JApiClassType classType = new JApiClassType(Optional.of(oldType), Optional.of(newType), changeStatus);
JApiClass jApiClass = new JApiClass(this.jarArchiveComparator, oldCtClass.getName(), Optional.of(oldCtClass), Optional.of(newCtClass), changeStatus, classType, options);
JApiClass jApiClass = new JApiClass(this.jarArchiveComparator, oldCtClass.getName(), Optional.of(oldCtClass), Optional.of(newCtClass), changeStatus, classType);
if (includeClass(jApiClass)) {
classes.add(jApiClass);
}
Expand All @@ -58,7 +58,7 @@ private void sortIntoLists(Map<String, CtClass> oldClassesMap, Map<String, CtCla
if (oldCtClass == null) {
JApiClassType.ClassType newType = ClassHelper.getType(newCtClass);
JApiClassType classType = new JApiClassType(Optional.<JApiClassType.ClassType>absent(), Optional.of(newType), JApiChangeStatus.NEW);
JApiClass jApiClass = new JApiClass(this.jarArchiveComparator, newCtClass.getName(), Optional.<CtClass>absent(), Optional.of(newCtClass), JApiChangeStatus.NEW, classType, options);
JApiClass jApiClass = new JApiClass(this.jarArchiveComparator, newCtClass.getName(), Optional.<CtClass>absent(), Optional.of(newCtClass), JApiChangeStatus.NEW, classType);
if (includeClass(jApiClass)) {
classes.add(jApiClass);
}
Expand Down
49 changes: 49 additions & 0 deletions japicmp/src/main/java/japicmp/cmp/JarArchiveComparator.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package japicmp.cmp;

import com.google.common.base.Optional;
import japicmp.exception.JApiCmpException;
import japicmp.exception.JApiCmpException.Reason;
import japicmp.filter.AnnotationFilterBase;
Expand All @@ -8,6 +9,7 @@
import japicmp.filter.JavadocLikePackageFilter;
import japicmp.compat.CompatibilityChanges;
import japicmp.model.JApiClass;
import japicmp.model.JApiException;
import japicmp.model.JavaObjectSerializationCompatibility;
import japicmp.output.OutputFilter;
import japicmp.util.AnnotationHelper;
Expand Down Expand Up @@ -304,4 +306,51 @@ public ClassPool getOldClassPool() {
public ClassPool getNewClassPool() {
return newClassPool;
}

public enum ArchiveType {
OLD, NEW
}

/**
* Loads a class either from the old, new or common classpath.
* @param archiveType specify if this class should be loaded from the old or new class path
* @param name the name of the class (FQN)
* @return the loaded class (if options are not set to ignore missing classes)
* @throws japicmp.exception.JApiCmpException if loading the class fails
*/
public Optional<CtClass> loadClass(ArchiveType archiveType, String name) {
Optional<CtClass> loadedClass = Optional.absent();
if (this.options.getClassPathMode() == JarArchiveComparatorOptions.ClassPathMode.ONE_COMMON_CLASSPATH) {
try {
loadedClass = Optional.of(commonClassPool.get(name));
} catch (NotFoundException e) {
if (!options.isIgnoreMissingClasses()) {
throw JApiCmpException.forClassLoading(e, name, this);
}
}
} else if (this.options.getClassPathMode() == JarArchiveComparatorOptions.ClassPathMode.TWO_SEPARATE_CLASSPATHS) {
if (archiveType == ArchiveType.OLD) {
try {
loadedClass = Optional.of(oldClassPool.get(name));
} catch (NotFoundException e) {
if (!options.isIgnoreMissingClasses()) {
throw JApiCmpException.forClassLoading(e, name, this);
}
}
} else if (archiveType == ArchiveType.NEW) {
try {
loadedClass = Optional.of(newClassPool.get(name));
} catch (NotFoundException e) {
if (!options.isIgnoreMissingClasses()) {
throw JApiCmpException.forClassLoading(e, name, this);
}
}
} else {
throw new JApiCmpException(Reason.IllegalState, "Unknown archive type: " + archiveType);
}
} else {
throw new JApiCmpException(Reason.IllegalState, "Unknown classpath mode: " + this.options.getClassPathMode());
}
return loadedClass;
}
}
15 changes: 12 additions & 3 deletions japicmp/src/main/java/japicmp/compat/CompatibilityChanges.java
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ private void forAllSuperclasses(JApiClass jApiClass, Map<String, JApiClass> clas
} else {
classType = new JApiClassType(Optional.<JApiClassType.ClassType>absent(), Optional.<JApiClassType.ClassType>absent(), JApiChangeStatus.UNCHANGED);
}
foundClass = new JApiClass(this.jarArchiveComparator, newSuperclassName, oldClassOptional, newClassOptional, changeStatus, classType, this.jarArchiveComparator.getJarArchiveComparatorOptions());
foundClass = new JApiClass(this.jarArchiveComparator, newSuperclassName, oldClassOptional, newClassOptional, changeStatus, classType);
evaluate(Collections.singletonList(foundClass));
int returnValue = onSuperclassCallback.callback(foundClass, classMap);
returnValues.add(returnValue);
Expand Down Expand Up @@ -329,6 +329,15 @@ public int callback(JApiClass superclass, Map<String, JApiClass> classMap) {
addCompatibilityChange(method, JApiCompatibilityChange.METHOD_ADDED_TO_INTERFACE);
}
}
checkIfExceptionIsNowChecked(method);
}
}

private void checkIfExceptionIsNowChecked(JApiMethod method) {
for (JApiException exception : method.getExceptions()) {
if (exception.getChangeStatus() == JApiChangeStatus.NEW && exception.isCheckedException()) {
addCompatibilityChange(method, JApiCompatibilityChange.METHOD_NOW_THROWS_CHECKED_EXCEPTION);
}
}
}

Expand Down Expand Up @@ -439,10 +448,10 @@ public int callback(JApiClass superclass, Map<String, JApiClass> classMap) {
}
}
}
checkIfClassNowCheckedException(jApiClass, classMap);
checkIfClassNowCheckedException(jApiClass);
}

private void checkIfClassNowCheckedException(JApiClass jApiClass, Map<String, JApiClass> classMap) {
private void checkIfClassNowCheckedException(JApiClass jApiClass) {
JApiSuperclass jApiClassSuperclass = jApiClass.getSuperclass();
if (jApiClassSuperclass.getChangeStatus() == JApiChangeStatus.MODIFIED) {
if (jApiClassSuperclass.getNewSuperclassName().isPresent()) {
Expand Down
23 changes: 14 additions & 9 deletions japicmp/src/main/java/japicmp/model/JApiBehavior.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
package japicmp.model;

import com.google.common.base.Optional;
import japicmp.cmp.JarArchiveComparator;
import japicmp.cmp.JarArchiveComparatorOptions;
import japicmp.util.AnnotationHelper;
import japicmp.util.Constants;
import japicmp.util.ModifierHelper;
import japicmp.util.OptionalHelper;
import javassist.CtBehavior;
import javassist.CtConstructor;
import javassist.CtMethod;
import javassist.Modifier;
import javassist.*;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ExceptionsAttribute;

Expand All @@ -23,6 +21,7 @@ public class JApiBehavior implements JApiHasModifiers, JApiHasChangeStatus, JApi
JApiHasFinalModifier, JApiHasAbstractModifier, JApiCompatibility, JApiHasAnnotations, JApiHasBridgeModifier,
JApiCanBeSynthetic, JApiHasLineNumber {
private final String name;
private final JarArchiveComparator jarArchiveComparator;
private final List<JApiParameter> parameters = new LinkedList<>();
private final List<JApiAnnotation> annotations = new LinkedList<>();
private final JApiModifier<AccessModifier> accessModifier;
Expand All @@ -38,9 +37,10 @@ public class JApiBehavior implements JApiHasModifiers, JApiHasChangeStatus, JApi
private final Optional<Integer> newLineNumber;
private final List<JApiCompatibilityChange> compatibilityChanges = new ArrayList<>();

public JApiBehavior(String name, Optional<? extends CtBehavior> oldBehavior, Optional<? extends CtBehavior> newBehavior, JApiChangeStatus changeStatus, JarArchiveComparatorOptions options) {
public JApiBehavior(String name, Optional<? extends CtBehavior> oldBehavior, Optional<? extends CtBehavior> newBehavior, JApiChangeStatus changeStatus, JarArchiveComparator jarArchiveComparator) {
this.name = name;
computeAnnotationChanges(annotations, oldBehavior, newBehavior, options);
this.jarArchiveComparator = jarArchiveComparator;
computeAnnotationChanges(annotations, oldBehavior, newBehavior, jarArchiveComparator.getJarArchiveComparatorOptions());
this.accessModifier = extractAccessModifier(oldBehavior, newBehavior);
this.finalModifier = extractFinalModifier(oldBehavior, newBehavior);
this.staticModifier = extractStaticModifier(oldBehavior, newBehavior);
Expand All @@ -61,14 +61,14 @@ private List<JApiException> computeExceptionChanges(Optional<? extends CtBehavio
List<String> newExceptions = extractExceptions(newMethodOptional);
for (String oldException : oldExceptions) {
if (newExceptions.contains(oldException)) {
exceptionList.add(new JApiException(oldException, JApiChangeStatus.UNCHANGED));
exceptionList.add(new JApiException(jarArchiveComparator, oldException, jarArchiveComparator.loadClass(JarArchiveComparator.ArchiveType.NEW, oldException), JApiChangeStatus.UNCHANGED));
newExceptions.remove(oldException);
} else {
exceptionList.add(new JApiException(oldException, JApiChangeStatus.REMOVED));
exceptionList.add(new JApiException(jarArchiveComparator, oldException, jarArchiveComparator.loadClass(JarArchiveComparator.ArchiveType.OLD, oldException), JApiChangeStatus.REMOVED));
}
}
for (String newException : newExceptions) {
exceptionList.add(new JApiException(newException, JApiChangeStatus.NEW));
exceptionList.add(new JApiException(jarArchiveComparator, newException, jarArchiveComparator.loadClass(JarArchiveComparator.ArchiveType.NEW, newException), JApiChangeStatus.NEW));
}
}
return exceptionList;
Expand Down Expand Up @@ -153,6 +153,11 @@ private JApiChangeStatus evaluateChangeStatus(JApiChangeStatus changeStatus) {
if (this.syntheticAttribute.getChangeStatus() != JApiChangeStatus.UNCHANGED) {
changeStatus = JApiChangeStatus.MODIFIED;
}
for (JApiException jApiException : exceptions) {
if (jApiException.getChangeStatus() == JApiChangeStatus.NEW || jApiException.getChangeStatus() == JApiChangeStatus.REMOVED) {
changeStatus = JApiChangeStatus.MODIFIED;
}
}
}
return changeStatus;
}
Expand Down
22 changes: 11 additions & 11 deletions japicmp/src/main/java/japicmp/model/JApiClass.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ public class JApiClass implements JApiHasModifiers, JApiHasChangeStatus, JApiHas
private JApiJavaObjectSerializationChangeStatus jApiJavaObjectSerializationChangeStatus = JApiJavaObjectSerializationChangeStatus.NOT_SERIALIZABLE;
private boolean changeCausedByClassElement = false;

public JApiClass(JarArchiveComparator jarArchiveComparator, String fullyQualifiedName, Optional<CtClass> oldClass, Optional<CtClass> newClass, JApiChangeStatus changeStatus, JApiClassType classType, JarArchiveComparatorOptions options) {
public JApiClass(JarArchiveComparator jarArchiveComparator, String fullyQualifiedName, Optional<CtClass> oldClass, Optional<CtClass> newClass, JApiChangeStatus changeStatus, JApiClassType classType) {
this.jarArchiveComparator = jarArchiveComparator;
this.options = this.jarArchiveComparator.getJarArchiveComparatorOptions();
this.fullyQualifiedName = fullyQualifiedName;
this.newClass = newClass;
this.oldClass = oldClass;
this.classType = classType;
this.options = options;
this.superclass = extractSuperclass(oldClass, newClass);
computeMethodChanges(oldClass, newClass);
computeInterfaceChanges(this.interfaces, oldClass, newClass);
Expand Down Expand Up @@ -304,7 +304,7 @@ private void sortMethodsIntoLists(Map<String, List<CtMethod>> oldMethodsMap, Map
methodDescriptorParser.parse(oldMethod.getSignature());
List<CtMethod> newMethodsWithSameName = newMethodsMap.get(methodName);
if (newMethodsWithSameName == null) {
JApiMethod jApiMethod = new JApiMethod(oldMethod.getName(), JApiChangeStatus.REMOVED, Optional.of(oldMethod), Optional.<CtMethod>absent(), options);
JApiMethod jApiMethod = new JApiMethod(oldMethod.getName(), JApiChangeStatus.REMOVED, Optional.of(oldMethod), Optional.<CtMethod>absent(), jarArchiveComparator);
addParametersToMethod(methodDescriptorParser, jApiMethod);
if (includeMethod(jApiMethod)) {
methods.add(jApiMethod);
Expand All @@ -313,15 +313,15 @@ private void sortMethodsIntoLists(Map<String, List<CtMethod>> oldMethodsMap, Map
Optional<CtMethod> matchingMethodOptional = findMatchingMethod(oldMethod, newMethodsWithSameName);
if (matchingMethodOptional.isPresent()) {
CtMethod matchingMethod = matchingMethodOptional.get();
JApiMethod jApiMethod = new JApiMethod(oldMethod.getName(), JApiChangeStatus.UNCHANGED, Optional.of(oldMethod), Optional.of(matchingMethod), options);
JApiMethod jApiMethod = new JApiMethod(oldMethod.getName(), JApiChangeStatus.UNCHANGED, Optional.of(oldMethod), Optional.of(matchingMethod), jarArchiveComparator);
addParametersToMethod(methodDescriptorParser, jApiMethod);
if (includeMethod(jApiMethod)) {
methods.add(jApiMethod);
}
oldMethodsWithSameNameIterator.remove();
newMethodsWithSameName.remove(matchingMethod);
} else {
JApiMethod jApiMethod = new JApiMethod(oldMethod.getName(), JApiChangeStatus.REMOVED, Optional.of(oldMethod), Optional.<CtMethod>absent(), options);
JApiMethod jApiMethod = new JApiMethod(oldMethod.getName(), JApiChangeStatus.REMOVED, Optional.of(oldMethod), Optional.<CtMethod>absent(), jarArchiveComparator);
addParametersToMethod(methodDescriptorParser, jApiMethod);
if (includeMethod(jApiMethod)) {
methods.add(jApiMethod);
Expand All @@ -336,7 +336,7 @@ private void sortMethodsIntoLists(Map<String, List<CtMethod>> oldMethodsMap, Map
methodDescriptorParser.parse(ctMethod.getSignature());
List<CtMethod> methodsWithSameName = oldMethodsMap.get(ctMethod.getName());
if (methodsWithSameName == null) {
JApiMethod jApiMethod = new JApiMethod(ctMethod.getName(), JApiChangeStatus.NEW, Optional.<CtMethod>absent(), Optional.of(ctMethod), options);
JApiMethod jApiMethod = new JApiMethod(ctMethod.getName(), JApiChangeStatus.NEW, Optional.<CtMethod>absent(), Optional.of(ctMethod), jarArchiveComparator);
addParametersToMethod(methodDescriptorParser, jApiMethod);
if (includeMethod(jApiMethod)) {
methods.add(jApiMethod);
Expand All @@ -345,13 +345,13 @@ private void sortMethodsIntoLists(Map<String, List<CtMethod>> oldMethodsMap, Map
Optional<CtMethod> matchingMethodOptional = findMatchingMethod(ctMethod, methodsWithSameName);
if (matchingMethodOptional.isPresent()) {
CtMethod matchingMethod = matchingMethodOptional.get();
JApiMethod jApiMethod = new JApiMethod(ctMethod.getName(), JApiChangeStatus.UNCHANGED, Optional.of(ctMethod), Optional.of(matchingMethod), options);
JApiMethod jApiMethod = new JApiMethod(ctMethod.getName(), JApiChangeStatus.UNCHANGED, Optional.of(ctMethod), Optional.of(matchingMethod), jarArchiveComparator);
addParametersToMethod(methodDescriptorParser, jApiMethod);
if (includeMethod(jApiMethod)) {
methods.add(jApiMethod);
}
} else {
JApiMethod jApiMethod = new JApiMethod(ctMethod.getName(), JApiChangeStatus.NEW, Optional.<CtMethod>absent(), Optional.of(ctMethod), options);
JApiMethod jApiMethod = new JApiMethod(ctMethod.getName(), JApiChangeStatus.NEW, Optional.<CtMethod>absent(), Optional.of(ctMethod), jarArchiveComparator);
addParametersToMethod(methodDescriptorParser, jApiMethod);
if (includeMethod(jApiMethod)) {
methods.add(jApiMethod);
Expand Down Expand Up @@ -422,13 +422,13 @@ private void sortConstructorsIntoLists(Map<String, CtConstructor> oldConstructor
methodDescriptorParser.parse(ctMethod.getSignature());
CtConstructor foundMethod = newConstructorsMap.get(longName);
if (foundMethod == null) {
JApiConstructor jApiConstructor = new JApiConstructor(ctMethod.getName(), JApiChangeStatus.REMOVED, Optional.of(ctMethod), Optional.<CtConstructor>absent(), options);
JApiConstructor jApiConstructor = new JApiConstructor(ctMethod.getName(), JApiChangeStatus.REMOVED, Optional.of(ctMethod), Optional.<CtConstructor>absent(), jarArchiveComparator);
addParametersToMethod(methodDescriptorParser, jApiConstructor);
if (includeConstructor(jApiConstructor)) {
constructors.add(jApiConstructor);
}
} else {
JApiConstructor jApiConstructor = new JApiConstructor(ctMethod.getName(), JApiChangeStatus.UNCHANGED, Optional.of(ctMethod), Optional.of(foundMethod), options);
JApiConstructor jApiConstructor = new JApiConstructor(ctMethod.getName(), JApiChangeStatus.UNCHANGED, Optional.of(ctMethod), Optional.of(foundMethod), jarArchiveComparator);
addParametersToMethod(methodDescriptorParser, jApiConstructor);
if (includeConstructor(jApiConstructor)) {
constructors.add(jApiConstructor);
Expand All @@ -440,7 +440,7 @@ private void sortConstructorsIntoLists(Map<String, CtConstructor> oldConstructor
methodDescriptorParser.parse(ctMethod.getSignature());
CtConstructor foundMethod = oldConstructorsMap.get(longName);
if (foundMethod == null) {
JApiConstructor jApiConstructor = new JApiConstructor(ctMethod.getName(), JApiChangeStatus.NEW, Optional.<CtConstructor>absent(), Optional.of(ctMethod), options);
JApiConstructor jApiConstructor = new JApiConstructor(ctMethod.getName(), JApiChangeStatus.NEW, Optional.<CtConstructor>absent(), Optional.of(ctMethod), jarArchiveComparator);
addParametersToMethod(methodDescriptorParser, jApiConstructor);
if (includeConstructor(jApiConstructor)) {
constructors.add(jApiConstructor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public enum JApiCompatibilityChange {
METHOD_NOW_STATIC(false, false),
METHOD_NO_LONGER_STATIC(false, false),
METHOD_ADDED_TO_INTERFACE(true, false),
METHOD_NOW_THROWS_CHECKED_EXCEPTION(true, false),
FIELD_STATIC_AND_OVERRIDES_STATIC(false, false),
FIELD_LESS_ACCESSIBLE_THAN_IN_SUPERCLASS(false, false),
FIELD_NOW_FINAL(false, false),
Expand Down
5 changes: 3 additions & 2 deletions japicmp/src/main/java/japicmp/model/JApiConstructor.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package japicmp.model;

import com.google.common.base.Optional;
import japicmp.cmp.JarArchiveComparator;
import japicmp.cmp.JarArchiveComparatorOptions;
import javassist.CtConstructor;

Expand All @@ -10,8 +11,8 @@ public class JApiConstructor extends JApiBehavior {
private final Optional<CtConstructor> oldConstructor;
private final Optional<CtConstructor> newConstructor;

public JApiConstructor(String name, JApiChangeStatus changeStatus, Optional<CtConstructor> oldConstructor, Optional<CtConstructor> newConstructor, JarArchiveComparatorOptions options) {
super(name, oldConstructor, newConstructor, changeStatus, options);
public JApiConstructor(String name, JApiChangeStatus changeStatus, Optional<CtConstructor> oldConstructor, Optional<CtConstructor> newConstructor, JarArchiveComparator jarArchiveComparator) {
super(name, oldConstructor, newConstructor, changeStatus, jarArchiveComparator);
this.oldConstructor = oldConstructor;
this.newConstructor = newConstructor;
}
Expand Down
Loading

0 comments on commit dc2f010

Please sign in to comment.