square/moshi

Moshi Polymorphic adapter fails on Kotlin 2.0 scripts

franvis opened this issue · 0 comments

We are facing an issue with one of our kotlin scripts that uses a polymorphic adapter after starting to run it with Kotlin 2.0.

The exception we get is:

java.lang.IllegalStateException: Incomplete hierarchy for class TestBlockA, unresolved classes [TestBlock]
        at kotlin.reflect.jvm.internal.impl.descriptors.runtime.components.RuntimeErrorReporter.reportIncompleteHierarchy(RuntimeErrorReporter.kt:26)
        at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedClassDescriptor$DeserializedClassTypeConstructor.computeSupertypes(DeserializedClassDescriptor.kt:250)
        at kotlin.reflect.jvm.internal.impl.types.AbstractTypeConstructor.supertypes$lambda$0(AbstractTypeConstructor.kt:78)
        at kotlin.reflect.jvm.internal.impl.types.AbstractTypeConstructor.accessor$AbstractTypeConstructor$lambda0(AbstractTypeConstructor.kt)
        at kotlin.reflect.jvm.internal.impl.types.AbstractTypeConstructor$$Lambda$0.invoke(Unknown Source)
        at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$LockBasedLazyValue.invoke(LockBasedStorageManager.java:408)
        at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$LockBasedLazyValueWithPostCompute.invoke(LockBasedStorageManager.java:481)
        at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$LockBasedNotNullLazyValueWithPostCompute.invoke(LockBasedStorageManager.java:512)
        at kotlin.reflect.jvm.internal.impl.types.AbstractTypeConstructor.getSupertypes(AbstractTypeConstructor.kt:27)
        at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedClassDescriptor$DeserializedClassMemberScope.getNonDeclaredVariableNames(DeserializedClassDescriptor.kt:360)
        at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope$OptimizedImplementation.variableNames_delegate$lambda$9(DeserializedMemberScope.kt:262)
        at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope$OptimizedImplementation.accessor$DeserializedMemberScope$OptimizedImplementation$lambda4(DeserializedMemberScope.kt)
        at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope$OptimizedImplementation$$Lambda$4.invoke(Unknown Source)
        at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$LockBasedLazyValue.invoke(LockBasedStorageManager.java:408)
        at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$LockBasedNotNullLazyValue.invoke(LockBasedStorageManager.java:527)
        at kotlin.reflect.jvm.internal.impl.storage.StorageKt.getValue(storage.kt:42)
        at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope$OptimizedImplementation.getVariableNames(DeserializedMemberScope.kt:261)
        at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope$OptimizedImplementation.addFunctionsAndPropertiesTo(DeserializedMemberScope.kt:349)
        at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope.computeDescriptors(DeserializedMemberScope.kt:115)
        at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedClassDescriptor$DeserializedClassMemberScope.allDescriptors$lambda$2(DeserializedClassDescriptor.kt:279)
        at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedClassDescriptor$DeserializedClassMemberScope.accessor$DeserializedClassDescriptor$DeserializedClassMemberScope$lambda1(DeserializedClassDescriptor.kt)
        at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedClassDescriptor$DeserializedClassMemberScope$$Lambda$1.invoke(Unknown Source)
        at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$LockBasedLazyValue.invoke(LockBasedStorageManager.java:408)
        at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$LockBasedNotNullLazyValue.invoke(LockBasedStorageManager.java:527)
        at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedClassDescriptor$DeserializedClassMemberScope.getContributedDescriptors(DeserializedClassDescriptor.kt:289)
        at kotlin.reflect.jvm.internal.impl.resolve.scopes.ResolutionScope$DefaultImpls.getContributedDescriptors$default(ResolutionScope.kt:50)
        at kotlin.reflect.jvm.internal.KDeclarationContainerImpl.getMembers(KDeclarationContainerImpl.kt:58)
        at kotlin.reflect.jvm.internal.KClassImpl$Data.declaredNonStaticMembers_delegate$lambda$22(KClassImpl.kt:173)
        at kotlin.reflect.jvm.internal.KClassImpl$Data.accessor$KClassImpl$Data$lambda10(KClassImpl.kt)
        at kotlin.reflect.jvm.internal.KClassImpl$Data$$Lambda$10.invoke(Unknown Source)
        at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:70)
        at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
        at kotlin.reflect.jvm.internal.KClassImpl$Data.getDeclaredNonStaticMembers(KClassImpl.kt:173)
        at kotlin.reflect.jvm.internal.KClassImpl$Data.allNonStaticMembers_delegate$lambda$26(KClassImpl.kt:182)
        at kotlin.reflect.jvm.internal.KClassImpl$Data.accessor$KClassImpl$Data$lambda14(KClassImpl.kt)
        at kotlin.reflect.jvm.internal.KClassImpl$Data$$Lambda$14.invoke(Unknown Source)
        at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:70)
        at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
        at kotlin.reflect.jvm.internal.KClassImpl$Data.getAllNonStaticMembers(KClassImpl.kt:182)
        at kotlin.reflect.full.KClasses.getMemberProperties(KClasses.kt:148)
        at com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory.create(KotlinJsonAdapter.kt:234)
        at com.squareup.moshi.Moshi.adapter(Moshi.java:146)
        at com.squareup.moshi.Moshi.adapter(Moshi.java:106)
        at com.squareup.moshi.Moshi.adapter(Moshi.java:75)
        at com.squareup.moshi.adapters.PolymorphicJsonAdapterFactory.create(PolymorphicJsonAdapterFactory.java:216)
        at com.squareup.moshi.Moshi.adapter(Moshi.java:146)
        at com.squareup.moshi.Moshi.adapter(Moshi.java:106)
        at com.squareup.moshi.Moshi.adapter(Moshi.java:75)
        at com.squareup.moshi.CollectionJsonAdapter.newArrayListAdapter(CollectionJsonAdapter.java:54)
        at com.squareup.moshi.CollectionJsonAdapter$1.create(CollectionJsonAdapter.java:38)
        at com.squareup.moshi.Moshi.adapter(Moshi.java:146)
        at com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory.create(KotlinJsonAdapter.kt:292)
        at com.squareup.moshi.Moshi.adapter(Moshi.java:146)
        at com.squareup.moshi.Moshi.adapter(Moshi.java:106)
        at com.squareup.moshi.Moshi.adapter(Moshi.java:80)
        at Moshi_test_main.<init>(moshi_test.main.kts:51)

As an example, the following script will fail with the same exception we have:

#!/usr/bin/env kotlin
@file:DependsOn(
    "com.squareup.moshi:moshi:1.15.1",
    "com.squareup.moshi:moshi-kotlin:1.15.1",
    "com.squareup.moshi:moshi-adapters:1.15.1"
)

import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.JsonClass
import com.squareup.moshi.Moshi
import com.squareup.moshi.adapters.PolymorphicJsonAdapterFactory
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory

@JsonClass(generateAdapter = false)
sealed class TestBlock(open val type: String)

@JsonClass(generateAdapter = false)
data class TestPayload(val blocks: List<TestBlock>)

@JsonClass(generateAdapter = false)
data class TestBlockA(val text: String) : TestBlock(type = "test_a")

@JsonClass(generateAdapter = false)
data class TestBlockB(val elements: List<String>) : TestBlock(type = "test_b")

val adapter: JsonAdapter<TestPayload> =
    Moshi.Builder()
        .add(
            PolymorphicJsonAdapterFactory.of(TestBlock::class.java, "type")
                .withSubtype(TestBlockA::class.java, "test_a")
                .withSubtype(TestBlockB::class.java, "test_b")
        )
        .add(KotlinJsonAdapterFactory()).build().adapter(TestPayload::class.java)

Kotlin 2.0 scripts have known issues with nested classes and self references:

Is this related? Any advice on a workaround for it?

Thanks!