From 2c848b8bb0fe95b98eeb54f5077ecae69d98a4a2 Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Fri, 2 Oct 2015 14:18:55 +0300 Subject: [PATCH] Add JvmSynthetic annotation --- .../org/jetbrains/kotlin/codegen/AsmUtil.java | 5 ++- .../kotlin/codegen/PropertyCodegen.java | 5 +++ .../kotlin/resolve/AnnotationUtil.kt | 7 ++++ .../annotations/JvmSynthetic.kt | 17 +++++++++ .../annotations/JvmSynthetic.txt | 16 ++++++++ .../annotations/defaultTargets.txt | 16 ++++---- .../bytecodeListing/annotations/literals.txt | 38 +++++++++---------- .../annotations/onProperties.txt | 24 ++++++------ .../annotations/onReceiver.txt | 20 +++++----- .../codegen/AbstractBytecodeListingTest.kt | 21 +++++++++- .../codegen/BytecodeListingTestGenerated.java | 6 +++ .../src/kotlin/jvm/JvmPlatformAnnotations.kt | 4 ++ 12 files changed, 127 insertions(+), 52 deletions(-) create mode 100644 compiler/testData/codegen/bytecodeListing/annotations/JvmSynthetic.kt create mode 100644 compiler/testData/codegen/bytecodeListing/annotations/JvmSynthetic.txt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java index 24dd03f3126..8b5925825d5 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java @@ -41,6 +41,7 @@ import org.jetbrains.kotlin.load.java.JvmAnnotationNames; import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.resolve.DescriptorUtils; +import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt; import org.jetbrains.kotlin.resolve.annotations.AnnotationsPackage; import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage; import org.jetbrains.kotlin.resolve.inline.InlineUtil; @@ -212,7 +213,9 @@ public class AsmUtil { flags |= ACC_ABSTRACT; } - if (JetTypeMapper.isAccessor(functionDescriptor) || functionDescriptor.getVisibility() == Visibilities.INTERNAL) { + if (JetTypeMapper.isAccessor(functionDescriptor) + || functionDescriptor.getVisibility() == Visibilities.INTERNAL + || AnnotationUtilKt.hasJvmSyntheticAnnotation(functionDescriptor)) { flags |= ACC_SYNTHETIC; } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java index c3893f68e35..fe57bc6e59e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java @@ -36,6 +36,7 @@ import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage; import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.DescriptorFactory; import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; +import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt; import org.jetbrains.kotlin.resolve.annotations.AnnotationsPackage; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.constants.ConstantValue; @@ -293,6 +294,10 @@ public class PropertyCodegen { modifiers |= ACC_FINAL; } + if (AnnotationUtilKt.hasJvmSyntheticAnnotation(propertyDescriptor)) { + modifiers |= ACC_SYNTHETIC; + } + Type type = typeMapper.mapType(jetType); ClassBuilder builder = v; diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationUtil.kt index 343be1971e5..06ccedc7675 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationUtil.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl +import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.lexer.JetTokens import org.jetbrains.kotlin.name.FqName @@ -40,6 +41,12 @@ public fun DeclarationDescriptor.findPublicFieldAnnotation(): AnnotationDescript return getAnnotations().findAnnotation(FqName("kotlin.jvm.publicField")) } +public fun DeclarationDescriptor.hasJvmSyntheticAnnotation(): Boolean { + val jvmSyntheticName = FqName("kotlin.jvm.JvmSynthetic") + return annotations.findAnnotation(jvmSyntheticName) != null || + Annotations.findUseSiteTargetedAnnotation(annotations, AnnotationUseSiteTarget.FIELD, jvmSyntheticName) != null +} + public fun DeclarationDescriptor.hasIntrinsicAnnotation(): Boolean { return getAnnotations().findAnnotation(FqName("kotlin.jvm.internal.Intrinsic")) != null } diff --git a/compiler/testData/codegen/bytecodeListing/annotations/JvmSynthetic.kt b/compiler/testData/codegen/bytecodeListing/annotations/JvmSynthetic.kt new file mode 100644 index 00000000000..34f0541c69a --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/annotations/JvmSynthetic.kt @@ -0,0 +1,17 @@ +class Example { + @JvmSynthetic + val prop: String = "ABC" + + var prop2 = 5 + @JvmSynthetic public get + @JvmSynthetic public set + + @field:JvmSynthetic + val useSite = 0 + + @get:JvmSynthetic @set:JvmSynthetic + var useSite2 = 0 + + @JvmSynthetic + fun job() {} +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/annotations/JvmSynthetic.txt b/compiler/testData/codegen/bytecodeListing/annotations/JvmSynthetic.txt new file mode 100644 index 00000000000..dd6e2fc2ef7 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/annotations/JvmSynthetic.txt @@ -0,0 +1,16 @@ +@kotlin.jvm.internal.KotlinClass Example { + public synthetic field $kotlinClass: kotlin.reflect.KClass + private synthetic @org.jetbrains.annotations.NotNull field prop: java.lang.String + private field prop2: int + private synthetic field useSite: int + private field useSite2: int + method (): void + public @org.jetbrains.annotations.NotNull method getProp(): java.lang.String + public synthetic method getProp2(): int + public synthetic method setProp2(p0: int): void + public method getUseSite(): int + public method getUseSite2(): int + public method setUseSite2(p0: int): void + public synthetic method job(): void + public method (): void +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/annotations/defaultTargets.txt b/compiler/testData/codegen/bytecodeListing/annotations/defaultTargets.txt index a538cc95130..9e36fe93267 100644 --- a/compiler/testData/codegen/bytecodeListing/annotations/defaultTargets.txt +++ b/compiler/testData/codegen/bytecodeListing/annotations/defaultTargets.txt @@ -1,13 +1,13 @@ @kotlin.jvm.internal.KotlinClass A { - field $kotlinClass: kotlin.reflect.KClass - @AnnField @AnnParameterField @AnnTypeField field a: int - @AnnField @AnnTypeField field x: int + public synthetic field $kotlinClass: kotlin.reflect.KClass + private @AnnField @AnnParameterField @AnnTypeField field a: int + private @AnnField @AnnTypeField field x: int method (): void - @AnnProperty @AnnFieldProperty @AnnParameterProperty method a$annotations(): void - method getA(): int - @AnnProperty @AnnFieldProperty method x$annotations(): void - method getX(): int - method (@AnnParameterProperty @AnnParameterField p0: int): void + private synthetic deprecated @AnnProperty @AnnFieldProperty @AnnParameterProperty method a$annotations(): void + public method getA(): int + private synthetic deprecated @AnnProperty @AnnFieldProperty method x$annotations(): void + public method getX(): int + public method (@AnnParameterProperty @AnnParameterField p0: int): void } @kotlin.annotation.Target @java.lang.annotation.Retention @java.lang.annotation.Target @kotlin.jvm.internal.KotlinClass AnnField diff --git a/compiler/testData/codegen/bytecodeListing/annotations/literals.txt b/compiler/testData/codegen/bytecodeListing/annotations/literals.txt index 6666962805c..00a36c92f92 100644 --- a/compiler/testData/codegen/bytecodeListing/annotations/literals.txt +++ b/compiler/testData/codegen/bytecodeListing/annotations/literals.txt @@ -6,32 +6,32 @@ @kotlin.jvm.internal.KotlinSyntheticClass @kotlin.jvm.internal.KotlinCallable LiteralsKt$foo$1 { inner class LiteralsKt$foo$1 - field $arg: int - method invoke(): java.lang.Object - @FunAnn method invoke(): int + synthetic field $arg: int + public method invoke(): java.lang.Object + public @FunAnn method invoke(): int method (p0: int): void } @kotlin.jvm.internal.KotlinSyntheticClass @kotlin.jvm.internal.KotlinCallable LiteralsKt$foo$2 { inner class LiteralsKt$foo$2 - field $arg: int - method invoke(): java.lang.Object - method invoke(): int + synthetic field $arg: int + public method invoke(): java.lang.Object + public method invoke(): int method (p0: int): void } @kotlin.jvm.internal.KotlinLocalClass @kotlin.jvm.internal.KotlinClass LiteralsKt$foo$3 { inner class LiteralsKt$foo$3 - field $kotlinClass: kotlin.reflect.KClass + public synthetic field $kotlinClass: kotlin.reflect.KClass method (): void method (): void } @kotlin.jvm.internal.KotlinSyntheticClass @kotlin.jvm.internal.KotlinCallable LiteralsKt$foo$x$1 { inner class LiteralsKt$foo$x$1 - field $arg: int - method invoke(): java.lang.Object - @FunAnn method invoke(): int + synthetic field $arg: int + public method invoke(): java.lang.Object + public @FunAnn method invoke(): int method (p0: int): void } @@ -40,20 +40,20 @@ inner class LiteralsKt$foo$2 inner class LiteralsKt$foo$x$1 inner class LiteralsKt$foo$3 - method bar(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): int - @org.jetbrains.annotations.NotNull method foo(p0: int): My + public method bar(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): int + public @org.jetbrains.annotations.NotNull method foo(p0: int): My } @kotlin.jvm.internal.KotlinClass My { - field $kotlinClass: kotlin.reflect.KClass + public synthetic field $kotlinClass: kotlin.reflect.KClass method (): void - method (): void + public method (): void } @java.lang.Deprecated @kotlin.jvm.internal.KotlinPackage _DefaultPackage { - field $kotlinPackage: kotlin.reflect.KPackage - field $moduleName: java.lang.String + public synthetic field $kotlinPackage: kotlin.reflect.KPackage + public synthetic field $moduleName: java.lang.String method (): void - @kotlin.jvm.internal.KotlinDelegatedMethod method bar(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): int - @kotlin.jvm.internal.KotlinDelegatedMethod @org.jetbrains.annotations.NotNull method foo(p0: int): My -} + public @kotlin.jvm.internal.KotlinDelegatedMethod method bar(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): int + public @kotlin.jvm.internal.KotlinDelegatedMethod @org.jetbrains.annotations.NotNull method foo(p0: int): My +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/annotations/onProperties.txt b/compiler/testData/codegen/bytecodeListing/annotations/onProperties.txt index e9a2d2a160f..810172096b9 100644 --- a/compiler/testData/codegen/bytecodeListing/annotations/onProperties.txt +++ b/compiler/testData/codegen/bytecodeListing/annotations/onProperties.txt @@ -1,17 +1,17 @@ @kotlin.jvm.internal.KotlinClass A { - field $kotlinClass: kotlin.reflect.KClass - @AnnField field p: int - @AnnField field x: int - field y: int + public synthetic field $kotlinClass: kotlin.reflect.KClass + private @AnnField field p: int + private @AnnField field x: int + private field y: int method (): void - @AnnProp @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 (@AnnParam p0: int, @AnnParam p1: int): void + private synthetic deprecated @AnnProp @AnnProp2 method p$annotations(): void + public @AnnGetter method getP(): int + public @AnnSetter method setP(@AnnParam p0: int): void + private synthetic deprecated @AnnProp2 method x$annotations(): void + public method getX(): int + public @AnnGetter method getY(): int + public @AnnSetter method setY(p0: int): void + public method (@AnnParam p0: int, @AnnParam p1: int): void } @java.lang.annotation.Retention @kotlin.jvm.internal.KotlinClass AnnField diff --git a/compiler/testData/codegen/bytecodeListing/annotations/onReceiver.txt b/compiler/testData/codegen/bytecodeListing/annotations/onReceiver.txt index 108f7aae796..f6a1ee09dc5 100644 --- a/compiler/testData/codegen/bytecodeListing/annotations/onReceiver.txt +++ b/compiler/testData/codegen/bytecodeListing/annotations/onReceiver.txt @@ -1,22 +1,22 @@ @kotlin.jvm.internal.KotlinClass A { - field $kotlinClass: kotlin.reflect.KClass + public synthetic field $kotlinClass: kotlin.reflect.KClass method (): 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 (): void + public @org.jetbrains.annotations.NotNull method f(@Ann p0: java.lang.String): java.lang.String + public @org.jetbrains.annotations.NotNull method getP(@Ann p0: java.lang.String): java.lang.String + public method (): void } @java.lang.annotation.Retention @kotlin.jvm.internal.KotlinClass Ann @kotlin.jvm.internal.KotlinFileFacade OnReceiverKt { - @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 + public @org.jetbrains.annotations.NotNull method topLevelF(@Ann p0: java.lang.String): java.lang.String + public @org.jetbrains.annotations.NotNull method getTopLevelP(@Ann p0: java.lang.String): java.lang.String } @java.lang.Deprecated @kotlin.jvm.internal.KotlinPackage _DefaultPackage { - field $kotlinPackage: kotlin.reflect.KPackage - field $moduleName: java.lang.String + public synthetic field $kotlinPackage: kotlin.reflect.KPackage + public synthetic field $moduleName: java.lang.String method (): void - @kotlin.jvm.internal.KotlinDelegatedMethod @org.jetbrains.annotations.NotNull method getTopLevelP(@Ann p0: java.lang.String): java.lang.String - @kotlin.jvm.internal.KotlinDelegatedMethod @org.jetbrains.annotations.NotNull method topLevelF(@Ann p0: java.lang.String): java.lang.String + public @kotlin.jvm.internal.KotlinDelegatedMethod @org.jetbrains.annotations.NotNull method getTopLevelP(@Ann p0: java.lang.String): java.lang.String + public @kotlin.jvm.internal.KotlinDelegatedMethod @org.jetbrains.annotations.NotNull method topLevelF(@Ann p0: java.lang.String): java.lang.String } \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/AbstractBytecodeListingTest.kt b/compiler/tests/org/jetbrains/kotlin/codegen/AbstractBytecodeListingTest.kt index 2426edf3b62..9fa5183ed94 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/AbstractBytecodeListingTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/codegen/AbstractBytecodeListingTest.kt @@ -48,9 +48,22 @@ public abstract class AbstractBytecodeListingTest : CodegenTestCase() { private val classAnnotations = arrayListOf() private var className = "" - private fun addAnnotation(desc: String) { + private fun addAnnotation(desc: String, list: MutableList = declarationsInsideClass.last().annotations) { val name = Type.getType(desc).className - declarationsInsideClass.last().annotations.add("@$name ") + list.add("@$name ") + } + + private fun addModifier(text: String, list: MutableList) { + list.add("$text ") + } + + private fun handleModifiers(access: Int, list: MutableList = declarationsInsideClass.last().annotations) { + if ((access and Opcodes.ACC_PUBLIC) != 0) addModifier("public", list) + if ((access and Opcodes.ACC_PROTECTED) != 0) addModifier("protected", list) + if ((access and Opcodes.ACC_PRIVATE) != 0) addModifier("private", list) + + if ((access and Opcodes.ACC_SYNTHETIC) != 0) addModifier("synthetic", list) + if ((access and Opcodes.ACC_DEPRECATED) != 0) addModifier("deprecated", list) } public val text: String @@ -78,6 +91,8 @@ public abstract class AbstractBytecodeListingTest : CodegenTestCase() { val methodAnnotations = arrayListOf() val parameterAnnotations = hashMapOf>() + handleModifiers(access, methodAnnotations) + return object : MethodVisitor(Opcodes.ASM5) { override fun visitAnnotation(desc: String, visible: Boolean): AnnotationVisitor? { val type = Type.getType(desc).className @@ -105,6 +120,8 @@ public abstract class AbstractBytecodeListingTest : CodegenTestCase() { 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")) + handleModifiers(access) + return object : FieldVisitor(Opcodes.ASM5) { override fun visitAnnotation(desc: String, visible: Boolean): AnnotationVisitor? { addAnnotation(desc) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java index 84a96b266e5..cb85c0db408 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java @@ -49,6 +49,12 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest { doTest(fileName); } + @TestMetadata("JvmSynthetic.kt") + public void testJvmSynthetic() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/annotations/JvmSynthetic.kt"); + doTest(fileName); + } + @TestMetadata("literals.kt") public void testLiterals() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/annotations/literals.kt"); diff --git a/libraries/stdlib/src/kotlin/jvm/JvmPlatformAnnotations.kt b/libraries/stdlib/src/kotlin/jvm/JvmPlatformAnnotations.kt index 903b7906ed6..f078c9974c9 100644 --- a/libraries/stdlib/src/kotlin/jvm/JvmPlatformAnnotations.kt +++ b/libraries/stdlib/src/kotlin/jvm/JvmPlatformAnnotations.kt @@ -61,6 +61,10 @@ public annotation class JvmName(public val name: String) @MustBeDocumented public annotation class JvmMultifileClass +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER, AnnotationTarget.FIELD) +@Retention(AnnotationRetention.SOURCE) +public annotation class JvmSynthetic + /** * Instructs the Kotlin compiler to generate a public backing field for this property. */