se.ansman.kotshi.model.AnnotationModel.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.*
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
import se.ansman.kotshi.*
data class AnnotationModel(
val annotationName: ClassName,
val hasMethods: Boolean,
val values: Map>
) {
sealed class Value {
abstract val value: T
sealed class Single : Value()
sealed class Primitive : Single()
sealed class Object : Single()
data class Class(override val value: ClassName) : Object()
data class Annotation(override val value: AnnotationModel) : Object()
data class Enum(val enumType: ClassName, override val value: kotlin.String) : Object()
data class String(override val value: kotlin.String) : Object()
data class Float(override val value: kotlin.Float) : Primitive()
data class Char(override val value: kotlin.Char) : Primitive()
data class Boolean(override val value: kotlin.Boolean) : Primitive()
data class Double(override val value: kotlin.Double) : Primitive()
data class Byte(override val value: kotlin.Byte) : Primitive()
data class UByte(override val value: kotlin.UByte) : Primitive()
data class Short(override val value: kotlin.Short) : Primitive()
data class UShort(override val value: kotlin.UShort) : Primitive()
data class Int(override val value: kotlin.Int) : Primitive()
data class UInt(override val value: kotlin.UInt) : Primitive()
data class Long(override val value: kotlin.Long) : Primitive()
data class ULong(override val value: kotlin.ULong) : Primitive()
sealed class Array> : Value>() {
data class Object(val elementType: TypeName, override val value: List>) : Array>()
data class Float(override val value: List) : Array()
data class Char(override val value: List) : Array()
data class Boolean(override val value: List) : Array()
data class Double(override val value: List) : Array()
data class Byte(override val value: List) : Array()
data class UByte(override val value: List) : Array()
data class Short(override val value: List) : Array()
data class UShort(override val value: List) : Array()
data class Int(override val value: List) : Array()
data class UInt(override val value: List) : Array()
data class Long(override val value: List) : Array()
data class ULong(override val value: List) : Array()
}
}
}
fun AnnotationModel.render(createAnnotationsUsingConstructor: Boolean): CodeBlock =
if (createAnnotationsUsingConstructor) {
CodeBlock.builder()
.add("%T(", annotationName)
.indent()
.applyEach(values.entries) { (name, value) ->
add("\n%N·=·%L,", name, value.render(true))
}
.unindent()
.applyIf(values.isNotEmpty()) { add("\n") }
.add(")")
.build()
} else if (values.isEmpty()) {
CodeBlock.of("%T::class.java.%M()", annotationName, Functions.Kotshi.createJsonQualifierImplementation)
} else {
CodeBlock.builder()
.add("%T::class.java.%M(mapOf(", annotationName, Functions.Kotshi.createJsonQualifierImplementation)
.withIndent {
values.entries.forEachIndexed { i, (name, value) ->
if (i > 0) {
add(",")
}
add("\n%S·to·%L", name, value.render(false))
}
}
.add("\n))")
.build()
}
private fun AnnotationModel.Value<*>.render(createAnnotationsUsingConstructor: Boolean): CodeBlock =
when (this) {
is AnnotationModel.Value.Boolean ->
CodeBlock.of("%L", value)
is AnnotationModel.Value.Byte ->
CodeBlock.of("(%L).toByte()", value)
is AnnotationModel.Value.UByte ->
if (createAnnotationsUsingConstructor) CodeBlock.of("%LU", value) else CodeBlock.of("(%LU).toByte()", value)
is AnnotationModel.Value.Char ->
CodeBlock.of("'%L'", if (value == '\'') "\\'" else value)
is AnnotationModel.Value.Class ->
if (createAnnotationsUsingConstructor) CodeBlock.of("%T::class", value) else CodeBlock.of("%T::class.java", value)
is AnnotationModel.Value.Annotation ->
value.render(createAnnotationsUsingConstructor)
is AnnotationModel.Value.Double -> {
var s = value.toString()
if ('.' !in s) s += ".0"
CodeBlock.of("%L", s)
}
is AnnotationModel.Value.Enum ->
CodeBlock.of("%T.%L", enumType, value)
is AnnotationModel.Value.Float ->
CodeBlock.of("%Lf", value)
is AnnotationModel.Value.Int ->
CodeBlock.of("%L", value)
is AnnotationModel.Value.UInt ->
if (createAnnotationsUsingConstructor) CodeBlock.of("%LU", value) else CodeBlock.of("(%LU).toInt()", value)
is AnnotationModel.Value.Long -> {
if (value == Long.MIN_VALUE) {
CodeBlock.of("%T.MIN_VALUE", LONG)
} else {
CodeBlock.of("%LL", value)
}
}
is AnnotationModel.Value.ULong ->
if (createAnnotationsUsingConstructor) CodeBlock.of("%LUL", value) else CodeBlock.of("(%LUL).toLong()", value)
is AnnotationModel.Value.Short ->
CodeBlock.of("(%L).toShort()", value)
is AnnotationModel.Value.UShort ->
if (createAnnotationsUsingConstructor) CodeBlock.of("%LU", value) else CodeBlock.of("(%LU).toShort()", value)
is AnnotationModel.Value.String ->
CodeBlock.of("%S", value)
is AnnotationModel.Value.Array<*> -> {
CodeBlock.builder()
.add(
when (this) {
is AnnotationModel.Value.Array.Boolean ->
CodeBlock.of("%M", Functions.Kotlin.booleanArrayOf)
is AnnotationModel.Value.Array.Char ->
CodeBlock.of("%M", Functions.Kotlin.charArrayOf)
is AnnotationModel.Value.Array.Double ->
CodeBlock.of("%M", Functions.Kotlin.doubleArrayOf)
is AnnotationModel.Value.Array.Float ->
CodeBlock.of("%M", Functions.Kotlin.floatArrayOf)
is AnnotationModel.Value.Array.Byte ->
CodeBlock.of("%M", Functions.Kotlin.byteArrayOf)
is AnnotationModel.Value.Array.UByte ->
if (createAnnotationsUsingConstructor) {
CodeBlock.of("%M", Functions.Kotlin.ubyteArrayOf)
} else {
CodeBlock.of("%M", Functions.Kotlin.byteArrayOf)
}
is AnnotationModel.Value.Array.Short ->
CodeBlock.of("%M", Functions.Kotlin.shortArrayOf)
is AnnotationModel.Value.Array.UShort ->
if (createAnnotationsUsingConstructor) {
CodeBlock.of("%M", Functions.Kotlin.ushortArrayOf)
} else {
CodeBlock.of("%M", Functions.Kotlin.shortArrayOf)
}
is AnnotationModel.Value.Array.Int ->
CodeBlock.of("%M", Functions.Kotlin.intArrayOf)
is AnnotationModel.Value.Array.UInt ->
if (createAnnotationsUsingConstructor) {
CodeBlock.of("%M", Functions.Kotlin.uintArrayOf)
} else {
CodeBlock.of("%M", Functions.Kotlin.intArrayOf)
}
is AnnotationModel.Value.Array.Long ->
CodeBlock.of("%M", Functions.Kotlin.longArrayOf)
is AnnotationModel.Value.Array.ULong ->
if (createAnnotationsUsingConstructor) {
CodeBlock.of("%M", Functions.Kotlin.ulongArrayOf)
} else {
CodeBlock.of("%M", Functions.Kotlin.longArrayOf)
}
is AnnotationModel.Value.Array.Object ->
if (createAnnotationsUsingConstructor) {
CodeBlock.of("%M", Functions.Kotlin.arrayOf)
} else {
val elementType = elementType.withoutVariance()
CodeBlock.of(
"%M<%T>",
Functions.Kotlin.arrayOf,
if (elementType is ParameterizedTypeName && elementType.rawType == Types.Kotlin.kClass) {
Types.Java.clazz.parameterizedBy(elementType.typeArguments.single())
} else {
elementType
}
)
}
}
)
.add("(")
.applyEachIndexed(value) { i, v ->
if (i > 0) {
add(", ")
}
add(v.render(createAnnotationsUsingConstructor))
}
.add(")")
.build()
}
}