Add bytecode listing test for use site targets and default targets (with priorities)

This commit is contained in:
Yan Zhulanow
2015-08-26 15:51:57 +03:00
parent 9dbd355e92
commit 552211b2f4
9 changed files with 350 additions and 0 deletions
@@ -0,0 +1,38 @@
target(AnnotationTarget.PROPERTY)
annotation class AnnProperty
target(AnnotationTarget.FIELD)
annotation class AnnField
target(AnnotationTarget.FIELD, AnnotationTarget.PROPERTY)
annotation class AnnFieldProperty
target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.PROPERTY)
annotation class AnnParameterProperty
target(AnnotationTarget.PROPERTY, AnnotationTarget.FIELD)
annotation class AnnParameterField
target(AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
annotation class AnnGetterSetter
target(AnnotationTarget.PROPERTY_SETTER, AnnotationTarget.PROPERTY)
annotation class AnnPropertySetter
target(AnnotationTarget.PROPERTY, AnnotationTarget.PROPERTY_GETTER)
annotation class AnnTypeGetter
target(AnnotationTarget.PROPERTY, AnnotationTarget.TYPE)
annotation class AnnTypeField
public class A(
@AnnProperty @AnnField @AnnFieldProperty @AnnParameterProperty @AnnParameterField
@AnnGetterSetter @AnnPropertySetter @AnnTypeGetter @AnnTypeField
public val x: Int
) {
@AnnProperty @AnnField @AnnFieldProperty @AnnParameterProperty @AnnParameterField
@AnnGetterSetter @AnnPropertySetter @AnnTypeGetter @AnnTypeField
public val a: Int = 1
}
@@ -0,0 +1,29 @@
@kotlin.jvm.internal.KotlinClass A {
field $kotlinClass: kotlin.reflect.KClass
@AnnField @AnnFieldProperty @AnnParameterField field a: int
@AnnField @AnnFieldProperty @AnnParameterField field x: int
method <clinit>(): void
@AnnProperty @AnnParameterProperty @AnnPropertySetter @AnnTypeGetter @AnnTypeField method a$annotations(): void
@AnnGetterSetter method getA(): int
@AnnProperty @AnnPropertySetter @AnnTypeGetter @AnnTypeField method x$annotations(): void
@AnnGetterSetter method getX(): int
method <init>(@AnnParameterProperty p0: int): void
}
@kotlin.annotation.target @java.lang.annotation.Retention @java.lang.annotation.Target @kotlin.jvm.internal.KotlinClass AnnField
@kotlin.annotation.target @java.lang.annotation.Retention @java.lang.annotation.Target @kotlin.jvm.internal.KotlinClass AnnFieldProperty
@kotlin.annotation.target @java.lang.annotation.Retention @java.lang.annotation.Target @kotlin.jvm.internal.KotlinClass AnnGetterSetter
@kotlin.annotation.target @java.lang.annotation.Retention @java.lang.annotation.Target @kotlin.jvm.internal.KotlinClass AnnParameterField
@kotlin.annotation.target @java.lang.annotation.Retention @java.lang.annotation.Target @kotlin.jvm.internal.KotlinClass AnnParameterProperty
@kotlin.annotation.target @java.lang.annotation.Retention @java.lang.annotation.Target @kotlin.jvm.internal.KotlinClass AnnProperty
@kotlin.annotation.target @java.lang.annotation.Retention @java.lang.annotation.Target @kotlin.jvm.internal.KotlinClass AnnPropertySetter
@kotlin.annotation.target @java.lang.annotation.Retention @java.lang.annotation.Target @kotlin.jvm.internal.KotlinClass AnnTypeField
@kotlin.annotation.target @java.lang.annotation.Retention @java.lang.annotation.Target @kotlin.jvm.internal.KotlinClass AnnTypeGetter
@@ -0,0 +1,13 @@
annotation class AnnProp
annotation class AnnField
annotation class AnnProp2
annotation class AnnGetter
annotation class AnnSetter
annotation class AnnParam
public class A(@AnnParam @field:AnnField @property:AnnProp2 val x: Int, @param:AnnParam @get:AnnGetter @set:AnnSetter var y: Int) {
@AnnProp @field:AnnField @property:AnnProp2 @get:AnnGetter @set:AnnSetter @sparam:AnnParam
var p: Int = 0
}
@@ -0,0 +1,27 @@
@kotlin.jvm.internal.KotlinClass A {
field $kotlinClass: kotlin.reflect.KClass
@AnnProp @AnnField field p: int
@AnnField field x: int
field y: int
method <clinit>(): void
@AnnProp2 method p$annotations(): void
@AnnGetter method getP(): int
@AnnSetter method setP(@AnnParam p0: int): void
@AnnProp2 method x$annotations(): void
method getX(): int
@AnnGetter method getY(): int
@AnnSetter method setY(p0: int): void
method <init>(@AnnParam p0: int, @AnnParam p1: int): void
}
@java.lang.annotation.Retention @kotlin.jvm.internal.KotlinClass AnnField
@java.lang.annotation.Retention @kotlin.jvm.internal.KotlinClass AnnGetter
@java.lang.annotation.Retention @kotlin.jvm.internal.KotlinClass AnnParam
@java.lang.annotation.Retention @kotlin.jvm.internal.KotlinClass AnnProp
@java.lang.annotation.Retention @kotlin.jvm.internal.KotlinClass AnnProp2
@java.lang.annotation.Retention @kotlin.jvm.internal.KotlinClass AnnSetter
@@ -0,0 +1,14 @@
public annotation class Ann
public class A {
fun @receiver:Ann String.f(): String = ""
val @receiver:Ann String.p: String
get() = ""
}
fun @receiver:Ann String.topLevelF(): String = ""
val @receiver:Ann String.topLevelP: String
get() = ""
@@ -0,0 +1,21 @@
@kotlin.jvm.internal.KotlinClass A {
field $kotlinClass: kotlin.reflect.KClass
method <clinit>(): void
@org.jetbrains.annotations.NotNull method f(@Ann p0: java.lang.String): java.lang.String
@org.jetbrains.annotations.NotNull method getP(@Ann p0: java.lang.String): java.lang.String
method <init>(): void
}
@java.lang.annotation.Retention @kotlin.jvm.internal.KotlinClass Ann
@kotlin.jvm.internal.KotlinSyntheticClass _DefaultPackage$onReceiver$b389baba {
@org.jetbrains.annotations.NotNull method topLevelF(@Ann p0: java.lang.String): java.lang.String
@org.jetbrains.annotations.NotNull method getTopLevelP(@Ann p0: java.lang.String): java.lang.String
}
@kotlin.jvm.internal.KotlinPackage _DefaultPackage {
field $kotlinPackage: kotlin.reflect.KPackage
method <clinit>(): void
@org.jetbrains.annotations.NotNull method getTopLevelP(@Ann p0: java.lang.String): java.lang.String
@org.jetbrains.annotations.NotNull method topLevelF(@Ann p0: java.lang.String): java.lang.String
}
@@ -0,0 +1,140 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.JetTestUtils
import org.jetbrains.org.objectweb.asm.*
import java.io.File
import java.util.*
public abstract class AbstractBytecodeListingTest : CodegenTestCase() {
throws(Exception::class)
public fun doTest(filename: String) {
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.ALL)
loadFileByFullPath(filename)
val ktFile = File(filename)
val txtFile = File(ktFile.parent, ktFile.nameWithoutExtension + ".txt")
val generatedFiles = CodegenTestUtil.generateFiles(myEnvironment, myFiles)
.asList()
.sortedBy { it.relativePath }
.map {
val cr = ClassReader(it.asByteArray())
val visitor = TextCollectingVisitor()
cr.accept(visitor, ClassReader.SKIP_CODE)
visitor.text
}.joinToString("\n\n")
JetTestUtils.assertEqualsToFile(txtFile, generatedFiles)
}
private class TextCollectingVisitor : ClassVisitor(Opcodes.ASM5) {
private class Declaration(val text: String, val annotations: MutableList<String> = arrayListOf())
private val declarationsInsideClass = arrayListOf<Declaration>()
private val classAnnotations = arrayListOf<String>()
private var className = ""
private fun addAnnotation(desc: String) {
val name = Type.getType(desc).className
declarationsInsideClass.last().annotations.add("@$name ")
}
public val text: String
get() = StringBuilder {
append(classAnnotations.joinToString(""))
append(className)
if (declarationsInsideClass.isNotEmpty()) {
append(" {\n")
for (declaration in declarationsInsideClass) {
append(" ").append(declaration.annotations.joinToString("")).append(declaration.text).append("\n")
}
append("}")
}
}.toString()
override fun visitMethod(
access: Int,
name: String,
desc: String,
signature: String?,
exceptions: Array<out String>?
): MethodVisitor? {
val returnType = Type.getReturnType(desc).className
val parameterTypes = Type.getArgumentTypes(desc).map { it.className }
val methodAnnotations = arrayListOf<String>()
val parameterAnnotations = hashMapOf<Int, MutableList<String>>()
return object : MethodVisitor(Opcodes.ASM5) {
override fun visitAnnotation(desc: String, visible: Boolean): AnnotationVisitor? {
val type = Type.getType(desc).className
methodAnnotations += "@$type "
return super.visitAnnotation(desc, visible)
}
override fun visitParameterAnnotation(parameter: Int, desc: String, visible: Boolean): AnnotationVisitor? {
val type = Type.getType(desc).className
parameterAnnotations.getOrPut(parameter, { arrayListOf() }).add("@$type ")
return super.visitParameterAnnotation(parameter, desc, visible)
}
override fun visitEnd() {
val parameterWithAnnotations = parameterTypes.mapIndexed { index, parameter ->
val annotations = parameterAnnotations.getOrElse(index, { emptyList<String>() }).joinToString("")
"${annotations}p$index: $parameter"
}.joinToString()
declarationsInsideClass.add(Declaration("method $name($parameterWithAnnotations): $returnType", methodAnnotations))
super.visitEnd()
}
}
}
override fun visitField(access: Int, name: String, desc: String, signature: String?, value: Any?): FieldVisitor? {
val type = Type.getType(desc).className
declarationsInsideClass.add(Declaration("field $name: $type"))
return object : FieldVisitor(Opcodes.ASM5) {
override fun visitAnnotation(desc: String, visible: Boolean): AnnotationVisitor? {
addAnnotation(desc)
return super.visitAnnotation(desc, visible)
}
}
}
override fun visitAnnotation(desc: String, visible: Boolean): AnnotationVisitor? {
val name = Type.getType(desc).className
classAnnotations.add("@$name ")
return super.visitAnnotation(desc, visible)
}
override fun visit(
version: Int,
access: Int,
name: String,
signature: String?,
superName: String?,
interfaces: Array<out String>?
) {
className = name
}
override fun visitInnerClass(name: String, outerName: String?, innerName: String?, access: Int) {
declarationsInsideClass.add(Declaration("inner class $name"))
}
}
}
@@ -0,0 +1,64 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.JetTestUtils;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("compiler/testData/codegen/bytecodeListing")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
public void testAllFilesPresentInBytecodeListing() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeListing"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("compiler/testData/codegen/bytecodeListing/annotations")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Annotations extends AbstractBytecodeListingTest {
public void testAllFilesPresentInAnnotations() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeListing/annotations"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("defaultTargets.kt")
public void testDefaultTargets() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/annotations/defaultTargets.kt");
doTest(fileName);
}
@TestMetadata("onProperties.kt")
public void testOnProperties() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/annotations/onProperties.kt");
doTest(fileName);
}
@TestMetadata("onReceiver.kt")
public void testOnReceiver() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/annotations/onReceiver.kt");
doTest(fileName);
}
}
}
@@ -208,6 +208,10 @@ fun main(args: Array<String>) {
model("codegen/bytecodeText")
}
testClass(javaClass<AbstractBytecodeListingTest>()) {
model("codegen/bytecodeListing")
}
testClass(javaClass<AbstractTopLevelMembersInvocationTest>()) {
model("codegen/topLevelMemberInvocation", extension = null, recursive = false)
}