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

name.remal.gradle_plugins.dsl.extensions.org.gradle.api.plugins.ExtensionAware.kt Maven / Gradle / Ivy

There is a newer version: 1.9.2
Show newest version
package name.remal.gradle_plugins.dsl.extensions

import name.remal.gradle_plugins.dsl.reflective_project_plugin.action_param_injector.ActionParamInjector
import name.remal.gradle_plugins.dsl.reflective_project_plugin.action_param_injector.actionParamInjectors
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.plugins.ExtensionAware
import java.lang.reflect.Constructor
import javax.inject.Inject

operator fun  ExtensionAware.invoke(name: String, configurer: (T) -> Unit) = extensions(name, configurer)
operator fun  ExtensionAware.invoke(type: Class, configurer: (T) -> Unit) = extensions(type, configurer)
operator fun  ExtensionAware.get(name: String): T = extensions[name]
operator fun  ExtensionAware.get(type: Class) = extensions[type]
fun  ExtensionAware.getOrNull(name: String) = extensions.getOrNull(name)
fun  ExtensionAware.getOrNull(type: Class) = extensions.getOrNull(type)
operator fun ExtensionAware.contains(name: String) = extensions.contains(name)
operator fun ExtensionAware.contains(type: Class<*>) = extensions.contains(type)


fun  ExtensionAware.createExtensionWithInjectedParams(name: String, publicType: Class, instanceType: Class): T = when (this) {
    is Project -> createExtensionWithInjectedParams(this, name, publicType, instanceType)
    is Task -> createExtensionWithInjectedParams(project, name, publicType, instanceType)
    else -> throw UnsupportedOperationException("Unsupported type: $javaClass")
}

fun  ExtensionAware.createExtensionWithInjectedParams(name: String, publicType: Class) = createExtensionWithInjectedParams(name, publicType, publicType)
fun  ExtensionAware.createExtensionWithInjectedParams(publicType: Class, instanceType: Class) = createExtensionWithInjectedParams(publicType.extensionName, publicType, instanceType)
fun  ExtensionAware.createExtensionWithInjectedParams(publicType: Class) = createExtensionWithInjectedParams(publicType.extensionName, publicType, publicType)

private fun  ExtensionAware.createExtensionWithInjectedParams(project: Project, name: String, publicType: Class, instanceType: Class): T {
    val ctor: Constructor<*> = run {
        val constructors = instanceType.declaredConstructors
        val injectConstructors = constructors.filter { it.isAnnotationPresent(Inject::class.java) }
        if (injectConstructors.size == 1) {
            return@run injectConstructors.single()
        } else if (injectConstructors.size >= 2) {
            throw IllegalStateException("Class ${instanceType.name} has multiple constructors that are annotated with @Inject")
        }
        val noargCtor = constructors.firstOrNull { it.parameterCount == 0 }
        if (noargCtor != null) {
            return@run noargCtor
        }
        throw IllegalStateException("Class ${instanceType.name} has no constructor that is annotated with @Inject and no no-arg constructor")
    }

    val ctorParams = ctor.parameterTypes.map { type ->
        val injector = actionParamInjectors.firstOrNull { type.isAssignableFrom(it.paramType) }
            ?: throw IllegalStateException("${ActionParamInjector::class.java.simpleName} can't be found for $type")
        return@map injector.createValue(project)
    }

    return extensions.create(publicType, name, instanceType, *ctorParams.toTypedArray())
}


private val Class<*>.extensionName: String get() = "$$" + name.replace('.', '$')




© 2015 - 2024 Weber Informatics LLC | Privacy Policy