summaryrefslogtreecommitdiffstats
path: root/abi-check-plugin
diff options
context:
space:
mode:
authorIlpo Ruotsalainen <ilpo.ruotsalainen@oath.com>2018-11-28 15:49:37 +0100
committerIlpo Ruotsalainen <ilpo.ruotsalainen@oath.com>2018-11-28 15:54:45 +0100
commit48c554881cdeafc0c6e474da7171f9238fef8e5f (patch)
tree26e255bdfe3f4b7d73972a1b37d4a82694ca4c66 /abi-check-plugin
parent54bf0d9de1f98a0e1e987d74c7af723ad7666e14 (diff)
Fields, superclass and interfaces are part of ABI.
Diffstat (limited to 'abi-check-plugin')
-rw-r--r--abi-check-plugin/src/main/java/com/yahoo/abicheck/collector/PublicSignatureCollector.java49
-rw-r--r--abi-check-plugin/src/main/java/com/yahoo/abicheck/collector/Util.java15
-rw-r--r--abi-check-plugin/src/main/java/com/yahoo/abicheck/mojo/AbiCheck.java20
-rw-r--r--abi-check-plugin/src/main/java/com/yahoo/abicheck/signature/JavaClassSignature.java9
4 files changed, 78 insertions, 15 deletions
diff --git a/abi-check-plugin/src/main/java/com/yahoo/abicheck/collector/PublicSignatureCollector.java b/abi-check-plugin/src/main/java/com/yahoo/abicheck/collector/PublicSignatureCollector.java
index b7520c58d96..b6506bb4622 100644
--- a/abi-check-plugin/src/main/java/com/yahoo/abicheck/collector/PublicSignatureCollector.java
+++ b/abi-check-plugin/src/main/java/com/yahoo/abicheck/collector/PublicSignatureCollector.java
@@ -9,6 +9,7 @@ import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
@@ -18,8 +19,11 @@ public class PublicSignatureCollector extends ClassVisitor {
private final Map<String, JavaClassSignature> classSignatures = new LinkedHashMap<>();
private String currentName;
+ private String currentSuper;
+ private Set<String> currentInterfaces;
private int currentAccess;
private Set<String> currentMethods;
+ private Set<String> currentFields;
public PublicSignatureCollector() {
super(Opcodes.ASM6);
@@ -31,23 +35,39 @@ public class PublicSignatureCollector extends ClassVisitor {
private static String describeMethod(String name, int access, String returnType,
List<String> argumentTypes) {
- String attributes = String.join(" ", Util.convertAccess(access, Util.methodFlags));
- return String
- .format("%s %s %s(%s)", attributes, returnType, name, String.join(", ", argumentTypes));
+ return String.format("%s %s %s(%s)", describeAccess(access, Util.methodFlags), returnType, name,
+ String.join(", ", argumentTypes));
+ }
+
+ private static String describeAccess(int access, List<Util.AccessFlag> possibleFlags) {
+ return String.join(" ", Util.convertAccess(access, possibleFlags));
+ }
+
+ private static String describeField(String name, int access, String type) {
+ return String.format("%s %s %s", describeAccess(access, Util.fieldFlags), type, name);
+ }
+
+ private static String internalNameToClassName(String superName) {
+ return Type.getObjectType(superName).getClassName();
}
@Override
public void visit(int version, int access, String name, String signature, String superName,
String[] interfaces) {
- currentName = Type.getObjectType(name).getClassName();
+ currentName = internalNameToClassName(name);
+ currentSuper = internalNameToClassName(superName);
+ currentInterfaces = Arrays.stream(interfaces)
+ .map(PublicSignatureCollector::internalNameToClassName)
+ .collect(Collectors.toCollection(LinkedHashSet::new));
currentAccess = access;
currentMethods = new LinkedHashSet<>();
+ currentFields = new LinkedHashSet<>();
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature,
String[] exceptions) {
- if (isVisibleMethod(access)) {
+ if (isVisibleMember(access)) {
Type method = Type.getMethodType(descriptor);
List<String> argumentTypes = Arrays.stream(method.getArgumentTypes()).map(Type::getClassName)
.collect(Collectors.toList());
@@ -57,12 +77,21 @@ public class PublicSignatureCollector extends ClassVisitor {
return null;
}
- private boolean isVisibleMethod(int access) {
- // Public methods are visible
+ @Override
+ public FieldVisitor visitField(int access, String name, String descriptor, String signature,
+ Object value) {
+ if (isVisibleMember(access)) {
+ currentFields.add(describeField(name, access, Type.getType(descriptor).getClassName()));
+ }
+ return null;
+ }
+
+ private boolean isVisibleMember(int access) {
+ // Public members are visible
if (testBit(access, Opcodes.ACC_PUBLIC)) {
return true;
}
- // Protected non-static methods are visible if the class is not final (can be called from
+ // Protected non-static members are visible if the class is not final (can be called from
// extending classes)
if (!testBit(access, Opcodes.ACC_STATIC) && testBit(access, Opcodes.ACC_PROTECTED) && !testBit(
currentAccess, Opcodes.ACC_FINAL)) {
@@ -76,8 +105,8 @@ public class PublicSignatureCollector extends ClassVisitor {
public void visitEnd() {
if ((currentAccess & Opcodes.ACC_PUBLIC) != 0) {
classSignatures.put(currentName,
- new JavaClassSignature(Util.convertAccess(currentAccess, Util.classFlags),
- currentMethods));
+ new JavaClassSignature(currentSuper, currentInterfaces,
+ Util.convertAccess(currentAccess, Util.classFlags), currentMethods, currentFields));
}
}
diff --git a/abi-check-plugin/src/main/java/com/yahoo/abicheck/collector/Util.java b/abi-check-plugin/src/main/java/com/yahoo/abicheck/collector/Util.java
index 7c997322cee..f308ad42db5 100644
--- a/abi-check-plugin/src/main/java/com/yahoo/abicheck/collector/Util.java
+++ b/abi-check-plugin/src/main/java/com/yahoo/abicheck/collector/Util.java
@@ -39,6 +39,19 @@ public class Util {
AccessFlag.ignored(Opcodes.ACC_DEPRECATED)
);
+ public static final List<AccessFlag> fieldFlags = Arrays.asList(
+ AccessFlag.make(Opcodes.ACC_PUBLIC, "public"),
+ AccessFlag.make(Opcodes.ACC_PRIVATE, "private"),
+ AccessFlag.make(Opcodes.ACC_PROTECTED, "protected"),
+ AccessFlag.make(Opcodes.ACC_STATIC, "static"),
+ AccessFlag.make(Opcodes.ACC_FINAL, "final"),
+ AccessFlag.make(Opcodes.ACC_VOLATILE, "volatile"),
+ AccessFlag.make(Opcodes.ACC_TRANSIENT, "transient"),
+ AccessFlag.make(Opcodes.ACC_SYNTHETIC, "synthetic"), // FIXME: Do we want this?
+ AccessFlag.make(Opcodes.ACC_ENUM, "enum"),
+ AccessFlag.ignored(Opcodes.ACC_DEPRECATED)
+ );
+
public static List<String> convertAccess(int access, List<AccessFlag> flags) {
List<String> result = new ArrayList<>();
for (AccessFlag flag : flags) {
@@ -53,7 +66,7 @@ public class Util {
return result;
}
- private static class AccessFlag {
+ public static class AccessFlag {
public final int bit;
public final String attribute;
diff --git a/abi-check-plugin/src/main/java/com/yahoo/abicheck/mojo/AbiCheck.java b/abi-check-plugin/src/main/java/com/yahoo/abicheck/mojo/AbiCheck.java
index 007d0ff6a51..6dae44c8aa9 100644
--- a/abi-check-plugin/src/main/java/com/yahoo/abicheck/mojo/AbiCheck.java
+++ b/abi-check-plugin/src/main/java/com/yahoo/abicheck/mojo/AbiCheck.java
@@ -128,15 +128,29 @@ public class AbiCheck extends AbstractMojo {
private boolean matchingClasses(String className, JavaClassSignature expected,
JavaClassSignature actual) {
boolean match = true;
- if (!matchingItemSets(new HashSet<>(expected.attributes), new HashSet<>(actual.attributes),
- item -> true, (item, error) -> getLog().error(String
- .format("Class %s: %s attribute %s", className, capitalizeFirst(error), item)))) {
+ if (!expected.superClass.equals(actual.superClass)) {
match = false;
+ getLog().error(String
+ .format("Class %s: Expected superclass %s, found %s", className, expected.superClass,
+ actual.superClass));
+ }
+ if (!matchingItemSets(expected.interfaces, actual.interfaces, item -> true,
+ (item, error) -> getLog().error(
+ String.format("Class %s: %s interface %s", className, capitalizeFirst(error), item)))) {
+ if (!matchingItemSets(new HashSet<>(expected.attributes), new HashSet<>(actual.attributes),
+ item -> true, (item, error) -> getLog().error(String
+ .format("Class %s: %s attribute %s", className, capitalizeFirst(error), item)))) {
+ match = false;
+ }
}
if (!matchingItemSets(expected.methods, actual.methods, item -> true, (item, error) -> getLog()
.error(String.format("Class %s: %s method %s", className, capitalizeFirst(error), item)))) {
match = false;
}
+ if (!matchingItemSets(expected.fields, actual.fields, item -> true, (item, error) -> getLog()
+ .error(String.format("Class %s: %s field %s", className, capitalizeFirst(error), item)))) {
+ match = false;
+ }
return match;
}
diff --git a/abi-check-plugin/src/main/java/com/yahoo/abicheck/signature/JavaClassSignature.java b/abi-check-plugin/src/main/java/com/yahoo/abicheck/signature/JavaClassSignature.java
index c9c2242e245..5e748d1b7e2 100644
--- a/abi-check-plugin/src/main/java/com/yahoo/abicheck/signature/JavaClassSignature.java
+++ b/abi-check-plugin/src/main/java/com/yahoo/abicheck/signature/JavaClassSignature.java
@@ -5,11 +5,18 @@ import java.util.Set;
public class JavaClassSignature {
+ public final String superClass;
+ public final Set<String> interfaces;
public final List<String> attributes;
public final Set<String> methods;
+ public final Set<String> fields;
- public JavaClassSignature(List<String> attributes, Set<String> methods) {
+ public JavaClassSignature(String superClass, Set<String> interfaces, List<String> attributes,
+ Set<String> methods, Set<String> fields) {
+ this.superClass = superClass;
+ this.interfaces = interfaces;
this.attributes = attributes;
this.methods = methods;
+ this.fields = fields;
}
}