use of org.revapi.java.spi.Util in project revapi by revapi.
the class SerialVersionUidChecker method computeStructuralId.
public static long computeStructuralId(TypeElement type, TypeEnvironment environment) {
Predicate<Element> serializableFields = e -> {
Set<Modifier> mods = e.getModifiers();
return !mods.contains(Modifier.TRANSIENT) && !mods.contains(Modifier.STATIC);
};
Comparator<Element> bySimpleName = Comparator.comparing(e -> e.getSimpleName().toString());
List<TypeMirror> fields = ElementFilter.fieldsIn(type.getEnclosedElements()).stream().filter(serializableFields).sorted(bySimpleName).map(Element::asType).collect(Collectors.toList());
Types types = environment.getTypeUtils();
for (TypeMirror st : Util.getAllSuperClasses(types, type.asType())) {
Element ste = types.asElement(st);
ElementFilter.fieldsIn(ste.getEnclosedElements()).stream().filter(serializableFields).sorted(bySimpleName).map(e -> types.asMemberOf((DeclaredType) st, e)).forEach(fields::add);
}
String data = fields.stream().map(Util::toUniqueString).collect(Collectors.joining());
try {
byte[] bytes = data.getBytes("UTF-8");
MessageDigest md = MessageDigest.getInstance("SHA");
byte[] hashBytes = md.digest(bytes);
long hash = 0;
for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
hash = (hash << 8) | (hashBytes[i] & 0xFF);
}
return hash;
} catch (UnsupportedEncodingException | NoSuchAlgorithmException e) {
throw new IllegalStateException("Could not compute structural ID of a type " + type.getQualifiedName().toString(), e);
}
}
use of org.revapi.java.spi.Util 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.java.spi.Util 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;
}
Aggregations