se.ansman.kotshi.model.SealedClassJsonAdapter.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of compiler Show documentation
Show all versions of compiler Show documentation
An annotations processor that generates Moshi adapters from Kotlin data classes
The newest version!
package se.ansman.kotshi.model
import com.squareup.kotlinpoet.ClassName
import com.squareup.kotlinpoet.TypeName
import com.squareup.kotlinpoet.TypeVariableName
import se.ansman.kotshi.*
import se.ansman.kotshi.Errors.nestedSealedClassHasPolymorphicLabel
import se.ansman.kotshi.Errors.nestedSealedClassMissingPolymorphicLabel
import se.ansman.kotshi.Errors.nestedSealedClassMustBePolymorphic
data class SealedClassJsonAdapter(
override val targetPackageName: String,
override val targetSimpleNames: List,
override val targetTypeVariables: List,
val polymorphicLabels: Map,
val labelKey: String,
val onMissing: Polymorphic.Fallback,
val onInvalid: Polymorphic.Fallback,
val subtypes: List,
val defaultType: ClassName?,
) : GeneratableJsonAdapter() {
init {
if (defaultType != null) {
require(onMissing == Polymorphic.Fallback.DEFAULT || onInvalid == Polymorphic.Fallback.DEFAULT) {
"Using @JsonDefaultValue in combination with onMissing=$onMissing and onInvalid=$onInvalid makes no sense"
}
}
}
data class Subtype(
val type: TypeName,
val wildcardType: TypeName,
val superClass: TypeName,
val label: String
)
}
fun T.getSealedSubtypes(
getSealedSubclasses: T.() -> Sequence,
isSealed: T.() -> Boolean,
hasAnnotation: T.(Class) -> Boolean,
getPolymorphicLabelKey: T.() -> String?,
getPolymorphicLabel: T.() -> String?,
error: (String, T) -> Throwable,
labelKey: String = getPolymorphicLabelKey() ?: throw error(Errors.sealedClassMustBePolymorphic, this)
): Sequence = getSealedSubclasses().flatMap {
if (!it.hasAnnotation(JsonSerializable::class.java)) {
throw error(Errors.polymorphicSubclassMustHaveJsonSerializable, it)
}
when {
it.isSealed() -> {
val subclassLabelKey = it.getPolymorphicLabelKey()
?: throw error(nestedSealedClassMustBePolymorphic, it)
val subclassLabel = it.getPolymorphicLabel()
when {
subclassLabelKey == labelKey -> {
if (subclassLabel != null) {
throw error(nestedSealedClassHasPolymorphicLabel, it)
}
it.getSealedSubtypes(
getSealedSubclasses = getSealedSubclasses,
isSealed = isSealed,
hasAnnotation = hasAnnotation,
getPolymorphicLabelKey = getPolymorphicLabelKey,
getPolymorphicLabel = getPolymorphicLabel,
error = error,
labelKey = subclassLabelKey,
)
}
subclassLabel == null -> {
throw error(nestedSealedClassMissingPolymorphicLabel, it)
}
else -> sequenceOf(it)
}
}
!it.hasAnnotation(PolymorphicLabel::class.java) && !it.hasAnnotation(JsonDefaultValue::class.java) ->
throw error(Errors.polymorphicSubclassMustHavePolymorphicLabel, it)
else -> sequenceOf(it)
}
}