All Downloads are FREE. Search and download functionalities are using the official Maven repository.

se.ansman.kotshi.AdapterKey.kt Maven / Gradle / Ivy

Go to download

An annotations processor that generates Moshi adapters from Kotlin data classes

There is a newer version: 3.0.0
Show newest version
package se.ansman.kotshi

import com.squareup.kotlinpoet.ANY
import com.squareup.kotlinpoet.ARRAY
import com.squareup.kotlinpoet.AnnotationSpec
import com.squareup.kotlinpoet.ClassName
import com.squareup.kotlinpoet.CodeBlock
import com.squareup.kotlinpoet.Dynamic
import com.squareup.kotlinpoet.LambdaTypeName
import com.squareup.kotlinpoet.ParameterizedTypeName
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
import com.squareup.kotlinpoet.TypeName
import com.squareup.kotlinpoet.TypeVariableName
import com.squareup.kotlinpoet.WildcardTypeName
import com.squareup.kotlinpoet.asClassName
import com.squareup.moshi.Types

data class AdapterKey(
    val type: TypeName,
    val jsonQualifiers: Set
)

fun AdapterKey.asRuntimeType(typeVariableAccessor: (TypeVariableName) -> CodeBlock): CodeBlock =
    type.asRuntimeType(typeVariableAccessor)

val AdapterKey.suggestedAdapterName: String
    get() = "${jsonQualifiers.joinToString("") { it.className.simpleName }}${type.baseAdapterName}Adapter".decapitalize()

private val TypeName.baseAdapterName: String
    get() {
        return when (this) {
            is ClassName -> simpleNames.joinToString("")
            Dynamic -> "dynamic"
            is LambdaTypeName -> "lambda"
            is ParameterizedTypeName ->
                typeArguments.joinToString("") { it.baseAdapterName } + rawType.baseAdapterName
            is TypeVariableName -> name
            is WildcardTypeName -> "wildcard"
        }
    }

private fun TypeName.asRuntimeType(typeVariableAccessor: (TypeVariableName) -> CodeBlock): CodeBlock =
    when (this) {
        is ParameterizedTypeName ->
            CodeBlock.builder()
                .add("%T.newParameterizedType(%T::class.javaObjectType", moshiTypes, if (rawType == ARRAY) {
                    // Arrays are special, you cannot just do Array::class.java
                    this
                } else {
                    rawType.notNull()
                })
                .apply {
                    for (typeArgument in typeArguments) {
                        add(", ")
                        add(typeArgument.asRuntimeType(typeVariableAccessor))
                    }
                }
                .add(")")
                .build()
        is WildcardTypeName -> when {
            inTypes.size == 1 -> inTypes[0].asRuntimeType(typeVariableAccessor)
            outTypes[0] == ANY -> ANY.asRuntimeType(typeVariableAccessor)
            else -> outTypes[0].asRuntimeType(typeVariableAccessor)
        }
        is LambdaTypeName -> asParameterizedTypeName().asRuntimeType(typeVariableAccessor)
        is TypeVariableName -> typeVariableAccessor(this)
        else -> CodeBlock.of("%T::class.javaObjectType", notNull())
    }

val moshiTypes = Types::class.java.asClassName()

private fun LambdaTypeName.asParameterizedTypeName(): ParameterizedTypeName {
    val parameters = mutableListOf()
    receiver?.let(parameters::add)
    parameters.addAll(parameters)
    parameters.add(returnType)
    return ClassName("kotlin", "Function${parameters.size + (if (receiver == null) 0 else 1)}")
        .parameterizedBy(parameters)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy