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

se.ansman.deager.renderers.EagerObjectModuleJavaRenderer.kt Maven / Gradle / Ivy

The newest version!
package se.ansman.deager.renderers

import com.squareup.javapoet.AnnotationSpec
import com.squareup.javapoet.ClassName
import com.squareup.javapoet.CodeBlock
import com.squareup.javapoet.JavaFile
import com.squareup.javapoet.MethodSpec
import com.squareup.javapoet.ParameterSpec
import com.squareup.javapoet.ParameterizedTypeName
import com.squareup.javapoet.TypeName
import com.squareup.javapoet.TypeSpec
import dagger.Binds
import dagger.Lazy
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.codegen.OriginatingElement
import dagger.hilt.components.SingletonComponent
import dagger.multibindings.IntoSet
import se.ansman.deager.Initializable
import se.ansman.deager.asClassName
import se.ansman.deager.models.EagerObject
import javax.lang.model.element.Modifier

typealias JavaEagerObject = EagerObject

class EagerObjectModuleJavaRenderer private constructor(
    private val moduleName: ClassName,
    private val originatingElement: ClassName,
    private val eagerObjects: List
) {
    constructor(module: ClassName, eagerObjects: Iterable) : this(
        moduleName = module.peerClass(module.simpleNames().joinToString(separator = "", prefix = "Eager")),
        originatingElement = module.topLevelClassName(),
        eagerObjects = eagerObjects.toList()
    )

    constructor(eagerObject: JavaEagerObject) : this(
        moduleName = eagerObject.moduleName(),
        originatingElement = eagerObject.targetType.asClassName().topLevelClassName(),
        eagerObjects = listOf(eagerObject)
    )

    fun render(modifier: TypeSpec.Builder.() -> Unit = {}): JavaFile {
        val typeSpec = TypeSpec.classBuilder(moduleName)
            .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
            .addMethod(
                MethodSpec.constructorBuilder()
                    .addModifiers(Modifier.PRIVATE)
                    .build()
            )
            .addAnnotation(Module::class.java)
            .addAnnotation(
                AnnotationSpec.builder(InstallIn::class.java)
                    .addMember("value", "\$T.class", SingletonComponent::class.java)
                    .build()
            )
            .addAnnotation(
                AnnotationSpec.builder(OriginatingElement::class.java)
                    .addMember("topLevelClass", "\$T.class", originatingElement)
                    .build()
            )

        for (eagerObject in eagerObjects) {
            val qualifiers = eagerObject.qualifiers.map { it.toAnnotationSpec() }
            val methodSpec = MethodSpec.methodBuilder(eagerObject.method.name)
            val parameterName = eagerObject.targetType
                .asClassName()
                .simpleName()
                .replaceFirstChar(Char::lowercaseChar)
            when (eagerObject.method) {
                is EagerObject.Method.Binding -> {
                    methodSpec
                        .addModifiers(Modifier.ABSTRACT)
                        .addAnnotation(Binds::class.java)
                        .addParameter(
                            ParameterSpec
                                .builder(eagerObject.targetType, parameterName)
                                .addAnnotations(qualifiers)
                                .build()
                        )
                }
                is EagerObject.Method.Provider -> {
                    val parameter = ParameterSpec
                        .builder(
                            ParameterizedTypeName.get(ClassName.get(Lazy::class.java), eagerObject.targetType),
                            parameterName
                        )
                        .addAnnotations(qualifiers)
                        .build()
                    methodSpec
                        .addModifiers(Modifier.STATIC)
                        .addAnnotation(Provides::class.java)
                        .addParameter(parameter)
                        .addStatement(
                            "return \$T.fromLazy(\$N\$L)",
                            Initializable::class.java,
                            parameter,
                            if (eagerObject.priority == null) {
                                CodeBlock.of("")
                            } else {
                                CodeBlock.of(", /* priority */ \$L", eagerObject.priority)
                            }
                        )
                }
            }
            typeSpec.addMethod(
                methodSpec
                    .addModifiers(Modifier.PUBLIC)
                    .addAnnotation(IntoSet::class.java)
                    .returns(Initializable::class.java)
                    .build()
            )
        }

        return JavaFile.builder(moduleName.packageName(), typeSpec.apply(modifier).build())
            .addFileComment("Code generated by Deager. Do not edit.")
            .build()
    }
}

private fun JavaEagerObject.moduleName(): ClassName =
    ClassName.get(
        targetType.asClassName().packageName(),
        targetType.asClassName().simpleNames().joinToString(prefix = "Eager", postfix = "Module", separator = "")
    )




© 2015 - 2024 Weber Informatics LLC | Privacy Policy