From 6656c3f503aaaae03acee2e0c729ed9ef468bfa2 Mon Sep 17 00:00:00 2001 From: Cedric Beust Date: Fri, 4 Dec 2015 17:23:36 -0800 Subject: [PATCH] First pass at introducing ITaskContributor. --- .../kotlin/com/beust/kobalt/BasePluginTask.kt | 2 - src/main/kotlin/com/beust/kobalt/Main.kt | 18 ++-- src/main/kotlin/com/beust/kobalt/Plugins.kt | 33 ++----- .../kotlin/com/beust/kobalt/api/BasePlugin.kt | 5 +- .../kotlin/com/beust/kobalt/api/IPlugin.kt | 33 ------- .../kotlin/com/beust/kobalt/api/Project.kt | 8 +- .../com/beust/kobalt/internal/TaskManager.kt | 88 ++++++++++++++++++- .../kobalt/internal/build/BuildScriptUtil.kt | 9 +- 8 files changed, 109 insertions(+), 87 deletions(-) diff --git a/src/main/kotlin/com/beust/kobalt/BasePluginTask.kt b/src/main/kotlin/com/beust/kobalt/BasePluginTask.kt index e54d73f5..855d4271 100644 --- a/src/main/kotlin/com/beust/kobalt/BasePluginTask.kt +++ b/src/main/kotlin/com/beust/kobalt/BasePluginTask.kt @@ -3,8 +3,6 @@ package com.beust.kobalt import com.beust.kobalt.api.IPlugin import com.beust.kobalt.api.PluginTask import com.beust.kobalt.api.Project -import com.beust.kobalt.TaskResult -import com.beust.kobalt.internal.TaskResult2 public abstract class BasePluginTask(override val plugin: IPlugin, override val name: String, diff --git a/src/main/kotlin/com/beust/kobalt/Main.kt b/src/main/kotlin/com/beust/kobalt/Main.kt index a446cc99..691029b7 100644 --- a/src/main/kotlin/com/beust/kobalt/Main.kt +++ b/src/main/kotlin/com/beust/kobalt/Main.kt @@ -178,18 +178,14 @@ private class Main @Inject constructor( // List of tasks // val sb = StringBuffer("List of tasks\n") - Plugins.plugins.forEach { plugin -> - if (plugin.tasks.size > 0) { - sb.append("\n " + AsciiArt.horizontalDoubleLine +" ${plugin.name} " - + AsciiArt.horizontalDoubleLine + "\n") - plugin.tasks.distinctBy { - it.name - }.forEach { task -> - sb.append(" ${task.name}\t\t${task.doc}\n") - } - } + taskManager.tasks.distinctBy { + it.name + }.forEach { task -> + sb.append("\n " + AsciiArt.horizontalDoubleLine +" ${task.plugin.name} " + + AsciiArt.horizontalDoubleLine + "\n") + sb.append(" ${task.name}\t\t${task.doc}\n") + println(sb.toString()) } - println(sb.toString()) } else if (args.checkVersions) { checkVersions.run(allProjects) } else if (args.download) { diff --git a/src/main/kotlin/com/beust/kobalt/Plugins.kt b/src/main/kotlin/com/beust/kobalt/Plugins.kt index 22c6689b..31a2d32e 100644 --- a/src/main/kotlin/com/beust/kobalt/Plugins.kt +++ b/src/main/kotlin/com/beust/kobalt/Plugins.kt @@ -5,7 +5,6 @@ import com.beust.kobalt.api.annotation.Task import com.beust.kobalt.internal.PluginInfo import com.beust.kobalt.internal.TaskManager import com.beust.kobalt.maven.DepFactory -import com.beust.kobalt.api.IClasspathDependency import com.beust.kobalt.maven.LocalRepo import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.KobaltExecutors @@ -26,7 +25,8 @@ public class Plugins @Inject constructor (val taskManagerProvider : Provider() @@ -84,33 +84,15 @@ public class Plugins @Inject constructor (val taskManagerProvider : Provider - val method = methodTask.method - val annotation = methodTask.taskAnnotation - - val methodName = method.declaringClass.toString() + "." + method.name - log(3, " Found task:${annotation.name} method: $methodName") - - fun toTask(m: Method, project: Project, plugin: IPlugin): (Project) -> TaskResult { - val result: (Project) -> TaskResult = { - m.invoke(plugin, project) as TaskResult - } - return result - } - - projects.filter { plugin.accept(it) }.forEach { project -> - plugin.addStaticTask(annotation, project, toTask(method, project, plugin)) - } - } } + + // Now that we have collected all static and dynamic tasks, turn them all into plug-in tasks + taskManager.computePluginTasks(plugins, projects) } /** @@ -136,9 +118,6 @@ public class Plugins @Inject constructor (val taskManagerProvider : Provider() - val allTasks : List - get() = Plugins.plugins.flatMap { it.tasks } - fun installPlugins(dependencies: List, classLoader: ClassLoader) { val executor = executors.newExecutor("Plugins", 5) dependencies.forEach { diff --git a/src/main/kotlin/com/beust/kobalt/api/BasePlugin.kt b/src/main/kotlin/com/beust/kobalt/api/BasePlugin.kt index dedbbcc5..651dcd32 100644 --- a/src/main/kotlin/com/beust/kobalt/api/BasePlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/api/BasePlugin.kt @@ -4,13 +4,10 @@ import com.beust.kobalt.Plugins import com.beust.kobalt.TaskResult import com.beust.kobalt.Variant import com.beust.kobalt.internal.TaskManager -import java.util.* import kotlin.properties.Delegates abstract public class BasePlugin : IPlugin { - override val tasks: ArrayList = arrayListOf() override var taskManager: TaskManager by Delegates.notNull() - override var methodTasks = arrayListOf() override fun accept(project: Project) = true var plugins: Plugins by Delegates.notNull() @@ -36,7 +33,7 @@ abstract public class BasePlugin : IPlugin { runTask: (Project) -> TaskResult) { Variant.allVariants(project).forEach { variant -> val variantTaskName = variant.toTask(taskName) - addTask(project, variantTaskName, variantTaskName, + taskManager.addTask(this, project, variantTaskName, variantTaskName, runBefore = runBefore.map { variant.toTask(it) }, runAfter = runAfter.map { variant.toTask(it) }, task = { p: Project -> diff --git a/src/main/kotlin/com/beust/kobalt/api/IPlugin.kt b/src/main/kotlin/com/beust/kobalt/api/IPlugin.kt index 50269b4d..97eaa2e0 100644 --- a/src/main/kotlin/com/beust/kobalt/api/IPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/api/IPlugin.kt @@ -1,43 +1,10 @@ package com.beust.kobalt.api -import com.beust.kobalt.BasePluginTask -import com.beust.kobalt.TaskResult -import com.beust.kobalt.api.annotation.Task import com.beust.kobalt.internal.TaskManager -import com.beust.kobalt.internal.TaskResult2 -import java.lang.reflect.Method -import java.util.* public interface IPlugin : IPluginActor { val name: String - val tasks : ArrayList fun accept(project: Project) : Boolean fun apply(project: Project, context: KobaltContext) {} - - class MethodTask(val method: Method, val taskAnnotation: Task) - val methodTasks : ArrayList - - fun addStaticTask(annotation: Task, project: Project, task: (Project) -> TaskResult) { - addTask(project, annotation.name, annotation.description, annotation.runBefore.toList(), - annotation.runAfter.toList(), annotation.alwaysRunAfter.toList(), task) - } - - fun addTask(project: Project, name: String, description: String = "", - runBefore: List = listOf(), - runAfter: List = listOf(), - alwaysRunAfter: List = listOf(), - task: (Project) -> TaskResult) { - tasks.add( - object : BasePluginTask(this, name, description, project) { - override fun call(): TaskResult2 { - val taskResult = task(project) - return TaskResult2(taskResult.success, this) - } - }) - runBefore.forEach { taskManager.runBefore(it, name) } - runAfter.forEach { taskManager.runBefore(name, it) } - alwaysRunAfter.forEach { taskManager.alwaysRunAfter(it, name)} - } - var taskManager : TaskManager } diff --git a/src/main/kotlin/com/beust/kobalt/api/Project.kt b/src/main/kotlin/com/beust/kobalt/api/Project.kt index 3e00e783..41bf1c72 100644 --- a/src/main/kotlin/com/beust/kobalt/api/Project.kt +++ b/src/main/kotlin/com/beust/kobalt/api/Project.kt @@ -26,7 +26,7 @@ open public class Project( @Directive open var packageName: String? = group, val projectInfo: IProjectInfo) : IBuildConfig { - override var buildConfig = BuildConfig() + override var buildConfig : BuildConfig? = null //BuildConfig() val testArgs = arrayListOf() val testJvmArgs = arrayListOf() @@ -171,7 +171,7 @@ class BuildConfig { } interface IBuildConfig { - var buildConfig: BuildConfig + var buildConfig: BuildConfig? fun buildConfig(init: BuildConfig.() -> Unit) { buildConfig = BuildConfig().apply { @@ -181,7 +181,7 @@ interface IBuildConfig { } class ProductFlavorConfig(val name: String) : IBuildConfig { - override var buildConfig = BuildConfig() + override var buildConfig : BuildConfig? = BuildConfig() } @Directive @@ -199,7 +199,7 @@ class BuildTypeConfig(val project: Project?, val name: String) : IBuildConfig { return Proguard(androidPlugin.androidHome(project)).getDefaultProguardFile(name) } - override var buildConfig = BuildConfig() + override var buildConfig : BuildConfig? = BuildConfig() } @Directive diff --git a/src/main/kotlin/com/beust/kobalt/internal/TaskManager.kt b/src/main/kotlin/com/beust/kobalt/internal/TaskManager.kt index 58ce4aa5..2db70066 100644 --- a/src/main/kotlin/com/beust/kobalt/internal/TaskManager.kt +++ b/src/main/kotlin/com/beust/kobalt/internal/TaskManager.kt @@ -1,18 +1,21 @@ package com.beust.kobalt.internal import com.beust.kobalt.* +import com.beust.kobalt.api.IPlugin import com.beust.kobalt.api.PluginTask import com.beust.kobalt.api.Project +import com.beust.kobalt.api.annotation.Task import com.beust.kobalt.misc.log import com.google.common.collect.ArrayListMultimap import com.google.common.collect.Multimap import com.google.common.collect.TreeMultimap +import java.lang.reflect.Method import java.util.* import javax.inject.Inject import javax.inject.Singleton @Singleton -public class TaskManager @Inject constructor(val plugins: Plugins, val args: Args) { +public class TaskManager @Inject constructor(val args: Args) { private val runBefore = TreeMultimap.create() private val alwaysRunAfter = TreeMultimap.create() @@ -48,7 +51,7 @@ public class TaskManager @Inject constructor(val plugins: Plugins, val args: Arg // There can be multiple tasks by the same name (e.g. PackagingPlugin and AndroidPlugin both // define "install"), so use a multimap val tasksByNames = ArrayListMultimap.create() - plugins.allTasks.filter { + tasks.filter { it.project.name == project.name }.forEach { tasksByNames.put(it.name, it) @@ -211,6 +214,87 @@ public class TaskManager @Inject constructor(val plugins: Plugins, val args: Arg return transitiveClosure } + + ///// + // Manage the tasks + // + + class StaticTask(val plugin: IPlugin, val method: Method, val taskAnnotation: Task) + class DynamicTask(val plugin: IPlugin, val name: String, val description: String, + val runBefore: List = listOf(), + val runAfter: List = listOf(), + val alwaysRunAfter: List = listOf(), + val closure: (Project) -> TaskResult) + + val tasks = arrayListOf() + val staticTasks = arrayListOf() + val dynamicTasks = arrayListOf() + + /** + * Turn all the static and dynamic tasks into plug-in tasks, which are then suitable to be executed. + */ + fun computePluginTasks(plugins: List, projects: List) { + addStaticTasks(projects) + addDynamicTasks(projects) + } + + private fun addDynamicTasks(projects: List) { + dynamicTasks.forEach { task -> + projects.filter { task.plugin.accept(it) }.forEach { project -> + addTask(task.plugin, project, task.name, task.description, task.runBefore, task.runAfter, + task.alwaysRunAfter, task.closure) + } + } + } + + private fun addStaticTasks(projects: List) { + staticTasks.forEach { staticTask -> + val method = staticTask.method + val annotation = staticTask.taskAnnotation + + val methodName = method.declaringClass.toString() + "." + method.name + log(3, " Found task:${annotation.name} method: $methodName") + + fun toTask(m: Method, project: Project, plugin: IPlugin): (Project) -> TaskResult { + val result: (Project) -> TaskResult = { + m.invoke(plugin, project) as TaskResult + } + return result + } + + val plugin = staticTask.plugin + projects.filter { plugin.accept(it) }.forEach { project -> + addStaticTask(plugin, project, staticTask.taskAnnotation, toTask(method, project, plugin)) + } + } + } + + private fun addStaticTask(plugin: IPlugin, project: Project, annotation: Task, task: (Project) -> TaskResult) { + addTask(plugin, project, annotation.name, annotation.description, annotation.runBefore.toList(), + annotation.runAfter.toList(), annotation.alwaysRunAfter.toList(), task) + } + + fun addTask(plugin: IPlugin, project: Project, name: String, description: String = "", + runBefore: List = listOf(), + runAfter: List = listOf(), + alwaysRunAfter: List = listOf(), + task: (Project) -> TaskResult) { + tasks.add( + object : BasePluginTask(plugin, name, description, project) { + override fun call(): TaskResult2 { + val taskResult = task(project) + return TaskResult2(taskResult.success, this) + } + }) + runBefore.forEach { runBefore(it, name) } + runAfter.forEach { runBefore(name, it) } + alwaysRunAfter.forEach { alwaysRunAfter(it, name)} + } + + // + // + ///// + } class TaskWorker(val tasks: List, val dryRun: Boolean) : IWorker { diff --git a/src/main/kotlin/com/beust/kobalt/internal/build/BuildScriptUtil.kt b/src/main/kotlin/com/beust/kobalt/internal/build/BuildScriptUtil.kt index 7fceb1a9..f3b07e85 100644 --- a/src/main/kotlin/com/beust/kobalt/internal/build/BuildScriptUtil.kt +++ b/src/main/kotlin/com/beust/kobalt/internal/build/BuildScriptUtil.kt @@ -2,11 +2,10 @@ package com.beust.kobalt.internal.build import com.beust.kobalt.KobaltException import com.beust.kobalt.Plugins -import com.beust.kobalt.api.IPlugin import com.beust.kobalt.api.KobaltContext import com.beust.kobalt.api.Project import com.beust.kobalt.api.annotation.Task -import com.beust.kobalt.internal.build.BuildFile +import com.beust.kobalt.internal.TaskManager import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.Topological import com.beust.kobalt.misc.log @@ -20,7 +19,8 @@ import java.net.URLClassLoader import java.util.* import java.util.jar.JarInputStream -class BuildScriptUtil @Inject constructor(val plugins: Plugins, val files: KFiles){ +class BuildScriptUtil @Inject constructor(val plugins: Plugins, val files: KFiles, + val taskManager: TaskManager) { val projects = arrayListOf() /** @@ -82,7 +82,8 @@ class BuildScriptUtil @Inject constructor(val plugins: Plugins, val files: KFile } else { val taskAnnotation = method.getAnnotation(Task::class.java) if (taskAnnotation != null) { - Plugins.defaultPlugin.methodTasks.add(IPlugin.MethodTask(method, taskAnnotation)) + taskManager.staticTasks.add(TaskManager.StaticTask(Plugins.defaultPlugin, + method, taskAnnotation)) } }}