name.remal.gradle_plugins.dsl.extensions.org.gradle.api.plugins.ExtensionAware.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle-plugins-kotlin-dsl Show documentation
Show all versions of gradle-plugins-kotlin-dsl Show documentation
Remal Gradle plugins: gradle-plugins-kotlin-dsl
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('.', '$')