Search in sources :

Example 1 with Code

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

Example 2 with Code

use of org.revapi.java.spi.Code in project revapi by revapi.

the class ReturnTypeChanged method doEnd.

@Nullable
@Override
protected List<Difference> doEnd() {
    ActiveElements<JavaMethodElement> methods = popIfActive();
    if (methods == null) {
        return null;
    }
    TypeMirror oldReturnType = methods.oldElement.getModelRepresentation().getReturnType();
    TypeMirror newReturnType = methods.newElement.getModelRepresentation().getReturnType();
    TypeMirror erasedOldType = getOldTypeEnvironment().getTypeUtils().erasure(oldReturnType);
    TypeMirror erasedNewType = getNewTypeEnvironment().getTypeUtils().erasure(newReturnType);
    String oldR = Util.toUniqueString(oldReturnType);
    String newR = Util.toUniqueString(newReturnType);
    String oldER = Util.toUniqueString(erasedOldType);
    String newER = Util.toUniqueString(erasedNewType);
    Code code = null;
    if (!oldER.equals(newER)) {
        // we need to check if the returned type changed covariantly or not.
        if (isPrimitiveOrVoid(erasedOldType) || isPrimitiveOrVoid(erasedNewType)) {
            code = Code.METHOD_RETURN_TYPE_CHANGED;
        } else if (isCovariant(erasedOldType, erasedNewType)) {
            code = Code.METHOD_RETURN_TYPE_CHANGED_COVARIANTLY;
        } else {
            code = Code.METHOD_RETURN_TYPE_CHANGED;
        }
    } else {
        if (!oldR.equals(newR)) {
            code = Code.METHOD_RETURN_TYPE_TYPE_PARAMETERS_CHANGED;
        }
    }
    String oldHR = Util.toHumanReadableString(oldReturnType);
    String newHR = Util.toHumanReadableString(newReturnType);
    return code == null ? null : Collections.singletonList(createDifference(code, Code.attachmentsFor(methods.oldElement, methods.newElement, "oldType", oldHR, "newType", newHR)));
}
Also used : TypeMirror(javax.lang.model.type.TypeMirror) JavaMethodElement(org.revapi.java.spi.JavaMethodElement) Code(org.revapi.java.spi.Code) Nullable(javax.annotation.Nullable)

Example 3 with Code

use of org.revapi.java.spi.Code in project revapi by revapi.

the class MovedInHierarchy method doEnd.

@Nullable
@Override
protected List<Difference> doEnd() {
    ActiveElements<JavaModelElement> els = popIfActive();
    if (els == null) {
        return null;
    }
    String oldType = Util.toHumanReadableString(els.oldElement.getDeclaringElement().getEnclosingElement().asType());
    String newType = Util.toHumanReadableString(els.newElement.getDeclaringElement().getEnclosingElement().asType());
    // we know that oldEl.isInherited() != newEl.isInherited(), so it's enough to just check for the old
    Code code = els.oldElement.isInherited() ? moveDown : moveUp;
    return Collections.singletonList(createDifference(code, Code.attachmentsFor(els.oldElement, els.newElement, "oldClass", oldType, "newClass", newType)));
}
Also used : JavaModelElement(org.revapi.java.spi.JavaModelElement) Code(org.revapi.java.spi.Code) Nullable(javax.annotation.Nullable)

Aggregations

Code (org.revapi.java.spi.Code)3 Nullable (javax.annotation.Nullable)2 TypeMirror (javax.lang.model.type.TypeMirror)2 ArrayList (java.util.ArrayList)1 List (java.util.List)1 CoIterator (org.revapi.CoIterator)1 Difference (org.revapi.Difference)1 JavaMethodElement (org.revapi.java.spi.JavaMethodElement)1 JavaModelElement (org.revapi.java.spi.JavaModelElement)1 JavaTypeElement (org.revapi.java.spi.JavaTypeElement)1 Util (org.revapi.java.spi.Util)1