mirror of
https://github.com/fankes/moshi.git
synced 2025-10-19 07:59:21 +08:00
Fail on sealed classes in KotlinJsonAdapterFactory and code gen (#914)
Resolves #906
This commit is contained in:
@@ -57,6 +57,7 @@ import me.eugeniomarletti.kotlin.metadata.kotlinMetadata
|
||||
import me.eugeniomarletti.kotlin.metadata.modality
|
||||
import me.eugeniomarletti.kotlin.metadata.shadow.metadata.ProtoBuf.Class
|
||||
import me.eugeniomarletti.kotlin.metadata.shadow.metadata.ProtoBuf.Modality.ABSTRACT
|
||||
import me.eugeniomarletti.kotlin.metadata.shadow.metadata.ProtoBuf.Modality.SEALED
|
||||
import me.eugeniomarletti.kotlin.metadata.shadow.metadata.ProtoBuf.Type
|
||||
import me.eugeniomarletti.kotlin.metadata.shadow.metadata.ProtoBuf.TypeParameter
|
||||
import me.eugeniomarletti.kotlin.metadata.shadow.metadata.ProtoBuf.TypeParameter.Variance
|
||||
@@ -277,6 +278,11 @@ internal fun targetType(messager: Messager,
|
||||
ERROR, "@JsonClass can't be applied to $element: must not be an inner class", element)
|
||||
return null
|
||||
}
|
||||
proto.modality == SEALED -> {
|
||||
messager.printMessage(
|
||||
ERROR, "@JsonClass can't be applied to $element: must not be sealed", element)
|
||||
return null
|
||||
}
|
||||
proto.modality == ABSTRACT -> {
|
||||
messager.printMessage(
|
||||
ERROR, "@JsonClass can't be applied to $element: must not be abstract", element)
|
||||
|
@@ -118,6 +118,23 @@ class JsonClassCodegenProcessorTest {
|
||||
"error: @JsonClass can't be applied to AbstractClass: must not be abstract")
|
||||
}
|
||||
|
||||
@Test fun sealedClassesNotSupported() {
|
||||
val call = KotlinCompilerCall(temporaryFolder.root)
|
||||
call.inheritClasspath = true
|
||||
call.addService(Processor::class, JsonClassCodegenProcessor::class)
|
||||
call.addKt("source.kt", """
|
||||
|import com.squareup.moshi.JsonClass
|
||||
|
|
||||
|@JsonClass(generateAdapter = true)
|
||||
|sealed class SealedClass(val a: Int)
|
||||
|""".trimMargin())
|
||||
|
||||
val result = call.execute()
|
||||
assertThat(result.exitCode).isEqualTo(ExitCode.COMPILATION_ERROR)
|
||||
assertThat(result.systemErr).contains(
|
||||
"error: @JsonClass can't be applied to SealedClass: must not be sealed")
|
||||
}
|
||||
|
||||
@Test fun innerClassesNotSupported() {
|
||||
val call = KotlinCompilerCall(temporaryFolder.root)
|
||||
call.inheritClasspath = true
|
||||
|
@@ -202,6 +202,9 @@ class KotlinJsonAdapterFactory : JsonAdapter.Factory {
|
||||
require(rawTypeKotlin.objectInstance == null) {
|
||||
"Cannot serialize object declaration ${rawType.name}"
|
||||
}
|
||||
require(!rawTypeKotlin.isSealed) {
|
||||
"Cannot reflectively serialize sealed class ${rawType.name}. Please register an adapter."
|
||||
}
|
||||
|
||||
val constructor = rawTypeKotlin.primaryConstructor ?: return null
|
||||
val parametersByName = constructor.parameters.associateBy { it.name }
|
||||
|
@@ -1113,6 +1113,21 @@ class KotlinJsonAdapterTest {
|
||||
@JvmSuppressWildcards(suppress = false)
|
||||
data class MapOfStringToClassCodegen(val map: Map<String, ConstructorParameters> = mapOf())
|
||||
|
||||
@Test fun sealedClassesAreRejected() {
|
||||
val moshi = Moshi.Builder()
|
||||
.add(KotlinJsonAdapterFactory())
|
||||
.build()
|
||||
|
||||
try {
|
||||
moshi.adapter<SealedClass>()
|
||||
fail()
|
||||
} catch (e: IllegalArgumentException) {
|
||||
assertThat(e).hasMessageContaining("Cannot reflectively serialize sealed class")
|
||||
}
|
||||
}
|
||||
|
||||
sealed class SealedClass
|
||||
|
||||
private fun <T> mapWildcardsParameterizedTest(type: Class<T>, json: String, value: T) {
|
||||
// Ensure the map was created with the expected wildcards of a Kotlin map.
|
||||
val fieldType = type.getDeclaredField("map").genericType
|
||||
|
Reference in New Issue
Block a user