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
This commit is contained in:
Alexander Udalov
2018-03-21 17:22:13 +01:00
parent 7bac9b62c7
commit 965e3ebab2
25 changed files with 231 additions and 53 deletions
@@ -136,16 +136,14 @@ public class JvmSerializerExtension extends SerializerExtension {
@Override @Override
public void serializeType(@NotNull KotlinType type, @NotNull ProtoBuf.Type.Builder proto) { 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 // 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)); proto.addExtension(JvmProtoBuf.typeAnnotation, annotationSerializer.serializeAnnotation(annotation));
} }
} }
@Override @Override
public void serializeTypeParameter( public void serializeTypeParameter(@NotNull TypeParameterDescriptor typeParameter, @NotNull ProtoBuf.TypeParameter.Builder proto) {
@NotNull TypeParameterDescriptor typeParameter, @NotNull ProtoBuf.TypeParameter.Builder proto for (AnnotationDescriptor annotation : DescriptorUtilsKt.getNonSourceAnnotations(typeParameter)) {
) {
for (AnnotationDescriptor annotation : typeParameter.getAnnotations()) {
proto.addExtension(JvmProtoBuf.typeParameterAnnotation, annotationSerializer.serializeAnnotation(annotation)); proto.addExtension(JvmProtoBuf.typeParameterAnnotation, annotationSerializer.serializeAnnotation(annotation));
} }
} }
@@ -33,6 +33,8 @@ import org.jetbrains.kotlin.resolve.constants.EnumValue
import org.jetbrains.kotlin.resolve.constants.IntValue import org.jetbrains.kotlin.resolve.constants.IntValue
import org.jetbrains.kotlin.resolve.constants.NullValue import org.jetbrains.kotlin.resolve.constants.NullValue
import org.jetbrains.kotlin.resolve.constants.StringValue 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.serialization.deserialization.ProtoEnumFlags
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.contains import org.jetbrains.kotlin.types.typeUtil.contains
@@ -396,7 +398,9 @@ class DescriptorSerializer private constructor(
builder.versionRequirement = requirement 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 return builder
} }
@@ -775,7 +779,11 @@ class DescriptorSerializer private constructor(
Variance.OUT_VARIANCE -> ProtoBuf.Type.Argument.Projection.OUT 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 <T : DeclarationDescriptor> sort(descriptors: Collection<T>): List<T> = fun <T : DeclarationDescriptor> sort(descriptors: Collection<T>): List<T> =
ArrayList(descriptors).apply { ArrayList(descriptors).apply {
@@ -20,13 +20,14 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.constants.NullValue import org.jetbrains.kotlin.resolve.constants.NullValue
import org.jetbrains.kotlin.resolve.descriptorUtil.nonSourceAnnotations
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
open class KotlinSerializerExtensionBase(private val protocol: SerializerExtensionProtocol) : SerializerExtension() { open class KotlinSerializerExtensionBase(private val protocol: SerializerExtensionProtocol) : SerializerExtension() {
override val stringTable = StringTableImpl() override val stringTable = StringTableImpl()
override fun serializeClass(descriptor: ClassDescriptor, proto: ProtoBuf.Class.Builder) { 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)) 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) { 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)) proto.addExtension(protocol.constructorAnnotation, annotationSerializer.serializeAnnotation(annotation))
} }
} }
override fun serializeFunction(descriptor: FunctionDescriptor, proto: ProtoBuf.Function.Builder) { 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)) proto.addExtension(protocol.functionAnnotation, annotationSerializer.serializeAnnotation(annotation))
} }
} }
override fun serializeProperty(descriptor: PropertyDescriptor, proto: ProtoBuf.Property.Builder) { 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)) proto.addExtension(protocol.propertyAnnotation, annotationSerializer.serializeAnnotation(annotation))
} }
val constantInitializer = descriptor.compileTimeInitializer ?: return 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) { 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)) proto.addExtension(protocol.enumEntryAnnotation, annotationSerializer.serializeAnnotation(annotation))
} }
} }
override fun serializeValueParameter(descriptor: ValueParameterDescriptor, proto: ProtoBuf.ValueParameter.Builder) { 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)) proto.addExtension(protocol.parameterAnnotation, annotationSerializer.serializeAnnotation(annotation))
} }
} }
override fun serializeType(type: KotlinType, proto: ProtoBuf.Type.Builder) { 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)) proto.addExtension(protocol.typeAnnotation, annotationSerializer.serializeAnnotation(annotation))
} }
} }
override fun serializeTypeParameter(typeParameter: TypeParameterDescriptor, proto: ProtoBuf.TypeParameter.Builder) { 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)) proto.addExtension(protocol.typeParameterAnnotation, annotationSerializer.serializeAnnotation(annotation))
} }
} }
@@ -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<X> = List<X>
fun typeAnnotation(): @A Unit {}
@@ -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 </*0*/ T> foo(/*0*/ x: T): kotlin.Unit
}
public typealias TypeAliasAnnotation</*0*/ X> = kotlin.collections.List<X>
@@ -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
}
@@ -0,0 +1,26 @@
package test
@test.A public val property: kotlin.Unit
@test.A public fun </*0*/ @test.A T> 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.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.Enum>
}
@test.A public final class Klass {
@test.A public constructor Klass()
}
@@ -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
}
@@ -0,0 +1,26 @@
package test
public val property: kotlin.Unit
public fun </*0*/ T> 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<test.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<test.Enum>
}
public final class Klass {
public constructor Klass()
}
@@ -119,7 +119,8 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
if (useTypeTableInSerializer) { if (useTypeTableInSerializer) {
configuration.put(JVMConfigurationKeys.USE_TYPE_TABLE, true); configuration.put(JVMConfigurationKeys.USE_TYPE_TABLE, true);
} }
updateConfigurationWithDirectives(ktFile, configuration); String fileContent = FileUtil.loadFile(ktFile, true);
updateConfigurationWithDirectives(fileContent, configuration);
KotlinCoreEnvironment environment = KotlinCoreEnvironment environment =
KotlinCoreEnvironment.createForTests(getTestRootDisposable(), configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES); KotlinCoreEnvironment.createForTests(getTestRootDisposable(), configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
@@ -143,11 +144,17 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
DescriptorValidator.validate(errorTypesForbidden(), packageFromSource); DescriptorValidator.validate(errorTypesForbidden(), packageFromSource);
DescriptorValidator.validate(new DeserializedScopeValidationVisitor(), packageFromBinary); DescriptorValidator.validate(new DeserializedScopeValidationVisitor(), packageFromBinary);
Configuration comparatorConfiguration = COMPARATOR_CONFIGURATION.checkPrimaryConstructors(true).checkPropertyAccessors(true).checkFunctionContracts(true); 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 { private static void updateConfigurationWithDirectives(String content, CompilerConfiguration configuration) {
String content = FileUtil.loadFile(file, true);
String version = InTextDirectivesUtils.findStringWithPrefixes(content, "// LANGUAGE_VERSION:"); String version = InTextDirectivesUtils.findStringWithPrefixes(content, "// LANGUAGE_VERSION:");
if (version != null) { if (version != null) {
LanguageVersion explicitVersion = LanguageVersion.fromVersionString(version); LanguageVersion explicitVersion = LanguageVersion.fromVersionString(version);
@@ -2089,6 +2089,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SimpleTypeAnnotation.kt"); 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") @TestMetadata("SupertypesAndBounds.kt")
public void testSupertypesAndBounds() throws Exception { public void testSupertypesAndBounds() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SupertypesAndBounds.kt"); runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SupertypesAndBounds.kt");
@@ -433,6 +433,11 @@ public class LoadKotlinWithTypeTableTestGenerated extends AbstractLoadKotlinWith
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SimpleTypeAnnotation.kt"); 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") @TestMetadata("SupertypesAndBounds.kt")
public void testSupertypesAndBounds() throws Exception { public void testSupertypesAndBounds() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SupertypesAndBounds.kt"); runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SupertypesAndBounds.kt");
@@ -2089,6 +2089,11 @@ public class LoadJavaUsingJavacTestGenerated extends AbstractLoadJavaUsingJavacT
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SimpleTypeAnnotation.kt"); 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") @TestMetadata("SupertypesAndBounds.kt")
public void testSupertypesAndBounds() throws Exception { public void testSupertypesAndBounds() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SupertypesAndBounds.kt"); runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SupertypesAndBounds.kt");
@@ -104,4 +104,12 @@ class BuiltInsSerializerTest : TestCaseWithTmpdir() {
fun testVarArgs() { fun testVarArgs() {
doTest("annotationArguments/varargs.kt") doTest("annotationArguments/varargs.kt")
} }
fun testSourceRetainedAnnotation() {
doTest("sourceRetainedAnnotation.kt")
}
fun testBinaryRetainedAnnotation() {
doTest("binaryRetainedAnnotation.kt")
}
} }
@@ -435,6 +435,11 @@ public class JvmRuntimeDescriptorLoaderTestGenerated extends AbstractJvmRuntimeD
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SimpleTypeAnnotation.kt"); 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") @TestMetadata("SupertypesAndBounds.kt")
public void testSupertypesAndBounds() throws Exception { public void testSupertypesAndBounds() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SupertypesAndBounds.kt"); runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SupertypesAndBounds.kt");
@@ -23,7 +23,13 @@ interface Annotated {
} }
interface Annotations : Iterable<AnnotationDescriptor> { interface Annotations : Iterable<AnnotationDescriptor> {
/**
* @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 isEmpty(): Boolean
fun findAnnotation(fqName: FqName): AnnotationDescriptor? = firstOrNull { it.fqName == fqName } fun findAnnotation(fqName: FqName): AnnotationDescriptor? = firstOrNull { it.fqName == fqName }
@@ -32,7 +38,9 @@ interface Annotations : Iterable<AnnotationDescriptor> {
fun getUseSiteTargetedAnnotations(): List<AnnotationWithTarget> fun getUseSiteTargetedAnnotations(): List<AnnotationWithTarget>
// 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<AnnotationWithTarget> fun getAllAnnotations(): List<AnnotationWithTarget>
companion object { companion object {
@@ -218,6 +218,18 @@ fun Annotated.getAnnotationRetention(): KotlinRetention? {
return KotlinRetention.valueOf(retentionArgumentValue.enumEntryName.asString()) return KotlinRetention.valueOf(retentionArgumentValue.enumEntryName.asString())
} }
val Annotated.nonSourceAnnotations: List<AnnotationDescriptor>
get() = annotations.filterOutSourceAnnotations()
fun Iterable<AnnotationDescriptor>.filterOutSourceAnnotations(): List<AnnotationDescriptor> =
filterNot(AnnotationDescriptor::isSourceAnnotation)
val AnnotationDescriptor.isSourceAnnotation: Boolean
get() {
val classDescriptor = annotationClass
return classDescriptor == null || classDescriptor.getAnnotationRetention() == KotlinRetention.SOURCE
}
val DeclarationDescriptor.parentsWithSelf: Sequence<DeclarationDescriptor> val DeclarationDescriptor.parentsWithSelf: Sequence<DeclarationDescriptor>
get() = generateSequence(this, { it.containingDeclaration }) get() = generateSequence(this, { it.containingDeclaration })
@@ -9,15 +9,15 @@ package test
public final class Outer<E, F> public constructor() { public final class Outer<E, F> public constructor() {
public final inner class Inner<G> public constructor() { public final inner class Inner<G> public constructor() {
@kotlin.Suppress public typealias TA<H> = kotlin.collections.Map<kotlin.collections.Map<E, F>, kotlin.collections.Map<G, H>> public typealias TA<H> = kotlin.collections.Map<kotlin.collections.Map<E, F>, kotlin.collections.Map<G, H>>
} }
} }
public final class TypeAliases public constructor() { 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<kotlin.String, kotlin.Double>.Inner<kotlin.Int>.TA<kotlin.Boolean> /* = kotlin.collections.Map<kotlin.collections.Map<kotlin.String, kotlin.Double>, kotlin.collections.Map<kotlin.Int, kotlin.Boolean>> */): kotlin.Unit { /* compiled code */ } public final fun foo(a: dependency.A /* = () -> kotlin.Unit */, b: test.TypeAliases.B /* = (dependency.A /* = () -> kotlin.Unit */) -> kotlin.Unit */, ta: test.Outer<kotlin.String, kotlin.Double>.Inner<kotlin.Int>.TA<kotlin.Boolean> /* = kotlin.collections.Map<kotlin.collections.Map<kotlin.String, kotlin.Double>, kotlin.collections.Map<kotlin.Int, kotlin.Boolean>> */): 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<E, F> = kotlin.collections.Map<E, F> @test.Ann private typealias Parametrized<E, F> = kotlin.collections.Map<E, F>
} }
@@ -6,8 +6,8 @@ package test
public final class TypeAliases public constructor() { 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<kotlin.String, kotlin.Double>.Inner<kotlin.Int>.TA<kotlin.Boolean> /* = kotlin.collections.Map<kotlin.collections.Map<kotlin.String, kotlin.Double>, kotlin.collections.Map<kotlin.Int, kotlin.Boolean>> */): kotlin.Unit { /* compiled code */ } public final fun foo(a: dependency.A /* = () -> kotlin.Unit */, b: test.TypeAliases.B /* = (dependency.A /* = () -> kotlin.Unit */) -> kotlin.Unit */, ta: test.Outer<kotlin.String, kotlin.Double>.Inner<kotlin.Int>.TA<kotlin.Boolean> /* = kotlin.collections.Map<kotlin.collections.Map<kotlin.String, kotlin.Double>, kotlin.collections.Map<kotlin.Int, kotlin.Boolean>> */): 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<E, F> = kotlin.collections.Map<E, F> @test.Ann private typealias Parametrized<E, F> = kotlin.collections.Map<E, F>
} }
@@ -268,11 +268,6 @@ PsiJetFileStubImpl[package=]
TYPE_REFERENCE TYPE_REFERENCE
USER_TYPE USER_TYPE
REFERENCE_EXPRESSION[referencedName=a] 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 USER_TYPE
USER_TYPE USER_TYPE
@@ -286,11 +281,6 @@ PsiJetFileStubImpl[package=]
TYPE_REFERENCE TYPE_REFERENCE
USER_TYPE USER_TYPE
REFERENCE_EXPRESSION[referencedName=a] 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 USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin] REFERENCE_EXPRESSION[referencedName=kotlin]
@@ -97,13 +97,6 @@ PsiJetFileStubImpl[package=test]
REFERENCE_EXPRESSION[referencedName=Unit] REFERENCE_EXPRESSION[referencedName=Unit]
TYPEALIAS[fqName=test.TypeAliases.B, isTopLevel=false, name=B] TYPEALIAS[fqName=test.TypeAliases.B, isTopLevel=false, name=B]
MODIFIER_LIST[public] 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 TYPE_REFERENCE
FUNCTION_TYPE FUNCTION_TYPE
VALUE_PARAMETER_LIST VALUE_PARAMETER_LIST
@@ -127,13 +120,6 @@ PsiJetFileStubImpl[package=test]
USER_TYPE USER_TYPE
REFERENCE_EXPRESSION[referencedName=test] REFERENCE_EXPRESSION[referencedName=test]
REFERENCE_EXPRESSION[referencedName=Ann] 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_LIST
TYPE_PARAMETER[fqName=null, isInVariance=false, isOutVariance=false, name=E] TYPE_PARAMETER[fqName=null, isInVariance=false, isOutVariance=false, name=E]
TYPE_PARAMETER[fqName=null, isInVariance=false, isOutVariance=false, name=F] TYPE_PARAMETER[fqName=null, isInVariance=false, isOutVariance=false, name=F]
@@ -433,6 +433,11 @@ public class LoadJavaClsStubTestGenerated extends AbstractLoadJavaClsStubTest {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SimpleTypeAnnotation.kt"); 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") @TestMetadata("SupertypesAndBounds.kt")
public void testSupertypesAndBounds() throws Exception { public void testSupertypesAndBounds() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SupertypesAndBounds.kt"); runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SupertypesAndBounds.kt");
@@ -24,21 +24,26 @@ import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtFile 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.DescriptorValidator.ValidationVisitor.errorTypesForbidden
import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator
import org.junit.Assert import org.junit.Assert
import java.io.File import java.io.File
abstract class AbstractResolveByStubTest : KotlinLightCodeInsightFixtureTestCase() { abstract class AbstractResolveByStubTest : KotlinLightCodeInsightFixtureTestCase() {
@Throws(Exception::class)
protected fun doTest(testFileName: String) { protected fun doTest(testFileName: String) {
doTest(testFileName, true, true) doTest(testFileName, true, true)
} }
override fun getProjectDescriptor(): LightProjectDescriptor = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE override fun getProjectDescriptor(): LightProjectDescriptor = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
@Throws(Exception::class)
private fun doTest(path: String, checkPrimaryConstructors: Boolean, checkPropertyAccessors: Boolean) { 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) myFixture.configureByFile(path)
val shouldFail = getTestName(false) == "ClassWithConstVal" val shouldFail = getTestName(false) == "ClassWithConstVal"
AstAccessControl.testWithControlledAccessToAst(shouldFail, project, testRootDisposable) { AstAccessControl.testWithControlledAccessToAst(shouldFail, project, testRootDisposable) {
@@ -433,6 +433,11 @@ public class ResolveByStubTestGenerated extends AbstractResolveByStubTest {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SimpleTypeAnnotation.kt"); 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") @TestMetadata("SupertypesAndBounds.kt")
public void testSupertypesAndBounds() throws Exception { public void testSupertypesAndBounds() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SupertypesAndBounds.kt"); runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/SupertypesAndBounds.kt");
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.protobuf.CodedInputStream import org.jetbrains.kotlin.protobuf.CodedInputStream
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils 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.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScope
@@ -250,7 +251,7 @@ object KotlinJavascriptSerializationUtil {
is KotlinPsiFileMetadata -> file.ktFile.annotationEntries.map { bindingContext[BindingContext.ANNOTATION, it]!! } is KotlinPsiFileMetadata -> file.ktFile.annotationEntries.map { bindingContext[BindingContext.ANNOTATION, it]!! }
is KotlinDeserializedFileMetadata -> file.packageFragment.fileMap[file.fileId]!!.annotations is KotlinDeserializedFileMetadata -> file.packageFragment.fileMap[file.fileId]!!.annotations
} }
for (annotation in annotations) { for (annotation in annotations.filterOutSourceAnnotations()) {
fileProto.addAnnotation(serializer.serializeAnnotation(annotation)) fileProto.addAnnotation(serializer.serializeAnnotation(annotation))
} }
filesProto.addFile(fileProto) filesProto.addFile(fileProto)