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

jvmMain.ch.softappeal.yass2.generate.InterceptorGenerate.kt Maven / Gradle / Ivy

There is a newer version: 5.0.0
Show newest version
package ch.softappeal.yass2.generate

import ch.softappeal.yass2.*
import kotlin.reflect.*
import kotlin.reflect.full.*

internal fun KFunction<*>.hasResult() = returnType.classifier != Unit::class

internal fun KType.needsCast() = classifier != Any::class || !isMarkedNullable

internal fun StringBuilder.functionSignature(index: Int, function: KCallable<*>) = with(function) {
    if (index != 0) append('\n')
    append("            override suspend fun $name(")
    valueParameters.forEach { parameter ->
        if (parameter.index != 1) append(", ")
        append("p${parameter.index}: ${parameter.type}")
    }
    append(")")
}

fun generateProxyFactory(services: List>, proxyFactoryName: String = "GeneratedProxyFactory"): String {
    require(services.toSet().size == services.size) { "duplicated services" }
    return with(StringBuilder(10_000)) {
        fun out(s: String, level: Int = 0) = append(s.replaceIndent("    ".repeat(level))).append('\n')
        out("""
            @Suppress("UNCHECKED_CAST", "PARAMETER_NAME_CHANGED_ON_OVERRIDE", "RemoveRedundantQualifierName", "SpellCheckingInspection")
            object $proxyFactoryName : ${ProxyFactory::class.qualifiedName} {
                override fun  create(
                    service: ${KClass::class.qualifiedName}, implementation: S, interceptor: ch.softappeal.yass2.Interceptor
                ): S = when (service) {
        """)
        services.forEach { service ->
            service.checkService()
            out("""
                ${service.qualifiedName}::class -> object : ${service.qualifiedName} {
            """, 2)
            service.serviceFunctions().withIndex().forEach { (index, function) ->
                with(function) {
                    fun KFunction<*>.pList() = valueParameters.forEach { parameter ->
                        if (parameter.index != 1) append(", ")
                        append("p${parameter.index}")
                    }
                    functionSignature(index, this)
                    if (hasResult()) append(": $returnType")
                    append(" {\n                ${if (hasResult()) "return " else ""}interceptor(\"$name\", ")
                    if (valueParameters.isEmpty()) append("emptyArray(") else {
                        append("arrayOf(")
                        pList()
                    }
                    append(")) { (implementation as ${service.qualifiedName}).$name(")
                    pList()
                    append(") }")
                    if (hasResult() && returnType.needsCast()) append(" as $returnType")
                    append("\n            }\n")
                }
            }
            out("""
                } as S
            """, 2)
        }
        out("""
                    else -> error("no proxy for '${'$'}service'")
                }
            }
        """)
    }.toString()
}