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

io.javalin.openapi.experimental.AnnotationProcessorContext.kt Maven / Gradle / Ivy

package io.javalin.openapi.experimental

import com.sun.source.util.Trees
import io.javalin.openapi.OpenApiName
import io.javalin.openapi.experimental.StructureType.DEFAULT
import io.javalin.openapi.experimental.processor.generators.TypeSchemaGenerator
import io.javalin.openapi.experimental.processor.shared.getTypeMirror
import io.javalin.openapi.experimental.processor.shared.getTypeMirrors
import javax.annotation.processing.Messager
import javax.annotation.processing.ProcessingEnvironment
import javax.annotation.processing.RoundEnvironment
import javax.lang.model.element.Element
import javax.lang.model.element.ExecutableElement
import javax.lang.model.element.TypeElement
import javax.lang.model.type.TypeMirror
import javax.lang.model.util.Types
import kotlin.reflect.KClass

class AnnotationProcessorContext(
    val parameters: OpenApiAnnotationProcessorParameters,
    val configuration: OpenApiAnnotationProcessorConfiguration,
    val env: ProcessingEnvironment,
    val trees: Trees?,
) {

    val types: Types = env.typeUtils
    val typeSchemaGenerator: TypeSchemaGenerator = TypeSchemaGenerator(this)
    var roundEnv: RoundEnvironment? = null

    fun  inContext(body: AnnotationProcessorContext.() -> R): R =
        body()

    fun inDebug(body: (Messager) -> Unit) {
        if (configuration.debug) {
            body(env.messager)
        }
    }

    fun getClassDefinition(mirror: TypeMirror, generics: List = emptyList(), type: StructureType = DEFAULT): ClassDefinition =
        ClassDefinition.classDefinitionFrom(this, mirror, generics, type)

    fun getClassDefinitions(mirrors: Set): Set =
        mirrors.map { getClassDefinition(it) }.toSet()

    fun forTypeElement(name: String): TypeElement? =
        env.elementUtils.getTypeElement(name)

    fun forTypeElement(mirror: TypeMirror): TypeElement =
        env.typeUtils.asElement(mirror) as TypeElement

    fun isAssignable(implementation: TypeMirror, superclass: TypeMirror): Boolean =
        env.typeUtils.isAssignable(implementation, superclass)

    fun hasElement(type: TypeElement, element: Element): Boolean =
        when (element) {
            is ExecutableElement -> env.elementUtils.getAllMembers(type).let { members ->
                members.contains(element) || members.filterIsInstance().any { env.elementUtils.overrides(element, it, type) }
            }
            else -> false
        }

    fun getFullName(mirror: TypeMirror): String =
        env.typeUtils.asElement(mirror)
            ?.getAnnotation(OpenApiName::class.java)
            ?.value
            ?.let { mirror.toString().substringBeforeLast(".") + "." + it }
            ?: env.typeUtils.asElement(mirror)?.toString()?.substringBefore("<")
            ?: mirror.toString().substringBefore("<")

    /* Extension methods, should be replaced by context receivers in the future */

    fun TypeMirror.toClassDefinition(
        generics: List = emptyList(),
        type: StructureType = DEFAULT
    ): ClassDefinition = getClassDefinition(this, generics, type)

    fun TypeMirror.getSimpleName(): String =
        getFullName().substringAfterLast(".")

    @JvmName("getFullNameExt")
    fun TypeMirror.getFullName(): String =
        getFullName(this)

    fun  A.getClassDefinitions(supplier: A.() -> Array>): Set =
        getTypeMirrors(supplier)
            .map { it.toClassDefinition() }
            .toSet()

    fun  A.getClassDefinition(supplier: A.() -> KClass<*>): ClassDefinition =
        getTypeMirror(supplier).toClassDefinition()

}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy