use of org.revapi.Difference in project revapi by revapi.
the class NowImplementsInterface method doEnd.
@Override
protected List<Difference> doEnd() {
CheckBase.ActiveElements<JavaTypeElement> types = popIfActive();
if (types == null) {
return null;
}
List<Difference> result = new ArrayList<>();
List<? extends TypeMirror> newInterfaces = types.newElement.getDeclaringElement().getInterfaces();
List<? extends TypeMirror> oldInterfaces = types.oldElement.getDeclaringElement().getInterfaces();
for (TypeMirror newIface : newInterfaces) {
if (!Util.isSubtype(newIface, oldInterfaces, getNewTypeEnvironment().getTypeUtils())) {
result.add(createDifference(Code.CLASS_NOW_IMPLEMENTS_INTERFACE, Code.attachmentsFor(types.oldElement, types.newElement, "interface", Util.toHumanReadableString(newIface))));
}
}
return result;
}
use of org.revapi.Difference in project revapi by revapi.
the class Added method doEnd.
@Override
protected List<Difference> doEnd() {
ActiveElements<JavaMethodElement> methods = popIfActive();
if (methods == null) {
return null;
}
// we need to consider several cases here:
// 1) method added to a interface
// 2) method added to a final class
// 3) concrete method added to a non-final class
// 4) abstract method added to a non-final class
// 5) final method added to a non-final class
// 5) previously inherited method is now declared in class
ExecutableElement method = methods.newElement.getDeclaringElement();
if (methods.newElement.getParent() == null) {
LOG.warn("Could not find an enclosing class of method " + method + ". That's weird.");
return null;
}
TypeElement enclosingClass = (TypeElement) methods.newElement.getParent().getDeclaringElement();
Difference difference;
if (enclosingClass.getKind() == ElementKind.INTERFACE) {
if (method.isDefault()) {
difference = createDifference(Code.METHOD_DEFAULT_METHOD_ADDED_TO_INTERFACE, Code.attachmentsFor(methods.oldElement, methods.newElement));
} else if (method.getModifiers().contains(Modifier.STATIC)) {
// statics on interface can only be called using the interface they are declared on, even if a method
// with a same signature was declared on some of the super types in the old version, the users would
// not have been able to call those methods using the current type. So we don't need to specialize here
// based on the presence of a previously inherited method.
difference = createDifference(Code.METHOD_STATIC_METHOD_ADDED_TO_INTERFACE, Code.attachmentsFor(methods.oldElement, methods.newElement));
} else {
difference = createDifference(Code.METHOD_ADDED_TO_INTERFACE, Code.attachmentsFor(methods.oldElement, methods.newElement));
}
} else if (method.getModifiers().contains(Modifier.ABSTRACT)) {
difference = createDifference(Code.METHOD_ABSTRACT_METHOD_ADDED, Code.attachmentsFor(methods.oldElement, methods.newElement));
} else if (method.getModifiers().contains(Modifier.FINAL) && !enclosingClass.getModifiers().contains(Modifier.FINAL)) {
difference = createDifference(Code.METHOD_FINAL_METHOD_ADDED_TO_NON_FINAL_CLASS, Code.attachmentsFor(methods.oldElement, methods.newElement));
} else {
difference = createDifference(Code.METHOD_ADDED, Code.attachmentsFor(methods.oldElement, methods.newElement));
}
return Collections.singletonList(difference);
}
use of org.revapi.Difference in project revapi by revapi.
the class TextReporter method report.
@Override
public void report(@Nonnull Report report) {
if (report.getDifferences().isEmpty()) {
return;
}
DifferenceSeverity maxReportedSeverity = DifferenceSeverity.NON_BREAKING;
for (Difference d : report.getDifferences()) {
for (DifferenceSeverity c : d.classification.values()) {
if (c.compareTo(maxReportedSeverity) > 0) {
maxReportedSeverity = c;
}
}
}
if (maxReportedSeverity.compareTo(minLevel) < 0) {
return;
}
reports.add(report);
}
use of org.revapi.Difference in project revapi by revapi.
the class InheritanceChainChanged method doEnd.
@Override
protected List<Difference> doEnd() {
ActiveElements<JavaTypeElement> types = popIfActive();
if (types != null) {
List<Difference> ret = new ArrayList<>();
@SuppressWarnings("unchecked") List<TypeMirror> oldSuperClasses = (List<TypeMirror>) types.context[0];
@SuppressWarnings("unchecked") List<TypeMirror> newSuperClasses = (List<TypeMirror>) types.context[1];
Comparator<TypeMirror> typeNameComparator = Comparator.comparing(Util::toUniqueString);
List<TypeMirror> removedSuperClasses = new ArrayList<>();
List<TypeMirror> addedSuperClasses = new ArrayList<>();
oldSuperClasses.sort(typeNameComparator);
newSuperClasses.sort(typeNameComparator);
CoIterator<TypeMirror> iterator = new CoIterator<>(oldSuperClasses.iterator(), newSuperClasses.iterator(), typeNameComparator);
while (iterator.hasNext()) {
iterator.next();
TypeMirror oldType = iterator.getLeft();
TypeMirror newType = iterator.getRight();
if (oldType == null) {
addedSuperClasses.add(newType);
} else if (newType == null) {
removedSuperClasses.add(oldType);
}
}
// this will give us the equivalent of removed/added superclasses but ordered by the inheritance chain
// not by name
removedSuperClasses = retainInCopy(oldSuperClasses, removedSuperClasses);
addedSuperClasses = retainInCopy(newSuperClasses, addedSuperClasses);
Iterator<TypeMirror> removedIt = removedSuperClasses.iterator();
Iterator<TypeMirror> addedIt = addedSuperClasses.iterator();
// always report the most concrete classes
if (removedIt.hasNext()) {
removedIt.next();
}
if (addedIt.hasNext()) {
addedIt.next();
}
// ok, now we only have super types left of the most concrete removed/added super class.
// we are only going to report those that changed their inheritance hierarchy in the other version of the API.
removeClassesWithEquivalentSuperClassChain(removedIt, getOldTypeEnvironment(), getNewTypeEnvironment());
removeClassesWithEquivalentSuperClassChain(addedIt, getNewTypeEnvironment(), getOldTypeEnvironment());
for (TypeMirror t : removedSuperClasses) {
String str = Util.toHumanReadableString(t);
ret.add(createDifference(Code.CLASS_NO_LONGER_INHERITS_FROM_CLASS, Code.attachmentsFor(types.oldElement, types.newElement, "superClass", str)));
}
for (TypeMirror t : addedSuperClasses) {
String str = Util.toHumanReadableString(t);
Code code = types.oldElement.getDeclaringElement().getModifiers().contains(Modifier.FINAL) ? Code.CLASS_FINAL_CLASS_INHERITS_FROM_NEW_CLASS : Code.CLASS_NON_FINAL_CLASS_INHERITS_FROM_NEW_CLASS;
ret.add(createDifference(code, Code.attachmentsFor(types.oldElement, types.newElement, "superClass", str)));
// additionally add a difference about checked exceptions
if (changedToCheckedException(getNewTypeEnvironment().getTypeUtils(), t, oldSuperClasses)) {
ret.add(createDifference(Code.CLASS_NOW_CHECKED_EXCEPTION, Code.attachmentsFor(types.oldElement, types.newElement)));
}
}
return ret;
}
return null;
}
use of org.revapi.Difference in project revapi by revapi.
the class FormalTypeParametersChanged method doEnd.
@Nullable
@Override
protected List<Difference> doEnd() {
ActiveElements<JavaModelElement> els = popIfActive();
if (els == null) {
return null;
}
@SuppressWarnings("unchecked") List<TypeParameterElement> added = (List<TypeParameterElement>) els.context[0];
@SuppressWarnings("unchecked") List<TypeParameterElement> removed = (List<TypeParameterElement>) els.context[1];
@SuppressWarnings("unchecked") Map<TypeParameterElement, TypeParameterElement> changed = (Map<TypeParameterElement, TypeParameterElement>) els.context[2];
Parameterizable oldT = (Parameterizable) els.oldElement.getDeclaringElement();
List<Difference> diffs = new ArrayList<>();
if (oldT.getTypeParameters().isEmpty()) {
diffs.add(createDifference(Code.GENERICS_ELEMENT_NOW_PARAMETERIZED, Code.attachmentsFor(els.oldElement, els.newElement)));
}
for (TypeParameterElement e : added) {
diffs.add(createDifferenceWithExplicitParams(Code.GENERICS_FORMAL_TYPE_PARAMETER_ADDED, Code.attachmentsFor(els.oldElement, els.newElement), Util.toHumanReadableString(e)));
}
for (TypeParameterElement e : removed) {
diffs.add(createDifferenceWithExplicitParams(Code.GENERICS_FORMAL_TYPE_PARAMETER_REMOVED, Code.attachmentsFor(els.oldElement, els.newElement), Util.toHumanReadableString(e)));
}
for (Map.Entry<TypeParameterElement, TypeParameterElement> e : changed.entrySet()) {
String oldP = Util.toHumanReadableString(e.getKey());
String newP = Util.toHumanReadableString(e.getValue());
diffs.add(createDifferenceWithExplicitParams(Code.GENERICS_FORMAL_TYPE_PARAMETER_CHANGED, Code.attachmentsFor(els.oldElement, els.newElement, "oldTypeParameter", oldP, "newTypeParameter", newP), oldP, newP));
}
return diffs;
}
Aggregations