Support type annotations
#KT-35843 Fixed
This commit is contained in:
+36
-6
@@ -13,14 +13,17 @@ import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.tree.*
|
||||
import org.jetbrains.org.objectweb.asm.util.Printer
|
||||
import org.jetbrains.org.objectweb.asm.util.Textifier
|
||||
import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor
|
||||
import java.io.File
|
||||
|
||||
private val LINE_SEPARATOR = System.getProperty("line.separator")
|
||||
|
||||
abstract class AbstractAsmLikeInstructionListingTest : CodegenTestCase() {
|
||||
private companion object {
|
||||
val CURIOUS_ABOUT_DIRECTIVE = "// CURIOUS_ABOUT "
|
||||
val LOCAL_VARIABLE_TABLE_DIRECTIVE = "// LOCAL_VARIABLE_TABLE"
|
||||
const val CURIOUS_ABOUT_DIRECTIVE = "// CURIOUS_ABOUT "
|
||||
const val LOCAL_VARIABLE_TABLE_DIRECTIVE = "// LOCAL_VARIABLE_TABLE"
|
||||
const val TYPE_ANNOTATIONS_DIRECTIVE = "// TYPE_ANNOTATIONS"
|
||||
}
|
||||
|
||||
override fun doMultiFileTest(wholeFile: File, files: List<TestFile>) {
|
||||
@@ -40,15 +43,21 @@ abstract class AbstractAsmLikeInstructionListingTest : CodegenTestCase() {
|
||||
.flatMap { it.split(',').map { it.trim() } }
|
||||
|
||||
val showLocalVariables = testFileLines.any { it.trim() == LOCAL_VARIABLE_TABLE_DIRECTIVE }
|
||||
val showTypeAnnotations = testFileLines.any { it.trim() == TYPE_ANNOTATIONS_DIRECTIVE }
|
||||
|
||||
KotlinTestUtils.assertEqualsToFile(txtFile, classes.joinToString(LINE_SEPARATOR.repeat(2)) {
|
||||
renderClassNode(it, printBytecodeForTheseMethods, showLocalVariables)
|
||||
renderClassNode(it, printBytecodeForTheseMethods, showLocalVariables, showTypeAnnotations)
|
||||
})
|
||||
}
|
||||
|
||||
protected open fun getExpectedTextFileName(wholeFile: File): String = wholeFile.nameWithoutExtension + ".txt"
|
||||
|
||||
private fun renderClassNode(clazz: ClassNode, showBytecodeForTheseMethods: List<String>, showLocalVariables: Boolean): String {
|
||||
private fun renderClassNode(
|
||||
clazz: ClassNode,
|
||||
showBytecodeForTheseMethods: List<String>,
|
||||
showLocalVariables: Boolean,
|
||||
showTypeAnnotations: Boolean
|
||||
): String {
|
||||
val fields = (clazz.fields ?: emptyList()).sortedBy { it.name }
|
||||
val methods = (clazz.methods ?: emptyList()).sortedBy { it.name }
|
||||
|
||||
@@ -74,7 +83,7 @@ abstract class AbstractAsmLikeInstructionListingTest : CodegenTestCase() {
|
||||
|
||||
methods.joinTo(this, LINE_SEPARATOR.repeat(2)) {
|
||||
val showBytecode = showBytecodeForTheseMethods.contains(it.name)
|
||||
renderMethod(it, showBytecode, showLocalVariables).withMargin()
|
||||
renderMethod(it, showBytecode, showLocalVariables, showTypeAnnotations).withMargin()
|
||||
}
|
||||
|
||||
appendln().append("}")
|
||||
@@ -88,7 +97,12 @@ abstract class AbstractAsmLikeInstructionListingTest : CodegenTestCase() {
|
||||
append(field.name)
|
||||
}
|
||||
|
||||
private fun renderMethod(method: MethodNode, showBytecode: Boolean, showLocalVariables: Boolean) = buildString {
|
||||
private fun renderMethod(
|
||||
method: MethodNode,
|
||||
showBytecode: Boolean,
|
||||
showLocalVariables: Boolean,
|
||||
showTypeAnnotations: Boolean
|
||||
) = buildString {
|
||||
renderVisibilityModifiers(method.access)
|
||||
renderModalityModifiers(method.access)
|
||||
val (returnType, parameterTypes) = with(Type.getMethodType(method.desc)) { returnType to argumentTypes }
|
||||
@@ -100,6 +114,20 @@ abstract class AbstractAsmLikeInstructionListingTest : CodegenTestCase() {
|
||||
"${type.className} $name"
|
||||
}.joinTo(this, prefix = "(", postfix = ")")
|
||||
|
||||
if (showTypeAnnotations) {
|
||||
val textifier = Textifier()
|
||||
val visitor = TraceMethodVisitor(textifier)
|
||||
method.visibleTypeAnnotations?.forEach {
|
||||
it.accept(visitor.visitTypeAnnotation(it.typeRef, it.typePath, it.desc, true))
|
||||
}
|
||||
method.invisibleTypeAnnotations?.forEach {
|
||||
it.accept(visitor.visitTypeAnnotation(it.typeRef, it.typePath, it.desc, false))
|
||||
}
|
||||
textifier.getText().takeIf { it.isNotEmpty() }?.let {
|
||||
append("\n${textifier.getText().joinToString("").trimEnd()}")
|
||||
}
|
||||
}
|
||||
|
||||
val actualShowBytecode = showBytecode && (method.access and ACC_ABSTRACT) == 0
|
||||
val actualShowLocalVariables = showLocalVariables && method.localVariables?.takeIf { it.isNotEmpty() } != null
|
||||
|
||||
@@ -121,6 +149,8 @@ abstract class AbstractAsmLikeInstructionListingTest : CodegenTestCase() {
|
||||
}
|
||||
|
||||
appendln().append("}")
|
||||
|
||||
method.visibleTypeAnnotations
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user