mirror of
https://github.com/fankes/moshi.git
synced 2025-10-20 00:19: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.modality
|
||||||
import me.eugeniomarletti.kotlin.metadata.shadow.metadata.ProtoBuf.Class
|
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.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.Type
|
||||||
import me.eugeniomarletti.kotlin.metadata.shadow.metadata.ProtoBuf.TypeParameter
|
import me.eugeniomarletti.kotlin.metadata.shadow.metadata.ProtoBuf.TypeParameter
|
||||||
import me.eugeniomarletti.kotlin.metadata.shadow.metadata.ProtoBuf.TypeParameter.Variance
|
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)
|
ERROR, "@JsonClass can't be applied to $element: must not be an inner class", element)
|
||||||
return null
|
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 -> {
|
proto.modality == ABSTRACT -> {
|
||||||
messager.printMessage(
|
messager.printMessage(
|
||||||
ERROR, "@JsonClass can't be applied to $element: must not be abstract", element)
|
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")
|
"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() {
|
@Test fun innerClassesNotSupported() {
|
||||||
val call = KotlinCompilerCall(temporaryFolder.root)
|
val call = KotlinCompilerCall(temporaryFolder.root)
|
||||||
call.inheritClasspath = true
|
call.inheritClasspath = true
|
||||||
|
@@ -202,6 +202,9 @@ class KotlinJsonAdapterFactory : JsonAdapter.Factory {
|
|||||||
require(rawTypeKotlin.objectInstance == null) {
|
require(rawTypeKotlin.objectInstance == null) {
|
||||||
"Cannot serialize object declaration ${rawType.name}"
|
"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 constructor = rawTypeKotlin.primaryConstructor ?: return null
|
||||||
val parametersByName = constructor.parameters.associateBy { it.name }
|
val parametersByName = constructor.parameters.associateBy { it.name }
|
||||||
|
@@ -1113,6 +1113,21 @@ class KotlinJsonAdapterTest {
|
|||||||
@JvmSuppressWildcards(suppress = false)
|
@JvmSuppressWildcards(suppress = false)
|
||||||
data class MapOfStringToClassCodegen(val map: Map<String, ConstructorParameters> = mapOf())
|
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) {
|
private fun <T> mapWildcardsParameterizedTest(type: Class<T>, json: String, value: T) {
|
||||||
// Ensure the map was created with the expected wildcards of a Kotlin map.
|
// Ensure the map was created with the expected wildcards of a Kotlin map.
|
||||||
val fieldType = type.getDeclaredField("map").genericType
|
val fieldType = type.getDeclaredField("map").genericType
|
||||||
|
Reference in New Issue
Block a user