Search in sources :

Example 16 with Difference

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;
}
Also used : CoIterator(org.revapi.CoIterator) JavaMethodElement(org.revapi.java.spi.JavaMethodElement) TypeElement(javax.lang.model.element.TypeElement) ArrayList(java.util.ArrayList) Util(org.revapi.java.spi.Util) Difference(org.revapi.Difference) TypeMirror(javax.lang.model.type.TypeMirror) Nullable(javax.annotation.Nullable)

Example 17 with Difference

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;
}
Also used : TypeMirror(javax.lang.model.type.TypeMirror) ArrayList(java.util.ArrayList) List(java.util.List) ArrayList(java.util.ArrayList) Difference(org.revapi.Difference) JavaTypeElement(org.revapi.java.spi.JavaTypeElement)

Example 18 with Difference

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;
}
Also used : JavaTypeElement(org.revapi.java.spi.JavaTypeElement) TypeElement(javax.lang.model.element.TypeElement) Difference(org.revapi.Difference) JavaTypeElement(org.revapi.java.spi.JavaTypeElement)

Example 19 with Difference

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();
    }
}
Also used : Archive(org.revapi.Archive) Report(org.revapi.Report) Element(org.revapi.Element) Difference(org.revapi.Difference) Map(java.util.Map)

Example 20 with Difference

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;
}
Also used : Report(org.revapi.Report) Difference(org.revapi.Difference)

Aggregations

Difference (org.revapi.Difference)22 ArrayList (java.util.ArrayList)7 Test (org.junit.Test)6 AnalysisContext (org.revapi.AnalysisContext)6 JavaTypeElement (org.revapi.java.spi.JavaTypeElement)6 TypeElement (javax.lang.model.element.TypeElement)5 Map (java.util.Map)4 TypeMirror (javax.lang.model.type.TypeMirror)4 Report (org.revapi.Report)4 List (java.util.List)3 JavaMethodElement (org.revapi.java.spi.JavaMethodElement)3 Nullable (javax.annotation.Nullable)2 AnnotationValue (javax.lang.model.element.AnnotationValue)2 ExecutableElement (javax.lang.model.element.ExecutableElement)2 CoIterator (org.revapi.CoIterator)2 DifferenceSeverity (org.revapi.DifferenceSeverity)2 Element (org.revapi.Element)2 Util (org.revapi.java.spi.Util)2 HashMap (java.util.HashMap)1 LinkedHashMap (java.util.LinkedHashMap)1