use of org.revapi.Difference in project revapi by revapi.
the class ExceptionsThrownChanged method doEnd.
@Nullable
@Override
protected List<Difference> doEnd() {
ActiveElements<JavaMethodElement> methods = popIfActive();
if (methods == null) {
return null;
}
List<? extends TypeMirror> oldExceptions = new ArrayList<>(methods.oldElement.getModelRepresentation().getThrownTypes());
List<? extends TypeMirror> newExceptions = new ArrayList<>(methods.newElement.getModelRepresentation().getThrownTypes());
Comparator<TypeMirror> byClassName = Comparator.comparing(Util::toUniqueString);
Collections.sort(oldExceptions, byClassName);
Collections.sort(newExceptions, byClassName);
CoIterator<TypeMirror> it = new CoIterator<>(oldExceptions.iterator(), newExceptions.iterator(), byClassName);
List<String> removedRuntimeExceptions = new ArrayList<>();
List<String> addedRuntimeExceptions = new ArrayList<>();
List<String> removedCheckedExceptions = new ArrayList<>();
List<String> addedCheckedExceptions = new ArrayList<>();
boolean reportSomething = false;
while (it.hasNext()) {
it.next();
TypeMirror oldType = it.getLeft();
TypeMirror newType = it.getRight();
if (oldType != null && newType != null) {
// they match, so move on, nothing to report here
continue;
}
reportSomething = true;
TypeElement oldException = oldType == null ? null : oldType.accept(CONVERT_TO_ELEMENT, null);
TypeElement newException = newType == null ? null : newType.accept(CONVERT_TO_ELEMENT, null);
if (oldException != null) {
if (isRuntimeException(oldException)) {
removedRuntimeExceptions.add(oldException.getQualifiedName().toString());
} else {
removedCheckedExceptions.add(oldException.getQualifiedName().toString());
}
} else if (newException != null) {
if (isRuntimeException(newException)) {
addedRuntimeExceptions.add(newException.getQualifiedName().toString());
} else {
addedCheckedExceptions.add(newException.getQualifiedName().toString());
}
}
}
if (!reportSomething) {
return null;
}
List<Difference> ret = new ArrayList<>();
if (!removedRuntimeExceptions.isEmpty()) {
removedRuntimeExceptions.forEach(ex -> ret.add(createDifference(Code.METHOD_RUNTIME_EXCEPTION_REMOVED, Code.attachmentsFor(methods.oldElement, methods.newElement, "exception", ex))));
}
if (!addedRuntimeExceptions.isEmpty()) {
addedRuntimeExceptions.forEach(ex -> ret.add(createDifference(Code.METHOD_RUNTIME_EXCEPTION_ADDED, Code.attachmentsFor(methods.oldElement, methods.newElement, "exception", ex))));
}
if (!addedCheckedExceptions.isEmpty()) {
addedCheckedExceptions.forEach(ex -> ret.add(createDifference(Code.METHOD_CHECKED_EXCEPTION_ADDED, Code.attachmentsFor(methods.oldElement, methods.newElement, "exception", ex))));
}
if (!removedCheckedExceptions.isEmpty()) {
removedCheckedExceptions.forEach(ex -> ret.add(createDifference(Code.METHOD_CHECKED_EXCEPTION_REMOVED, Code.attachmentsFor(methods.oldElement, methods.newElement, "exception", ex))));
}
return ret;
}
use of org.revapi.Difference in project revapi by revapi.
the class NoLongerImplementsInterface method doEnd.
@Override
protected List<Difference> doEnd() {
ActiveElements<JavaTypeElement> types = popIfActive();
if (types == null) {
return null;
}
List<Difference> result = new ArrayList<>();
@SuppressWarnings("unchecked") List<TypeMirror> oldInterfaces = (List<TypeMirror>) types.context[0];
@SuppressWarnings("unchecked") List<TypeMirror> newInterfaces = (List<TypeMirror>) types.context[1];
for (TypeMirror oldIface : oldInterfaces) {
if (!Util.isSubtype(oldIface, newInterfaces, getOldTypeEnvironment().getTypeUtils())) {
result.add(createDifference(Code.CLASS_NO_LONGER_IMPLEMENTS_INTERFACE, Code.attachmentsFor(types.oldElement, types.newElement, "interface", Util.toHumanReadableString(oldIface))));
}
}
return result;
}
use of org.revapi.Difference in project revapi by revapi.
the class Removed method doEnd.
@Override
protected List<Difference> doEnd() {
ActiveElements<JavaTypeElement> types = popIfActive();
if (types != null) {
TypeElement typeInNew = getNewTypeEnvironment().getElementUtils().getTypeElement(types.oldElement.getDeclaringElement().getQualifiedName());
Difference difference = typeInNew == null ? createDifference(Code.CLASS_REMOVED, Code.attachmentsFor(types.oldElement, types.newElement)) : createDifference(Code.CLASS_EXTERNAL_CLASS_NO_LONGER_EXPOSED_IN_API, Code.attachmentsFor(types.oldElement, types.newElement));
return Collections.singletonList(difference);
}
return null;
}
use of org.revapi.Difference in project revapi by revapi.
the class BuildTimeReporter method getAllProblemsMessage.
public String getAllProblemsMessage() {
StringBuilder errors = new StringBuilder("The following API problems caused the build to fail:\n");
StringBuilder ignores = new StringBuilder();
for (Report r : allProblems) {
Element element = r.getNewElement();
Archive archive;
if (element == null) {
element = r.getOldElement();
assert element != null;
archive = shouldOutputArchive(oldApi, element.getArchive()) ? element.getArchive() : null;
} else {
archive = shouldOutputArchive(newApi, element.getArchive()) ? element.getArchive() : null;
}
for (Difference d : r.getDifferences()) {
if (isReportable(d)) {
errors.append(d.code).append(": ").append(element.getFullHumanReadableString()).append(": ").append(d.description);
if (archive != null) {
errors.append(" [").append(archive.getName()).append("]");
}
errors.append("\n");
ignores.append("{\n");
ignores.append(" \"code\": \"").append(escape(d.code)).append("\",\n");
if (r.getOldElement() != null) {
ignores.append(" \"old\": \"").append(escape(r.getOldElement())).append("\",\n");
}
if (r.getNewElement() != null) {
ignores.append(" \"new\": \"").append(escape(r.getNewElement())).append("\",\n");
}
for (Map.Entry<String, String> e : d.attachments.entrySet()) {
ignores.append(" \"").append(escape(e.getKey())).append("\": \"").append(escape(e.getValue())).append("\",\n");
}
ignores.append(" \"justification\": <<<<< ADD YOUR EXPLANATION FOR THE NECESSITY OF THIS CHANGE" + " >>>>>\n");
ignores.append("},\n");
}
}
}
if (errors.length() == 0) {
return null;
} else {
ignores.replace(ignores.length() - 2, ignores.length(), "");
return errors.toString() + "\nIf you're using the semver-ignore extension, update your module's version to one compatible " + "with the current changes (e.g. mvn package revapi:update-versions). If you want to " + "explicitly ignore this change and provide a justification for it, add the following JSON snippet " + "to your Revapi configuration under \"revapi.ignore\" path:\n" + ignores.toString();
}
}
use of org.revapi.Difference in project revapi by revapi.
the class AbstractJavaElementAnalyzerTest method containsDifference.
protected boolean containsDifference(List<Report> problems, String oldElement, String newElement, String differenceCode) {
for (Report r : problems) {
boolean oldTypeMatches = oldElement == null ? r.getOldElement() == null : r.getOldElement() != null && oldElement.equals(r.getOldElement().getFullHumanReadableString());
boolean newTypeMatches = newElement == null ? r.getNewElement() == null : r.getNewElement() != null && newElement.equals(r.getNewElement().getFullHumanReadableString());
boolean problemMatches = false;
for (Difference p : r.getDifferences()) {
if (differenceCode.equals(p.code)) {
problemMatches = true;
break;
}
}
if (oldTypeMatches && newTypeMatches && problemMatches) {
return true;
}
}
return false;
}
Aggregations