name.remal.building.gradle_plugins.utils.asmUtils.kt Maven / Gradle / Ivy
package name.remal.building.gradle_plugins.utils
import com.google.common.collect.ImmutableListMultimap
import com.google.common.collect.MultimapBuilder
import org.objectweb.asm.*
import org.objectweb.asm.tree.AnnotationNode
import org.objectweb.asm.tree.ClassNode
internal val ASM_API = run {
val field = ClassVisitor::class.java.getDeclaredField("api").apply { isAccessible = true }
return@run field.getInt(ClassWriter(0))
}
internal val ClassNode.annotations: List
get() {
val annotations: MutableList = mutableListOf()
this.visibleAnnotations?.let { annotations += it }
this.invisibleAnnotations?.let { annotations += it }
return annotations
}
internal val AnnotationNode.valuesMultimap: ImmutableListMultimap
get() {
values.let { values ->
if (null == values || values.isEmpty()) return ImmutableListMultimap.of()
val valuesMultimap = MultimapBuilder.hashKeys().arrayListValues().build()
(0..values.size - 1 step 2).forEach { index ->
val field = values[index] as String
val value = values[index + 1]
if (value is List<*>) {
value.forEach { valuesMultimap.put(field, it) }
} else {
valuesMultimap.put(field, value)
}
}
return ImmutableListMultimap.copyOf(valuesMultimap)
}
}
private val stringsArrayClass = arrayOf().javaClass
@Suppress("UNCHECKED_CAST")
internal val AnnotationNode.stringValuesMultimap: ImmutableListMultimap
get() {
val valuesMultimap = this.valuesMultimap
if (valuesMultimap.isEmpty) return ImmutableListMultimap.of()
val stringValuesMultimap = MultimapBuilder.hashKeys().arrayListValues().build()
valuesMultimap.keySet().forEach forEachKey@ { key ->
valuesMultimap[key].forEach { value ->
if (value is AnnotationNode) {
// do nothing
} else if (value is Type) {
stringValuesMultimap.put(key, value.className)
} else if (stringsArrayClass.isAssignableFrom(value.javaClass)) {
value as Array
val desc = value[0]
stringValuesMultimap.put(key, desc.substring(1, desc.length - 2) + '.' + value[1])
} else {
stringValuesMultimap.put(key, value.toString())
}
}
}
return ImmutableListMultimap.copyOf(stringValuesMultimap)
}
internal class OnlyClassInfoVisitor(cv: ClassVisitor?) : ClassVisitor(ASM_API, cv) {
override fun visitField(access: Int, name: String?, fieldDesc: String?, signature: String?, value: Any?): FieldVisitor? {
return null
}
override fun visitMethod(access: Int, name: String?, methodDesc: String?, signature: String?, exceptions: Array?): MethodVisitor? {
return null
}
}