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

name.remal.gradle_plugins.dsl.BaseReflectiveProjectPlugin.kt Maven / Gradle / Ivy

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

import name.remal.findDeclaredConstructor
import name.remal.getMetaAnnotation
import name.remal.gradle_plugins.dsl.extensions.*
import name.remal.gradle_plugins.dsl.reflective_project_plugin.action_param_injector.invoke
import name.remal.gradle_plugins.dsl.reflective_project_plugin.info.*
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.util.GradleVersion
import java.lang.Deprecated as JavaDeprecated
import kotlin.Deprecated as KotlinDeprecated

abstract class BaseReflectiveProjectPlugin : BaseProjectPlugin() {

    final override fun applyImpl(project: Project) {
        val pluginInfo = PluginInfoCollector.collect(javaClass) ?: throw IllegalStateException("Plugin info can't be collected for $javaClass")

        if (project.isPluginDisabledByProperty(pluginInfo.id)) {
            logger.warn("{} plugin is disabled", pluginInfo.id)
            return
        }

        if (pluginInfo.doesNotSupportCurrentGradleVersion) {
            logger.warn("{}: Plugin {} doesn't support {}, as it requires {}", project, pluginInfo.id, GradleVersion.current(), pluginInfo.minGradleVersion)
            return
        }

        val deprecationMessage = javaClass.getMetaAnnotation(KotlinDeprecated::class.java)?.message ?: javaClass.getMetaAnnotation(JavaDeprecated::class.java)?.let { "" }
        if (deprecationMessage != null) {
            if (deprecationMessage.isNotEmpty()) {
                logger.warn("{}: Plugin {} is deprecated: {}", project, pluginInfo.id, deprecationMessage)
            } else {
                logger.warn("{}: Plugin {} is deprecated", project, pluginInfo.id)
            }
        }

        doActions(project, pluginInfo, this, pluginInfo)
    }

    @Suppress("ComplexMethod")
    private fun doActions(project: Project, pluginInfo: PluginInfo, actionsGroup: Any, actionsInfo: WithPluginActions) {
        if (actionsInfo.doesNotSupportCurrentGradleVersion) {
            logger.trace("{}: Plugin {}: {} doesn't support {}, as it requires {}", project, pluginInfo.id, actionsInfo, GradleVersion.current(), GradleVersionsRange(pluginInfo.minGradleVersion, pluginInfo.maxGradleVersion))
            return
        }

        for (conditionInfo in actionsInfo.conditionMethods) {
            if (!conditionInfo.invoke(actionsGroup, project)) {
                logger.trace("{}: Plugin {}: Skipping because of failed condition {}", pluginInfo.id, conditionInfo)
                return
            }
        }

        project.withPlugins(actionsInfo.requirePluginIds) {
            actionsInfo.applyPluginIds.filterNot(project::isPluginApplied).forEach { project.applyPlugin(it) }
            actionsInfo.applyPluginClasses.filterNot(project::isPluginApplied).forEach { project.applyPlugin(it) }
            actionsInfo.applyOptionalPluginIds.filterNot(project::isPluginApplied).forEach { project.tryApplyPlugin(it) }

            for (action in actionsInfo.actions) {
                if (action is ActionMethodInfo) {
                    if (action.doesNotSupportCurrentGradleVersion) {
                        logger.trace("{}: Plugin {}: {} doesn't support {}, as it requires {}", project, pluginInfo.id, action, GradleVersion.current(), GradleVersionsRange(action.minGradleVersion, action.maxGradleVersion))
                        return@withPlugins
                    }

                    project.withPlugins(action.requirePluginIds) {
                        try {
                            action.applyPluginIds.filterNot(project::isPluginApplied).forEach { project.applyPlugin(it) }
                            action.applyPluginClasses.filterNot(project::isPluginApplied).forEach { project.applyPlugin(it) }
                            action.applyOptionalPluginIds.filterNot(project::isPluginApplied).forEach { project.tryApplyPlugin(it) }

                            if (action.isAfterProjectEvaluation) {
                                project.afterEvaluateOrNow {
                                    logger.trace("{}: Plugin {}: Executing plugin action: {}", project, pluginInfo.id, action)
                                    action.invoke(actionsGroup, it)
                                }
                            } else {
                                logger.trace("{}: Plugin {}: Executing plugin action: {}", project, pluginInfo.id, action)
                                action.invoke(actionsGroup, project)
                            }

                            action.applyPluginIdsAtTheEnd.filterNot(project::isPluginApplied).forEach { project.applyPlugin(it) }
                            action.applyPluginClassesAtTheEnd.filterNot(project::isPluginApplied).forEach { project.applyPlugin(it) }
                            action.applyOptionalPluginIdsAtTheEnd.filterNot(project::isPluginApplied).forEach { project.tryApplyPlugin(it) }

                        } catch (e: Exception) {
                            throw GradleException("$project: Error applying plugin ${[email protected]().name}: $e", e)
                        }
                    }

                } else if (action is ActionsGroupInfo) {
                    val innerActionsGroup = action.actionsGroupClass.let {
                        it.findDeclaredConstructor(actionsGroup.javaClass)?.newInstance(actionsGroup)
                            ?: it.getDeclaredConstructor().newInstance()
                    }
                    doActions(project, pluginInfo, innerActionsGroup, action)

                } else {
                    throw UnsupportedOperationException("Unsupported action type: ${action.javaClass}")
                }
            }

            actionsInfo.applyPluginIdsAtTheEnd.filterNot(project::isPluginApplied).forEach { project.applyPlugin(it) }
            actionsInfo.applyPluginClassesAtTheEnd.filterNot(project::isPluginApplied).forEach { project.applyPlugin(it) }
            actionsInfo.applyOptionalPluginIdsAtTheEnd.filterNot(project::isPluginApplied).forEach { project.tryApplyPlugin(it) }
        }
    }


    private class GradleVersionsRange(val min: GradleVersion?, val max: GradleVersion?) {
        override fun toString(): String {
            if (min != null && max != null) {
                return "Gradle ${min.version} .. ${max.version}"
            } else if (min != null) {
                return "Gradle at least ${min.version}"
            } else if (max != null) {
                return "Gradle at most ${max.version}"
            } else {
                throw IllegalStateException("Min and max can't be both null")
            }
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy