Do not build dummy light classes for serialization-related classes

Otherwise, whether LazyLightClassMemberMatchingError happens
or other type of errors because serialization plugin expects
full resolution in the correct module

Currently, only @Serializable annotation leads to exceptions,
but just in case we consider both of them as potentially problematic

 #KT-26895 Fixed
This commit is contained in:
Denis Zharkov
2018-09-17 16:25:40 +03:00
parent fe9ce45e1d
commit a4b2e5964a
3 changed files with 39 additions and 5 deletions
@@ -42,3 +42,6 @@ fun AnnotationDescriptor.argumentValue(parameterName: String): ConstantValue<*>?
DeprecationLevel.ERROR
)
val JVM_FIELD_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmField")
val KOTLINX_SERIALIZABLE_FQ_NAME = FqName("kotlinx.serialization.Serializable")
val KOTLINX_SERIALIZER_FQ_NAME = FqName("kotlinx.serialization.Serializer")
@@ -52,6 +52,8 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.annotations.KOTLINX_SERIALIZABLE_FQ_NAME
import org.jetbrains.kotlin.resolve.annotations.KOTLINX_SERIALIZER_FQ_NAME
import org.jetbrains.kotlin.resolve.calls.CallResolver
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
@@ -158,7 +160,10 @@ internal object IDELightClassContexts {
listOf(classOrObject.containingKtFile)
)
ForceResolveUtil.forceResolveAllContents(resolveSession.resolveToDescriptor(classOrObject))
val descriptor = resolveSession.resolveToDescriptor(classOrObject) as? ClassDescriptor ?: return null
if (!isDummyResolveApplicableByDescriptor(descriptor)) return null
ForceResolveUtil.forceResolveAllContents(descriptor)
return IDELightClassConstructionContext(resolveSession.bindingContext, resolveSession.moduleDescriptor, classOrObject.languageVersionSettings, LIGHT)
}
@@ -183,9 +188,30 @@ internal object IDELightClassContexts {
if (hasMembersOverridingInternalMembers(classOrObject)) return false
if (hasSerializationLikeAnnotations(classOrObject)) return false
return classOrObject.declarations.filterIsInstance<KtClassOrObject>().all { isDummyResolveApplicable(it) }
}
private fun hasSerializationLikeAnnotations(classOrObject: KtClassOrObject) =
classOrObject.annotationEntries.any { isSerializableOrSerializerShortName(it.shortName) }
private fun isDummyResolveApplicableByDescriptor(classDescriptor: ClassDescriptor): Boolean {
if (classDescriptor.annotations.any { isSerializableOrSerializerFqName(it.fqName) }) return false
return classDescriptor
.unsubstitutedInnerClassesScope
.getContributedDescriptors()
.filterIsInstance<ClassDescriptor>()
.all(::isDummyResolveApplicableByDescriptor)
}
private fun isSerializableOrSerializerShortName(shortName: Name?) =
shortName == KOTLINX_SERIALIZABLE_FQ_NAME.shortName() || shortName == KOTLINX_SERIALIZER_FQ_NAME.shortName()
private fun isSerializableOrSerializerFqName(fqName: FqName?) =
fqName == KOTLINX_SERIALIZABLE_FQ_NAME || fqName == KOTLINX_SERIALIZER_FQ_NAME
private fun hasDelegatedSupertypes(classOrObject: KtClassOrObject) =
classOrObject.superTypeListEntries.any { it is KtDelegatedSuperTypeEntry }
@@ -332,7 +358,9 @@ internal object IDELightClassContexts {
FqName("kotlin.PublishedApi") +
FqName("kotlin.Deprecated") +
FqName("kotlin.internal.InlineOnly") +
FqName("kotlinx.android.parcel.Parcelize")
FqName("kotlinx.android.parcel.Parcelize") +
KOTLINX_SERIALIZABLE_FQ_NAME +
KOTLINX_SERIALIZER_FQ_NAME
}
class AdHocAnnotationResolver(
@@ -1,7 +1,10 @@
package org.jetbrains.kotlinx.serialization.compiler.resolve
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.annotations.KOTLINX_SERIALIZABLE_FQ_NAME
import org.jetbrains.kotlin.resolve.annotations.KOTLINX_SERIALIZER_FQ_NAME
object SerializationPackages {
internal val packageFqName = FqName("kotlinx.serialization")
@@ -10,8 +13,8 @@ object SerializationPackages {
}
object SerializationAnnotations {
internal val serializableAnnotationFqName = FqName("kotlinx.serialization.Serializable")
internal val serializerAnnotationFqName = FqName("kotlinx.serialization.Serializer")
internal val serializableAnnotationFqName = KOTLINX_SERIALIZABLE_FQ_NAME
internal val serializerAnnotationFqName = KOTLINX_SERIALIZER_FQ_NAME
internal val serialNameAnnotationFqName = FqName("kotlinx.serialization.SerialName")
internal val serialOptionalFqName = FqName("kotlinx.serialization.Optional")
internal val serialTransientFqName = FqName("kotlinx.serialization.Transient")
@@ -81,4 +84,4 @@ object CallingConventions {
const val addElement = "addElement"
const val addAnnotation = "pushAnnotation"
const val addClassAnnotation = "pushClassAnnotation"
}
}