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

name.remal.gradle_plugins.dsl.reflective_project_plugin.info.PluginInfoCollector.kt Maven / Gradle / Ivy

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

import name.remal.*
import name.remal.gradle_plugins.dsl.*
import name.remal.gradle_plugins.dsl.extensions.getOrInstantiate
import name.remal.gradle_plugins.dsl.utils.findPluginId
import name.remal.gradle_plugins.dsl.utils.getGradleLogger
import org.gradle.util.GradleVersion
import java.lang.reflect.AnnotatedElement
import java.lang.reflect.Method
import kotlin.reflect.full.memberProperties

object PluginInfoCollector {

    private val logger = getGradleLogger(PluginInfoCollector::class.java)

    @JvmStatic
    fun collect(pluginClass: ProjectPluginClass): PluginInfo? {
        val pluginAnnotation = pluginClass.getMetaAnnotation(Plugin::class.java) ?: return null
        return PluginInfo(
            pluginClass = pluginClass,
            id = pluginAnnotation.id,
            isHidden = pluginAnnotation.isHidden,
            description = pluginAnnotation.description,
            tags = pluginAnnotation.tags.toSet(),
            conditionMethods = collectConditionMethods(pluginClass),
            minGradleVersion = collectMinGradleVersion(pluginClass),
            maxGradleVersion = collectMaxGradleVersion(pluginClass),
            requirePluginIds = collectRequirePluginIds(pluginClass),
            applyPluginIds = collectApplyPluginIds(pluginClass),
            applyOptionalPluginIds = collectApplyOptionalPluginIds(pluginClass),
            applyPluginClasses = collectApplyPluginClasses(pluginClass),
            applyPluginIdsAtTheEnd = collectApplyPluginIdsAtTheEnd(pluginClass),
            applyOptionalPluginIdsAtTheEnd = collectApplyOptionalPluginIdsAtTheEnd(pluginClass),
            applyPluginClassesAtTheEnd = collectApplyPluginClassesAtTheEnd(pluginClass),
            actionMethods = collectActions(pluginClass),
            actionsGroups = collectActionsGroups(pluginClass)
        );
    }

    private fun collectConditionMethods(pluginClass: Class<*>): List {
        return buildList {
            pluginClass.allNotOverriddenMethods.forEach { method ->
                val conditionAnnotation = method.getMetaAnnotation(PluginCondition::class.java) ?: return@forEach
                if (Boolean::class.javaPrimitiveType != method.returnType) return@forEach logger.warn("{} can't be plugin condition method - it doesn't return boolean")
                add(ConditionMethodInfo(
                    method = method,
                    isHidden = conditionAnnotation.isHidden,
                    order = conditionAnnotation.order,
                    description = if (conditionAnnotation.value.isNotEmpty()) conditionAnnotation.value else method.name
                ))
            }
        }.sorted()
    }

    private fun collectMinGradleVersion(annotatedElement: AnnotatedElement): GradleVersion? {
        return annotatedElement.getMetaAnnotation(MinGradleVersion::class.java)?.value?.native
    }

    private fun collectMaxGradleVersion(annotatedElement: AnnotatedElement): GradleVersion? {
        return annotatedElement.getMetaAnnotation(MaxGradleVersion::class.java)?.value?.native
    }

    private fun collectRequirePluginIds(annotatedElement: AnnotatedElement): Set {
        return buildSet {
            annotatedElement.getMetaAnnotations(WithPlugins::class.java).forEach {
                it.value.forEach { add(it.getOrInstantiate()) }
            }

            annotatedElement.getMetaAnnotations(WithPluginClasses::class.java).forEach {
                it.value.forEach {
                    val id = findPluginId(it.java)
                        ?: throw IllegalStateException("Plugin ID can't be find for %s".format(it.java))
                    add(PluginId(id))
                }
            }
        }
    }

    private fun collectApplyPluginIds(annotatedElement: AnnotatedElement): Set {
        return buildSet {
            annotatedElement.getMetaAnnotations(ApplyPlugins::class.java).forEach {
                it.value.forEach { add(it.getOrInstantiate()) }
            }
        }
    }

    private fun collectApplyOptionalPluginIds(annotatedElement: AnnotatedElement): Set {
        return buildSet {
            annotatedElement.getMetaAnnotations(ApplyOptionalPlugins::class.java).forEach {
                it.value.forEach { add(it.getOrInstantiate()) }
            }
        }
    }

    private fun collectApplyPluginClasses(annotatedElement: AnnotatedElement): Set {
        return buildSet {
            annotatedElement.getMetaAnnotations(ApplyPluginClasses::class.java).forEach {
                it.value.forEach { add(it.java) }
            }
        }
    }

    private fun collectApplyPluginIdsAtTheEnd(annotatedElement: AnnotatedElement): Set {
        return buildSet {
            annotatedElement.getMetaAnnotations(ApplyPluginsAtTheEnd::class.java).forEach {
                it.value.forEach { add(it.getOrInstantiate()) }
            }
        }
    }

    private fun collectApplyOptionalPluginIdsAtTheEnd(annotatedElement: AnnotatedElement): Set {
        return buildSet {
            annotatedElement.getMetaAnnotations(ApplyOptionalPluginsAtTheEnd::class.java).forEach {
                it.value.forEach { add(it.getOrInstantiate()) }
            }
        }
    }

    private fun collectApplyPluginClassesAtTheEnd(annotatedElement: AnnotatedElement): Set {
        return buildSet {
            annotatedElement.getMetaAnnotations(ApplyPluginClassesAtTheEnd::class.java).forEach {
                it.value.forEach { add(it.java) }
            }
        }
    }

    private fun collectCreateExtensionInfo(method: Method): CreateExtensionInfo? {
        val returnType = method.returnType
        if (returnType.isPrimitive) return null
        val extensionAnnotation = returnType.getMetaAnnotation(Extension::class.java) ?: return null
        return CreateExtensionInfo(
            extensionClass = returnType,
            description = if (extensionAnnotation.value.isNotEmpty()) extensionAnnotation.value else returnType.simpleName,
            properties = returnType.kotlin.memberProperties
                .map {
                    val propertyAnnotation = it.getMetaAnnotation(ExtensionProperty::class.java) ?: return@map null
                    return@map ExtensionPropertyInfo(
                        name = it.name,
                        description = propertyAnnotation.value
                    )
                }
                .filterNotNull()
                .sortedBy(ExtensionPropertyInfo::name)
        )
    }

    private fun collectActions(contextClass: Class<*>): List {
        return buildList {
            contextClass.allNotOverriddenMethods.forEach { method ->
                val actionAnnotation = method.getMetaAnnotation(PluginAction::class.java) ?: return@forEach
                add(ActionMethodInfo(
                    method = method,
                    isHidden = actionAnnotation.isHidden,
                    order = actionAnnotation.order,
                    description = if (actionAnnotation.value.isNotEmpty()) actionAnnotation.value else method.name,
                    minGradleVersion = collectMinGradleVersion(method),
                    maxGradleVersion = collectMaxGradleVersion(method),
                    requirePluginIds = collectRequirePluginIds(method),
                    applyPluginIds = collectApplyPluginIds(method),
                    applyOptionalPluginIds = collectApplyOptionalPluginIds(method),
                    applyPluginClasses = collectApplyPluginClasses(method),
                    applyPluginIdsAtTheEnd = collectApplyPluginIdsAtTheEnd(method),
                    applyOptionalPluginIdsAtTheEnd = collectApplyOptionalPluginIdsAtTheEnd(method),
                    applyPluginClassesAtTheEnd = collectApplyPluginClassesAtTheEnd(method),
                    createExtensionInfo = collectCreateExtensionInfo(method),
                    isAfterProjectEvaluation = method.hasMetaAnnotation(AfterProjectEvaluation::class.java)
                ))
            }
        }.sorted()
    }

    private fun collectActionsGroups(contextClass: Class<*>): List {
        return buildList {
            contextClass.declaredClasses.forEach { innerClass ->
                val groupAnnotation = innerClass.getMetaAnnotation(PluginActionsGroup::class.java) ?: return@forEach
                add(ActionsGroupInfo(
                    actionsGroupClass = innerClass,
                    isHidden = groupAnnotation.isHidden,
                    order = groupAnnotation.order,
                    description = if (groupAnnotation.value.isNotEmpty()) groupAnnotation.value else innerClass.simpleName,
                    conditionMethods = collectConditionMethods(innerClass),
                    minGradleVersion = collectMinGradleVersion(innerClass),
                    maxGradleVersion = collectMaxGradleVersion(innerClass),
                    requirePluginIds = collectRequirePluginIds(innerClass),
                    applyPluginIds = collectApplyPluginIds(innerClass),
                    applyOptionalPluginIds = collectApplyOptionalPluginIds(innerClass),
                    applyPluginClasses = collectApplyPluginClasses(innerClass),
                    applyPluginIdsAtTheEnd = collectApplyPluginIdsAtTheEnd(innerClass),
                    applyOptionalPluginIdsAtTheEnd = collectApplyOptionalPluginIdsAtTheEnd(innerClass),
                    applyPluginClassesAtTheEnd = collectApplyPluginClassesAtTheEnd(innerClass),
                    actionMethods = collectActions(innerClass),
                    actionsGroups = collectActionsGroups(innerClass)
                ))
            }
        }.sorted()
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy