diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationAndConstantLoader.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationAndConstantLoader.kt index b07959df560..c949c4cb35c 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationAndConstantLoader.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationAndConstantLoader.kt @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.load.kotlin import com.google.protobuf.MessageLite -import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.SourceElement import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget import org.jetbrains.kotlin.load.java.JvmAbi @@ -133,8 +132,9 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader { - val kotlinClass = findClassWithAnnotationsAndInitializers(container, getImplClassName(container, property, isConst), field) - ?: return listOf() + val kotlinClass = + findClassWithAnnotationsAndInitializers(container, getSpecialCaseContainerClass(container, property, field, isConst)) + ?: return listOf() return storage(kotlinClass).memberAnnotations[signature] ?: listOf() } @@ -195,60 +195,54 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader specialCase + container is ProtoContainer.Class -> container.toBinaryClass() + else -> null } - - if (implClassName != null) { - return kotlinClassFinder.findKotlinClass(implClassName) - } - - return null } - private fun getImplClassName(container: ProtoContainer, property: Boolean, isConst: Boolean?): ClassId? { + // TODO: do not use KotlinClassFinder#findKotlinClass here because it traverses the file system in the compiler + // Introduce an API in KotlinJvmBinaryClass to find a class nearby instead + private fun getSpecialCaseContainerClass( + container: ProtoContainer, property: Boolean, field: Boolean, isConst: Boolean? + ): KotlinJvmBinaryClass? { if (property) { checkNotNull(isConst) { "isConst should not be null for property (container=$container)" } if (container is ProtoContainer.Class && container.kind == ProtoBuf.Class.Kind.INTERFACE) { - return container.classId.createNestedClassId(Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME)) + return kotlinClassFinder.findKotlinClass( + container.classId.createNestedClassId(Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME)) + ) } if (isConst!! && container is ProtoContainer.Package) { // Const properties in multifile classes are generated into the facade class val facadeClassName = (container.source as? JvmPackagePartSource)?.facadeClassName if (facadeClassName != null) { // Converting '/' to '.' is fine here because the facade class has a top level ClassId - return ClassId.topLevel(FqName(facadeClassName.internalName.replace('/', '.'))) + return kotlinClassFinder.findKotlinClass(ClassId.topLevel(FqName(facadeClassName.internalName.replace('/', '.')))) } } } - return ((container as? ProtoContainer.Package)?.source as? JvmPackagePartSource)?.classId + if (field && container is ProtoContainer.Class && container.kind == ProtoBuf.Class.Kind.COMPANION_OBJECT) { + val outerClass = container.outerClass + if (outerClass != null && (outerClass.kind == ProtoBuf.Class.Kind.CLASS || outerClass.kind == ProtoBuf.Class.Kind.ENUM_CLASS)) { + // Backing fields of properties of a companion object in a class are generated in the outer class + return outerClass.toBinaryClass() + } + } + if (container is ProtoContainer.Package && container.source is JvmPackagePartSource) { + return kotlinClassFinder.findKotlinClass((container.source as JvmPackagePartSource).classId) + } + return null } private fun loadAnnotationsAndInitializers(kotlinClass: KotlinJvmBinaryClass): Storage {