From 965e3ebab21065523cff020593ab133e61c49533 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 21 Mar 2018 17:22:13 +0100 Subject: [PATCH] Do not serialize SOURCE-retained annotations Also, fix the value of "hasAnnotations" flag to reflect if there are any _non-source_ annotations on a declaration. Unfortunately, after this change IncrementalJsCompilerRunnerTestGenerated$PureKotlin.testAnnotations starts to fail because of the following problem. The problem is that annotations on property accessors are not serialized yet on JS (see KT-14529), yet property proto message has setterFlags field which has the hasAnnotations flag. Upon the full rebuild of the code in that test, we correctly write hasAnnotations = true, but annotations themselves are not serialized. After an incremental build, we deserialize property setter descriptor, observe its Annotations object which happens to be an instance of NonEmptyDeserializedAnnotationsWithPossibleTargets. Now, because annotations itself are not serialized, that Annotations object has no annotations, yet its isEmpty always returns false (see the code). Everything worked correctly before the change because in DescriptorSerializer.hasAnnotations, we used Annotations.isEmpty and the result was the same in the full rebuild and in the incremental scenario. But now we're actually loading annotations, to determine their retention, and that's why the setterFlags are becoming different here and the test fails #KT-23360 Fixed --- .../serialization/JvmSerializerExtension.java | 8 +++--- .../serialization/DescriptorSerializer.kt | 12 +++++++-- .../serialization/SerializerExtensionBase.kt | 17 ++++++------ .../annotations/types/SourceRetention.kt | 17 ++++++++++++ .../annotations/types/SourceRetention.txt | 13 ++++++++++ .../binaryRetainedAnnotation.kt | 21 +++++++++++++++ .../binaryRetainedAnnotation.txt | 26 +++++++++++++++++++ .../sourceRetainedAnnotation.kt | 21 +++++++++++++++ .../sourceRetainedAnnotation.txt | 26 +++++++++++++++++++ .../jvm/compiler/AbstractLoadJavaTest.java | 15 ++++++++--- .../jvm/compiler/LoadJavaTestGenerated.java | 5 ++++ .../LoadKotlinWithTypeTableTestGenerated.java | 5 ++++ .../LoadJavaUsingJavacTestGenerated.java | 5 ++++ .../builtins/BuiltInsSerializerTest.kt | 8 ++++++ ...mRuntimeDescriptorLoaderTestGenerated.java | 5 ++++ .../descriptors/annotations/Annotations.kt | 12 +++++++-- .../kotlin/resolve/DescriptorUtils.kt | 12 +++++++++ .../decompiledTextJs/TypeAliases.expected.kt | 6 ++--- .../decompiledTextJvm/TypeAliases.expected.kt | 4 +-- .../stubBuilder/Annotations/Annotations.txt | 10 ------- .../stubBuilder/TypeAliases/TypeAliases.txt | 14 ---------- .../LoadJavaClsStubTestGenerated.java | 5 ++++ .../idea/stubs/AbstractResolveByStubTest.kt | 9 +++++-- .../stubs/ResolveByStubTestGenerated.java | 5 ++++ .../js/KotlinJavascriptSerializationUtil.kt | 3 ++- 25 files changed, 231 insertions(+), 53 deletions(-) create mode 100644 compiler/testData/loadJava/compiledKotlin/annotations/types/SourceRetention.kt create mode 100644 compiler/testData/loadJava/compiledKotlin/annotations/types/SourceRetention.txt create mode 100644 compiler/testData/serialization/builtinsSerializer/binaryRetainedAnnotation.kt create mode 100644 compiler/testData/serialization/builtinsSerializer/binaryRetainedAnnotation.txt create mode 100644 compiler/testData/serialization/builtinsSerializer/sourceRetainedAnnotation.kt create mode 100644 compiler/testData/serialization/builtinsSerializer/sourceRetainedAnnotation.txt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.java index a59e5292452..3c44f53f6cc 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.java @@ -136,16 +136,14 @@ public class JvmSerializerExtension extends SerializerExtension { @Override public void serializeType(@NotNull KotlinType type, @NotNull ProtoBuf.Type.Builder proto) { // TODO: don't store type annotations in our binary metadata on Java 8, use *TypeAnnotations attributes instead - for (AnnotationDescriptor annotation : type.getAnnotations()) { + for (AnnotationDescriptor annotation : DescriptorUtilsKt.getNonSourceAnnotations(type)) { proto.addExtension(JvmProtoBuf.typeAnnotation, annotationSerializer.serializeAnnotation(annotation)); } } @Override - public void serializeTypeParameter( - @NotNull TypeParameterDescriptor typeParameter, @NotNull ProtoBuf.TypeParameter.Builder proto - ) { - for (AnnotationDescriptor annotation : typeParameter.getAnnotations()) { + public void serializeTypeParameter(@NotNull TypeParameterDescriptor typeParameter, @NotNull ProtoBuf.TypeParameter.Builder proto) { + for (AnnotationDescriptor annotation : DescriptorUtilsKt.getNonSourceAnnotations(typeParameter)) { proto.addExtension(JvmProtoBuf.typeParameterAnnotation, annotationSerializer.serializeAnnotation(annotation)); } } diff --git a/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt b/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt index 9d2b0eaa8e3..d85e9b0f0e7 100644 --- a/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt +++ b/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt @@ -33,6 +33,8 @@ import org.jetbrains.kotlin.resolve.constants.EnumValue import org.jetbrains.kotlin.resolve.constants.IntValue import org.jetbrains.kotlin.resolve.constants.NullValue import org.jetbrains.kotlin.resolve.constants.StringValue +import org.jetbrains.kotlin.resolve.descriptorUtil.isSourceAnnotation +import org.jetbrains.kotlin.resolve.descriptorUtil.nonSourceAnnotations import org.jetbrains.kotlin.serialization.deserialization.ProtoEnumFlags import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.typeUtil.contains @@ -396,7 +398,9 @@ class DescriptorSerializer private constructor( builder.versionRequirement = requirement } - builder.addAllAnnotation(descriptor.annotations.map { extension.annotationSerializer.serializeAnnotation(it) }) + for (annotation in descriptor.nonSourceAnnotations) { + builder.addAnnotation(extension.annotationSerializer.serializeAnnotation(annotation)) + } return builder } @@ -775,7 +779,11 @@ class DescriptorSerializer private constructor( Variance.OUT_VARIANCE -> ProtoBuf.Type.Argument.Projection.OUT } - private fun hasAnnotations(descriptor: Annotated): Boolean = !descriptor.annotations.isEmpty() + private fun hasAnnotations(descriptor: Annotated): Boolean { + // Sadly, we can't just return `descriptor.nonSourceAnnotations.isNotEmpty()` because that would not + // consider use-site-targeted annotations + return descriptor.annotations.getAllAnnotations().filterNot { it.annotation.isSourceAnnotation }.isNotEmpty() + } fun sort(descriptors: Collection): List = ArrayList(descriptors).apply { diff --git a/compiler/serialization/src/org/jetbrains/kotlin/serialization/SerializerExtensionBase.kt b/compiler/serialization/src/org/jetbrains/kotlin/serialization/SerializerExtensionBase.kt index 9d86d44249a..ac85508fe3d 100644 --- a/compiler/serialization/src/org/jetbrains/kotlin/serialization/SerializerExtensionBase.kt +++ b/compiler/serialization/src/org/jetbrains/kotlin/serialization/SerializerExtensionBase.kt @@ -20,13 +20,14 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.constants.NullValue +import org.jetbrains.kotlin.resolve.descriptorUtil.nonSourceAnnotations import org.jetbrains.kotlin.types.KotlinType open class KotlinSerializerExtensionBase(private val protocol: SerializerExtensionProtocol) : SerializerExtension() { override val stringTable = StringTableImpl() override fun serializeClass(descriptor: ClassDescriptor, proto: ProtoBuf.Class.Builder) { - for (annotation in descriptor.annotations) { + for (annotation in descriptor.nonSourceAnnotations) { proto.addExtension(protocol.classAnnotation, annotationSerializer.serializeAnnotation(annotation)) } } @@ -36,19 +37,19 @@ open class KotlinSerializerExtensionBase(private val protocol: SerializerExtensi } override fun serializeConstructor(descriptor: ConstructorDescriptor, proto: ProtoBuf.Constructor.Builder) { - for (annotation in descriptor.annotations) { + for (annotation in descriptor.nonSourceAnnotations) { proto.addExtension(protocol.constructorAnnotation, annotationSerializer.serializeAnnotation(annotation)) } } override fun serializeFunction(descriptor: FunctionDescriptor, proto: ProtoBuf.Function.Builder) { - for (annotation in descriptor.annotations) { + for (annotation in descriptor.nonSourceAnnotations) { proto.addExtension(protocol.functionAnnotation, annotationSerializer.serializeAnnotation(annotation)) } } override fun serializeProperty(descriptor: PropertyDescriptor, proto: ProtoBuf.Property.Builder) { - for (annotation in descriptor.annotations) { + for (annotation in descriptor.nonSourceAnnotations) { proto.addExtension(protocol.propertyAnnotation, annotationSerializer.serializeAnnotation(annotation)) } val constantInitializer = descriptor.compileTimeInitializer ?: return @@ -58,25 +59,25 @@ open class KotlinSerializerExtensionBase(private val protocol: SerializerExtensi } override fun serializeEnumEntry(descriptor: ClassDescriptor, proto: ProtoBuf.EnumEntry.Builder) { - for (annotation in descriptor.annotations) { + for (annotation in descriptor.nonSourceAnnotations) { proto.addExtension(protocol.enumEntryAnnotation, annotationSerializer.serializeAnnotation(annotation)) } } override fun serializeValueParameter(descriptor: ValueParameterDescriptor, proto: ProtoBuf.ValueParameter.Builder) { - for (annotation in descriptor.annotations) { + for (annotation in descriptor.nonSourceAnnotations) { proto.addExtension(protocol.parameterAnnotation, annotationSerializer.serializeAnnotation(annotation)) } } override fun serializeType(type: KotlinType, proto: ProtoBuf.Type.Builder) { - for (annotation in type.annotations) { + for (annotation in type.nonSourceAnnotations) { proto.addExtension(protocol.typeAnnotation, annotationSerializer.serializeAnnotation(annotation)) } } override fun serializeTypeParameter(typeParameter: TypeParameterDescriptor, proto: ProtoBuf.TypeParameter.Builder) { - for (annotation in typeParameter.annotations) { + for (annotation in typeParameter.nonSourceAnnotations) { proto.addExtension(protocol.typeParameterAnnotation, annotationSerializer.serializeAnnotation(annotation)) } } diff --git a/compiler/testData/loadJava/compiledKotlin/annotations/types/SourceRetention.kt b/compiler/testData/loadJava/compiledKotlin/annotations/types/SourceRetention.kt new file mode 100644 index 00000000000..995b43c418f --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlin/annotations/types/SourceRetention.kt @@ -0,0 +1,17 @@ +// ALLOW_AST_ACCESS +// NO_CHECK_SOURCE_VS_BINARY + +package test + +@Target(AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.TYPEALIAS, AnnotationTarget.TYPE) +@Retention(AnnotationRetention.SOURCE) +annotation class A + +class TypeParameterAnnotation { + fun <@A T> foo(x: T) {} +} + +@A +typealias TypeAliasAnnotation = List + +fun typeAnnotation(): @A Unit {} diff --git a/compiler/testData/loadJava/compiledKotlin/annotations/types/SourceRetention.txt b/compiler/testData/loadJava/compiledKotlin/annotations/types/SourceRetention.txt new file mode 100644 index 00000000000..2dcff05a5cd --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlin/annotations/types/SourceRetention.txt @@ -0,0 +1,13 @@ +package test + +public fun typeAnnotation(): kotlin.Unit + +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.TYPEALIAS, AnnotationTarget.TYPE}) @kotlin.annotation.Retention(value = AnnotationRetention.SOURCE) public final annotation class A : kotlin.Annotation { + /*primary*/ public constructor A() +} + +public final class TypeParameterAnnotation { + /*primary*/ public constructor TypeParameterAnnotation() + public final fun foo(/*0*/ x: T): kotlin.Unit +} +public typealias TypeAliasAnnotation = kotlin.collections.List diff --git a/compiler/testData/serialization/builtinsSerializer/binaryRetainedAnnotation.kt b/compiler/testData/serialization/builtinsSerializer/binaryRetainedAnnotation.kt new file mode 100644 index 00000000000..99796764d56 --- /dev/null +++ b/compiler/testData/serialization/builtinsSerializer/binaryRetainedAnnotation.kt @@ -0,0 +1,21 @@ +package test + +import kotlin.annotation.AnnotationTarget.* + +@Retention(AnnotationRetention.BINARY) +@Target(CLASS, CONSTRUCTOR, FUNCTION, PROPERTY, VALUE_PARAMETER, TYPE, TYPE_PARAMETER) +annotation class A + +@A +class Klass @A constructor() + +@A +fun <@A T> function(@A param: Unit): @A Unit {} + +@A +val property = Unit + +enum class Enum { + @A + ENTRY +} diff --git a/compiler/testData/serialization/builtinsSerializer/binaryRetainedAnnotation.txt b/compiler/testData/serialization/builtinsSerializer/binaryRetainedAnnotation.txt new file mode 100644 index 00000000000..eba3372b80b --- /dev/null +++ b/compiler/testData/serialization/builtinsSerializer/binaryRetainedAnnotation.txt @@ -0,0 +1,26 @@ +package test + +@test.A public val property: kotlin.Unit +@test.A public fun function(/*0*/ @test.A param: kotlin.Unit): @test.A kotlin.Unit + +@kotlin.annotation.Retention(value = AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER}) public final annotation class A : kotlin.Annotation { + public constructor A() +} + +public final enum class Enum : kotlin.Enum { + @test.A enum entry ENTRY + + private constructor Enum() + public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: test.Enum): kotlin.Int + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): test.Enum + public final /*synthesized*/ fun values(): kotlin.Array +} + +@test.A public final class Klass { + @test.A public constructor Klass() +} diff --git a/compiler/testData/serialization/builtinsSerializer/sourceRetainedAnnotation.kt b/compiler/testData/serialization/builtinsSerializer/sourceRetainedAnnotation.kt new file mode 100644 index 00000000000..24564a1c2ca --- /dev/null +++ b/compiler/testData/serialization/builtinsSerializer/sourceRetainedAnnotation.kt @@ -0,0 +1,21 @@ +package test + +import kotlin.annotation.AnnotationTarget.* + +@Retention(AnnotationRetention.SOURCE) +@Target(CLASS, CONSTRUCTOR, FUNCTION, PROPERTY, VALUE_PARAMETER, TYPE, TYPE_PARAMETER) +annotation class A + +@A +class Klass @A constructor() + +@A +fun <@A T> function(@A param: Unit): @A Unit {} + +@A +val property = Unit + +enum class Enum { + @A + ENTRY +} diff --git a/compiler/testData/serialization/builtinsSerializer/sourceRetainedAnnotation.txt b/compiler/testData/serialization/builtinsSerializer/sourceRetainedAnnotation.txt new file mode 100644 index 00000000000..078881e0ffa --- /dev/null +++ b/compiler/testData/serialization/builtinsSerializer/sourceRetainedAnnotation.txt @@ -0,0 +1,26 @@ +package test + +public val property: kotlin.Unit +public fun function(/*0*/ param: kotlin.Unit): kotlin.Unit + +@kotlin.annotation.Retention(value = AnnotationRetention.SOURCE) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER}) public final annotation class A : kotlin.Annotation { + public constructor A() +} + +public final enum class Enum : kotlin.Enum { + enum entry ENTRY + + private constructor Enum() + public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: test.Enum): kotlin.Int + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): test.Enum + public final /*synthesized*/ fun values(): kotlin.Array +} + +public final class Klass { + public constructor Klass() +} diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/AbstractLoadJavaTest.java b/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/AbstractLoadJavaTest.java index 5cf6787adc2..6148815ff4c 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/AbstractLoadJavaTest.java +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/AbstractLoadJavaTest.java @@ -119,7 +119,8 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir { if (useTypeTableInSerializer) { configuration.put(JVMConfigurationKeys.USE_TYPE_TABLE, true); } - updateConfigurationWithDirectives(ktFile, configuration); + String fileContent = FileUtil.loadFile(ktFile, true); + updateConfigurationWithDirectives(fileContent, configuration); KotlinCoreEnvironment environment = KotlinCoreEnvironment.createForTests(getTestRootDisposable(), configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES); @@ -143,11 +144,17 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir { DescriptorValidator.validate(errorTypesForbidden(), packageFromSource); DescriptorValidator.validate(new DeserializedScopeValidationVisitor(), packageFromBinary); Configuration comparatorConfiguration = COMPARATOR_CONFIGURATION.checkPrimaryConstructors(true).checkPropertyAccessors(true).checkFunctionContracts(true); - compareDescriptors(packageFromSource, packageFromBinary, comparatorConfiguration, txtFile); + + if (InTextDirectivesUtils.isDirectiveDefined(fileContent, "NO_CHECK_SOURCE_VS_BINARY")) { + // If NO_CHECK_SOURCE_VS_BINARY is enabled, only check that binary descriptors correspond to the .txt file content + validateAndCompareDescriptorWithFile(packageFromBinary, comparatorConfiguration, txtFile); + } + else { + compareDescriptors(packageFromSource, packageFromBinary, comparatorConfiguration, txtFile); + } } - private static void updateConfigurationWithDirectives(File file, CompilerConfiguration configuration) throws IOException { - String content = FileUtil.loadFile(file, true); + private static void updateConfigurationWithDirectives(String content, CompilerConfiguration configuration) { String version = InTextDirectivesUtils.findStringWithPrefixes(content, "// LANGUAGE_VERSION:"); if (version != null) { LanguageVersion explicitVersion = LanguageVersion.fromVersionString(version); diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java index a72228be87e..96aa38dc0f9 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java @@ -2089,6 +2089,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SimpleTypeAnnotation.kt"); } + @TestMetadata("SourceRetention.kt") + public void testSourceRetention() throws Exception { + runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SourceRetention.kt"); + } + @TestMetadata("SupertypesAndBounds.kt") public void testSupertypesAndBounds() throws Exception { runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SupertypesAndBounds.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadKotlinWithTypeTableTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadKotlinWithTypeTableTestGenerated.java index d36b0b73c05..01e5ac7e886 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadKotlinWithTypeTableTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadKotlinWithTypeTableTestGenerated.java @@ -433,6 +433,11 @@ public class LoadKotlinWithTypeTableTestGenerated extends AbstractLoadKotlinWith runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SimpleTypeAnnotation.kt"); } + @TestMetadata("SourceRetention.kt") + public void testSourceRetention() throws Exception { + runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SourceRetention.kt"); + } + @TestMetadata("SupertypesAndBounds.kt") public void testSupertypesAndBounds() throws Exception { runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SupertypesAndBounds.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/javac/LoadJavaUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/javac/LoadJavaUsingJavacTestGenerated.java index fa362dc29dc..a97c1249bb4 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/javac/LoadJavaUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/javac/LoadJavaUsingJavacTestGenerated.java @@ -2089,6 +2089,11 @@ public class LoadJavaUsingJavacTestGenerated extends AbstractLoadJavaUsingJavacT runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SimpleTypeAnnotation.kt"); } + @TestMetadata("SourceRetention.kt") + public void testSourceRetention() throws Exception { + runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SourceRetention.kt"); + } + @TestMetadata("SupertypesAndBounds.kt") public void testSupertypesAndBounds() throws Exception { runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SupertypesAndBounds.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/serialization/builtins/BuiltInsSerializerTest.kt b/compiler/tests/org/jetbrains/kotlin/serialization/builtins/BuiltInsSerializerTest.kt index 611c0ea9f84..6afe4049332 100644 --- a/compiler/tests/org/jetbrains/kotlin/serialization/builtins/BuiltInsSerializerTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/serialization/builtins/BuiltInsSerializerTest.kt @@ -104,4 +104,12 @@ class BuiltInsSerializerTest : TestCaseWithTmpdir() { fun testVarArgs() { doTest("annotationArguments/varargs.kt") } + + fun testSourceRetainedAnnotation() { + doTest("sourceRetainedAnnotation.kt") + } + + fun testBinaryRetainedAnnotation() { + doTest("binaryRetainedAnnotation.kt") + } } diff --git a/core/descriptors.runtime/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java b/core/descriptors.runtime/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java index b0298c2a544..b33bf825af8 100644 --- a/core/descriptors.runtime/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java +++ b/core/descriptors.runtime/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java @@ -435,6 +435,11 @@ public class JvmRuntimeDescriptorLoaderTestGenerated extends AbstractJvmRuntimeD runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SimpleTypeAnnotation.kt"); } + @TestMetadata("SourceRetention.kt") + public void testSourceRetention() throws Exception { + runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SourceRetention.kt"); + } + @TestMetadata("SupertypesAndBounds.kt") public void testSupertypesAndBounds() throws Exception { runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SupertypesAndBounds.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/Annotations.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/Annotations.kt index bb9bea4eb38..07baa77e14e 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/Annotations.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/Annotations.kt @@ -23,7 +23,13 @@ interface Annotated { } interface Annotations : Iterable { - + /** + * @return `true` iff there are no "direct" annotations applicable to this declaration. Note that even if [isEmpty] is `true`, + * there may be use-site-targeted annotations applicable to the declaration! + * + * @see getUseSiteTargetedAnnotations + * @see getAllAnnotations + */ fun isEmpty(): Boolean fun findAnnotation(fqName: FqName): AnnotationDescriptor? = firstOrNull { it.fqName == fqName } @@ -32,7 +38,9 @@ interface Annotations : Iterable { fun getUseSiteTargetedAnnotations(): List - // Returns both targeted and annotations without target. Annotation order is preserved. + /** + * @return both targeted and annotations without target. Annotation order is preserved. + */ fun getAllAnnotations(): List companion object { diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt index 830d643ad11..b00d57375ba 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt @@ -218,6 +218,18 @@ fun Annotated.getAnnotationRetention(): KotlinRetention? { return KotlinRetention.valueOf(retentionArgumentValue.enumEntryName.asString()) } +val Annotated.nonSourceAnnotations: List + get() = annotations.filterOutSourceAnnotations() + +fun Iterable.filterOutSourceAnnotations(): List = + filterNot(AnnotationDescriptor::isSourceAnnotation) + +val AnnotationDescriptor.isSourceAnnotation: Boolean + get() { + val classDescriptor = annotationClass + return classDescriptor == null || classDescriptor.getAnnotationRetention() == KotlinRetention.SOURCE + } + val DeclarationDescriptor.parentsWithSelf: Sequence get() = generateSequence(this, { it.containingDeclaration }) diff --git a/idea/testData/decompiler/decompiledTextJs/TypeAliases.expected.kt b/idea/testData/decompiler/decompiledTextJs/TypeAliases.expected.kt index e6d0e9d23e2..95f092f235b 100644 --- a/idea/testData/decompiler/decompiledTextJs/TypeAliases.expected.kt +++ b/idea/testData/decompiler/decompiledTextJs/TypeAliases.expected.kt @@ -9,15 +9,15 @@ package test public final class Outer public constructor() { public final inner class Inner public constructor() { - @kotlin.Suppress public typealias TA = kotlin.collections.Map, kotlin.collections.Map> + public typealias TA = kotlin.collections.Map, kotlin.collections.Map> } } public final class TypeAliases public constructor() { public final fun foo(a: dependency.A /* = () -> kotlin.Unit */, b: test.TypeAliases.B /* = (dependency.A /* = () -> kotlin.Unit */) -> kotlin.Unit */, ta: test.Outer.Inner.TA /* = kotlin.collections.Map, kotlin.collections.Map> */): kotlin.Unit { /* compiled code */ } - @kotlin.Suppress public typealias B = (dependency.A) -> kotlin.Unit + public typealias B = (dependency.A) -> kotlin.Unit - @test.Ann @kotlin.Suppress private typealias Parametrized = kotlin.collections.Map + @test.Ann private typealias Parametrized = kotlin.collections.Map } diff --git a/idea/testData/decompiler/decompiledTextJvm/TypeAliases.expected.kt b/idea/testData/decompiler/decompiledTextJvm/TypeAliases.expected.kt index 009a90b4109..d23de240446 100644 --- a/idea/testData/decompiler/decompiledTextJvm/TypeAliases.expected.kt +++ b/idea/testData/decompiler/decompiledTextJvm/TypeAliases.expected.kt @@ -6,8 +6,8 @@ package test public final class TypeAliases public constructor() { public final fun foo(a: dependency.A /* = () -> kotlin.Unit */, b: test.TypeAliases.B /* = (dependency.A /* = () -> kotlin.Unit */) -> kotlin.Unit */, ta: test.Outer.Inner.TA /* = kotlin.collections.Map, kotlin.collections.Map> */): kotlin.Unit { /* compiled code */ } - @kotlin.Suppress public typealias B = (dependency.A) -> kotlin.Unit + public typealias B = (dependency.A) -> kotlin.Unit - @test.Ann @kotlin.Suppress private typealias Parametrized = kotlin.collections.Map + @test.Ann private typealias Parametrized = kotlin.collections.Map } diff --git a/idea/testData/decompiler/stubBuilder/Annotations/Annotations.txt b/idea/testData/decompiler/stubBuilder/Annotations/Annotations.txt index fb04faceb90..b67877f58c2 100644 --- a/idea/testData/decompiler/stubBuilder/Annotations/Annotations.txt +++ b/idea/testData/decompiler/stubBuilder/Annotations/Annotations.txt @@ -268,11 +268,6 @@ PsiJetFileStubImpl[package=] TYPE_REFERENCE USER_TYPE REFERENCE_EXPRESSION[referencedName=a] - ANNOTATION_ENTRY[hasValueArguments=false, shortName=b] - CONSTRUCTOR_CALLEE - TYPE_REFERENCE - USER_TYPE - REFERENCE_EXPRESSION[referencedName=b] USER_TYPE USER_TYPE USER_TYPE @@ -286,11 +281,6 @@ PsiJetFileStubImpl[package=] TYPE_REFERENCE USER_TYPE REFERENCE_EXPRESSION[referencedName=a] - ANNOTATION_ENTRY[hasValueArguments=false, shortName=b] - CONSTRUCTOR_CALLEE - TYPE_REFERENCE - USER_TYPE - REFERENCE_EXPRESSION[referencedName=b] USER_TYPE USER_TYPE REFERENCE_EXPRESSION[referencedName=kotlin] diff --git a/idea/testData/decompiler/stubBuilder/TypeAliases/TypeAliases.txt b/idea/testData/decompiler/stubBuilder/TypeAliases/TypeAliases.txt index dfe3a14b92a..2cc7d31e187 100644 --- a/idea/testData/decompiler/stubBuilder/TypeAliases/TypeAliases.txt +++ b/idea/testData/decompiler/stubBuilder/TypeAliases/TypeAliases.txt @@ -97,13 +97,6 @@ PsiJetFileStubImpl[package=test] REFERENCE_EXPRESSION[referencedName=Unit] TYPEALIAS[fqName=test.TypeAliases.B, isTopLevel=false, name=B] MODIFIER_LIST[public] - ANNOTATION_ENTRY[hasValueArguments=false, shortName=Suppress] - CONSTRUCTOR_CALLEE - TYPE_REFERENCE - USER_TYPE - USER_TYPE - REFERENCE_EXPRESSION[referencedName=kotlin] - REFERENCE_EXPRESSION[referencedName=Suppress] TYPE_REFERENCE FUNCTION_TYPE VALUE_PARAMETER_LIST @@ -127,13 +120,6 @@ PsiJetFileStubImpl[package=test] USER_TYPE REFERENCE_EXPRESSION[referencedName=test] REFERENCE_EXPRESSION[referencedName=Ann] - ANNOTATION_ENTRY[hasValueArguments=false, shortName=Suppress] - CONSTRUCTOR_CALLEE - TYPE_REFERENCE - USER_TYPE - USER_TYPE - REFERENCE_EXPRESSION[referencedName=kotlin] - REFERENCE_EXPRESSION[referencedName=Suppress] TYPE_PARAMETER_LIST TYPE_PARAMETER[fqName=null, isInVariance=false, isOutVariance=false, name=E] TYPE_PARAMETER[fqName=null, isInVariance=false, isOutVariance=false, name=F] diff --git a/idea/tests/org/jetbrains/kotlin/idea/decompiler/stubBuilder/LoadJavaClsStubTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/decompiler/stubBuilder/LoadJavaClsStubTestGenerated.java index 4b4f79e8ba4..bb0518e8bdd 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/decompiler/stubBuilder/LoadJavaClsStubTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/decompiler/stubBuilder/LoadJavaClsStubTestGenerated.java @@ -433,6 +433,11 @@ public class LoadJavaClsStubTestGenerated extends AbstractLoadJavaClsStubTest { runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SimpleTypeAnnotation.kt"); } + @TestMetadata("SourceRetention.kt") + public void testSourceRetention() throws Exception { + runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SourceRetention.kt"); + } + @TestMetadata("SupertypesAndBounds.kt") public void testSupertypesAndBounds() throws Exception { runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SupertypesAndBounds.kt"); diff --git a/idea/tests/org/jetbrains/kotlin/idea/stubs/AbstractResolveByStubTest.kt b/idea/tests/org/jetbrains/kotlin/idea/stubs/AbstractResolveByStubTest.kt index 2b77c2bdc0d..f3eb8a62ba4 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/stubs/AbstractResolveByStubTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/stubs/AbstractResolveByStubTest.kt @@ -24,21 +24,26 @@ import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.test.InTextDirectivesUtils import org.jetbrains.kotlin.test.util.DescriptorValidator.ValidationVisitor.errorTypesForbidden import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator import org.junit.Assert import java.io.File abstract class AbstractResolveByStubTest : KotlinLightCodeInsightFixtureTestCase() { - @Throws(Exception::class) protected fun doTest(testFileName: String) { doTest(testFileName, true, true) } override fun getProjectDescriptor(): LightProjectDescriptor = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE - @Throws(Exception::class) private fun doTest(path: String, checkPrimaryConstructors: Boolean, checkPropertyAccessors: Boolean) { + if (InTextDirectivesUtils.isDirectiveDefined(File(path).readText(), "NO_CHECK_SOURCE_VS_BINARY")) { + // If NO_CHECK_SOURCE_VS_BINARY is enabled, source vs binary descriptors differ, which means that we should not run this test: + // it would compare descriptors resolved from sources (by stubs) with .txt, which describes binary descriptors + return + } + myFixture.configureByFile(path) val shouldFail = getTestName(false) == "ClassWithConstVal" AstAccessControl.testWithControlledAccessToAst(shouldFail, project, testRootDisposable) { diff --git a/idea/tests/org/jetbrains/kotlin/idea/stubs/ResolveByStubTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/stubs/ResolveByStubTestGenerated.java index 55369efb542..ab679c09bfd 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/stubs/ResolveByStubTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/stubs/ResolveByStubTestGenerated.java @@ -433,6 +433,11 @@ public class ResolveByStubTestGenerated extends AbstractResolveByStubTest { runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SimpleTypeAnnotation.kt"); } + @TestMetadata("SourceRetention.kt") + public void testSourceRetention() throws Exception { + runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SourceRetention.kt"); + } + @TestMetadata("SupertypesAndBounds.kt") public void testSupertypesAndBounds() throws Exception { runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SupertypesAndBounds.kt"); diff --git a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptSerializationUtil.kt b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptSerializationUtil.kt index 85eade564ce..9511d51cb5c 100644 --- a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptSerializationUtil.kt +++ b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptSerializationUtil.kt @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.protobuf.CodedInputStream import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.descriptorUtil.filterOutSourceAnnotations import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.MemberScope @@ -250,7 +251,7 @@ object KotlinJavascriptSerializationUtil { is KotlinPsiFileMetadata -> file.ktFile.annotationEntries.map { bindingContext[BindingContext.ANNOTATION, it]!! } is KotlinDeserializedFileMetadata -> file.packageFragment.fileMap[file.fileId]!!.annotations } - for (annotation in annotations) { + for (annotation in annotations.filterOutSourceAnnotations()) { fileProto.addAnnotation(serializer.serializeAnnotation(annotation)) } filesProto.addFile(fileProto)