Check more flags in bytecode listing tests

This commit is contained in:
Dmitry Petrov
2020-02-25 16:14:59 +03:00
parent ee9be61c20
commit 84baa0b4c2
28 changed files with 197 additions and 154 deletions
@@ -56,6 +56,33 @@ class BytecodeListingTextCollectingVisitor(val filter: Filter, val withSignature
if (!filter.shouldWriteClass(cr.access, cr.className)) null else visitor.text
}.joinToString("\n\n", postfix = "\n")
private val CLASS_OR_FIELD_OR_METHOD = setOf(ModifierTarget.CLASS, ModifierTarget.FIELD, ModifierTarget.METHOD)
private val CLASS_OR_METHOD = setOf(ModifierTarget.CLASS, ModifierTarget.METHOD)
private val FIELD_ONLY = setOf(ModifierTarget.FIELD)
private val METHOD_ONLY = setOf(ModifierTarget.METHOD)
private val FIELD_OR_METHOD = setOf(ModifierTarget.FIELD, ModifierTarget.METHOD)
// TODO ACC_MANDATED - requires reading Parameters attribute, which we don't generate by default
internal val MODIFIERS =
arrayOf(
Modifier("public", ACC_PUBLIC, CLASS_OR_FIELD_OR_METHOD),
Modifier("protected", ACC_PROTECTED, CLASS_OR_FIELD_OR_METHOD),
Modifier("private", ACC_PRIVATE, CLASS_OR_FIELD_OR_METHOD),
Modifier("synthetic", ACC_SYNTHETIC, CLASS_OR_FIELD_OR_METHOD),
Modifier("bridge", ACC_BRIDGE, METHOD_ONLY),
Modifier("volatile", ACC_VOLATILE, FIELD_ONLY),
Modifier("synchronized", ACC_SYNCHRONIZED, METHOD_ONLY),
Modifier("varargs", ACC_VARARGS, METHOD_ONLY),
Modifier("transient", ACC_TRANSIENT, FIELD_ONLY),
Modifier("native", ACC_NATIVE, METHOD_ONLY),
Modifier("deprecated", ACC_DEPRECATED, CLASS_OR_FIELD_OR_METHOD),
Modifier("final", ACC_FINAL, CLASS_OR_FIELD_OR_METHOD),
Modifier("strict", ACC_STRICT, METHOD_ONLY),
Modifier("enum", ACC_ENUM, FIELD_ONLY), // ACC_ENUM modifier on class is handled in 'classOrInterface'
Modifier("abstract", ACC_ABSTRACT, CLASS_OR_METHOD, excludedMask = ACC_INTERFACE),
Modifier("static", ACC_STATIC, FIELD_OR_METHOD)
)
}
interface Filter {
@@ -89,16 +116,32 @@ class BytecodeListingTextCollectingVisitor(val filter: Filter, val withSignature
list.add("$text ")
}
private fun handleModifiers(access: Int, list: MutableList<String> = declarationsInsideClass.last().annotations) {
if (access and ACC_PUBLIC != 0) addModifier("public", list)
if (access and ACC_PROTECTED != 0) addModifier("protected", list)
if (access and ACC_PRIVATE != 0) addModifier("private", list)
internal enum class ModifierTarget {
CLASS, FIELD, METHOD
}
if (access and ACC_SYNTHETIC != 0) addModifier("synthetic", list)
if (access and ACC_DEPRECATED != 0) addModifier("deprecated", list)
if (access and ACC_FINAL != 0) addModifier("final", list)
if (access and ACC_ABSTRACT != 0 && access and ACC_INTERFACE == 0) addModifier("abstract", list)
if (access and ACC_STATIC != 0) addModifier("static", list)
internal class Modifier(
val text: String,
private val mask: Int,
private val applicableTo: Set<ModifierTarget>,
private val excludedMask: Int = 0
) {
fun hasModifier(access: Int, target: ModifierTarget) =
access and mask != 0 &&
access and excludedMask == 0 &&
applicableTo.contains(target)
}
private fun handleModifiers(
target: ModifierTarget,
access: Int,
list: MutableList<String> = declarationsInsideClass.last().annotations
) {
for (modifier in MODIFIERS) {
if (modifier.hasModifier(access, target)) {
addModifier(modifier.text, list)
}
}
}
private fun classOrInterface(access: Int): String {
@@ -115,7 +158,7 @@ class BytecodeListingTextCollectingVisitor(val filter: Filter, val withSignature
if (classAnnotations.isNotEmpty()) {
append(classAnnotations.joinToString("\n", postfix = "\n"))
}
arrayListOf<String>().apply { handleModifiers(classAccess, this) }.forEach { append(it) }
arrayListOf<String>().apply { handleModifiers(ModifierTarget.CLASS, classAccess, this) }.forEach { append(it) }
append(classOrInterface(classAccess))
if (withSignatures) {
append("<$classSignature> ")
@@ -141,7 +184,7 @@ class BytecodeListingTextCollectingVisitor(val filter: Filter, val withSignature
val methodAnnotations = arrayListOf<String>()
val parameterAnnotations = hashMapOf<Int, MutableList<String>>()
handleModifiers(access, methodAnnotations)
handleModifiers(ModifierTarget.METHOD, access, methodAnnotations)
val methodParamCount = Type.getArgumentTypes(desc).size
return object : MethodVisitor(API_VERSION) {
@@ -194,7 +237,7 @@ class BytecodeListingTextCollectingVisitor(val filter: Filter, val withSignature
val fieldSignature = if (withSignatures) "<$signature> " else ""
val fieldDeclaration = Declaration("field $fieldSignature$name: $type")
declarationsInsideClass.add(fieldDeclaration)
handleModifiers(access)
handleModifiers(ModifierTarget.FIELD, access)
if (access and ACC_VOLATILE != 0) addModifier("volatile", fieldDeclaration.annotations)
return object : FieldVisitor(API_VERSION) {