Change task creation with task registration in Kotlin plugin
#KT-27657 Fixed
This commit is contained in:
+94
-66
@@ -63,7 +63,7 @@ internal abstract class KotlinSourceSetProcessor<T : AbstractKotlinCompile<*>>(
|
||||
|
||||
protected val sourceSetName: String = kotlinCompilation.compilationName
|
||||
|
||||
protected val kotlinTask: T = createKotlinCompileTask()
|
||||
protected val kotlinTask: TaskHolder<out T> = registerKotlinCompileTask()
|
||||
|
||||
protected val javaSourceSet: SourceSet? = (kotlinCompilation as? KotlinWithJavaCompilation<*>)?.javaSourceSet
|
||||
|
||||
@@ -82,14 +82,15 @@ internal abstract class KotlinSourceSetProcessor<T : AbstractKotlinCompile<*>>(
|
||||
}
|
||||
}
|
||||
|
||||
private fun createKotlinCompileTask(): T {
|
||||
private fun registerKotlinCompileTask(): TaskHolder<out T> {
|
||||
val name = kotlinCompilation.compileKotlinTaskName
|
||||
logger.kotlinDebug("Creating kotlin compile task $name")
|
||||
val kotlinCompile = doCreateTask(project, name)
|
||||
kotlinCompile.description = taskDescription
|
||||
kotlinCompile.mapClasspath { kotlinCompilation.compileDependencyFiles }
|
||||
kotlinCompile.setDestinationDir { defaultKotlinDestinationDir }
|
||||
kotlinCompilation.output.tryAddClassesDir { project.files(kotlinTask.destinationDir).builtBy(kotlinTask) }
|
||||
val kotlinCompile = doRegisterTask(project, name) {
|
||||
it.description = taskDescription
|
||||
it.mapClasspath { kotlinCompilation.compileDependencyFiles }
|
||||
it.setDestinationDir { defaultKotlinDestinationDir }
|
||||
kotlinCompilation.output.tryAddClassesDir { project.files(kotlinTask.doGetTask().destinationDir).builtBy(kotlinTask.doGetTask()) }
|
||||
}
|
||||
return kotlinCompile
|
||||
}
|
||||
|
||||
@@ -134,16 +135,30 @@ internal abstract class KotlinSourceSetProcessor<T : AbstractKotlinCompile<*>>(
|
||||
}
|
||||
|
||||
private fun createAdditionalClassesTaskForIdeRunner() {
|
||||
open class IDEClassesTask : DefaultTask()
|
||||
// Workaround: as per KT-26641, when there's a Kotlin compilation with a Java source set, we create another task
|
||||
// that has a name composed as '<IDE module name>Classes`, where the IDE module name is the default source set name:
|
||||
val expectedClassesTaskName = "${kotlinCompilation.defaultSourceSetName}Classes"
|
||||
project.tasks.run {
|
||||
if (findByName(expectedClassesTaskName) == null)
|
||||
create(expectedClassesTaskName) { task -> task.dependsOn(getByName(kotlinCompilation.compileAllTaskName)) }
|
||||
var shouldCreateTask = false
|
||||
if (useLazyTaskConfiguration) {
|
||||
try {
|
||||
named(expectedClassesTaskName)
|
||||
} catch (e: Exception) {
|
||||
shouldCreateTask = true
|
||||
}
|
||||
} else {
|
||||
shouldCreateTask = findByName(expectedClassesTaskName) == null
|
||||
}
|
||||
if (shouldCreateTask) {
|
||||
registerTask(project, expectedClassesTaskName, IDEClassesTask::class.java) {
|
||||
it.dependsOn(getByName(kotlinCompilation.compileAllTaskName))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun doCreateTask(project: Project, taskName: String): T
|
||||
protected abstract fun doRegisterTask(project: Project, taskName: String, configureAction: (T) -> (Unit)): TaskHolder<out T>
|
||||
}
|
||||
|
||||
internal class Kotlin2JvmSourceSetProcessor(
|
||||
@@ -159,8 +174,8 @@ internal class Kotlin2JvmSourceSetProcessor(
|
||||
File(project.buildDir, "kotlin-classes/$sourceSetName") else
|
||||
super.defaultKotlinDestinationDir
|
||||
|
||||
override fun doCreateTask(project: Project, taskName: String): KotlinCompile =
|
||||
tasksProvider.createKotlinJVMTask(project, taskName, kotlinCompilation)
|
||||
override fun doRegisterTask(project: Project, taskName: String, configureAction: (KotlinCompile)->(Unit)): TaskHolder<out KotlinCompile> =
|
||||
tasksProvider.registerKotlinJVMTask(project, taskName, kotlinCompilation, configureAction)
|
||||
|
||||
override fun doTargetSpecificProcessing() {
|
||||
ifKaptEnabled(project) {
|
||||
@@ -169,29 +184,30 @@ internal class Kotlin2JvmSourceSetProcessor(
|
||||
|
||||
ScriptingGradleSubplugin.configureForSourceSet(project, kotlinCompilation.compilationName)
|
||||
|
||||
project.afterEvaluate { project ->
|
||||
project.runOnceAfterEvaluated("Kotlin2JvmSourceSetProcessor.doTargetSpecificProcessing", kotlinTask) {
|
||||
val kotlinTaskInstance = kotlinTask.doGetTask()
|
||||
val javaTask = javaSourceSet?.let { project.tasks.findByName(it.compileJavaTaskName) as JavaCompile }
|
||||
|
||||
val subpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinPluginVersion)
|
||||
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
|
||||
project, kotlinTask, javaTask, null, null, kotlinCompilation
|
||||
project, kotlinTaskInstance, javaTask, null, null, kotlinCompilation
|
||||
)
|
||||
|
||||
appliedPlugins
|
||||
.flatMap { it.getSubpluginKotlinTasks(project, kotlinTask) }
|
||||
.flatMap { it.getSubpluginKotlinTasks(project, kotlinTaskInstance) }
|
||||
.forEach { plugin -> kotlinCompilation.allKotlinSourceSets.forEach { sourceSet -> plugin.source(sourceSet.kotlin) } }
|
||||
|
||||
javaTask?.let { configureJavaTask(kotlinTask, it, logger) }
|
||||
javaTask?.let { configureJavaTask(kotlinTaskInstance, it, logger) }
|
||||
|
||||
var syncOutputTask: SyncOutputTask? = null
|
||||
|
||||
if (!isSeparateClassesDirSupported && javaTask != null) {
|
||||
syncOutputTask = createSyncOutputTask(project, kotlinTask, javaTask, sourceSetName)
|
||||
syncOutputTask = registerSyncOutputTask(project, kotlinTaskInstance, javaTask, sourceSetName)
|
||||
}
|
||||
|
||||
if (project.pluginManager.hasPlugin("java-library") && sourceSetName == SourceSet.MAIN_SOURCE_SET_NAME) {
|
||||
val (classesProviderTask, classesDirectory) = when {
|
||||
isSeparateClassesDirSupported -> kotlinTask.let { it to it.destinationDir }
|
||||
isSeparateClassesDirSupported -> kotlinTaskInstance.let { it to it.destinationDir }
|
||||
else -> syncOutputTask!!.let { it to it.javaOutputDir }
|
||||
}
|
||||
|
||||
@@ -250,55 +266,61 @@ internal class Kotlin2JsSourceSetProcessor(
|
||||
project, tasksProvider, taskDescription = "Compiles the Kotlin sources in $kotlinCompilation to JavaScript.",
|
||||
kotlinCompilation = kotlinCompilation
|
||||
) {
|
||||
override fun doCreateTask(project: Project, taskName: String): Kotlin2JsCompile =
|
||||
tasksProvider.createKotlinJSTask(project, taskName, kotlinCompilation)
|
||||
override fun doRegisterTask(
|
||||
project: Project,
|
||||
taskName: String,
|
||||
configureAction: (Kotlin2JsCompile) -> (Unit)
|
||||
): TaskHolder<out Kotlin2JsCompile> =
|
||||
tasksProvider.registerKotlinJSTask(project, taskName, kotlinCompilation, configureAction)
|
||||
|
||||
override fun doTargetSpecificProcessing() {
|
||||
project.tasks.findByName(kotlinCompilation.compileAllTaskName)!!.dependsOn(kotlinTask)
|
||||
project.tasks.findByName(kotlinCompilation.compileAllTaskName)!!.dependsOn(kotlinTask.getTaskOrProvider())
|
||||
|
||||
createCleanSourceMapTask()
|
||||
registerCleanSourceMapTask()
|
||||
|
||||
if (kotlinCompilation is KotlinWithJavaCompilation<*>) {
|
||||
kotlinCompilation.javaSourceSet.clearJavaSrcDirs()
|
||||
}
|
||||
|
||||
// outputFile can be set later during the configuration phase, get it only after the phase:
|
||||
project.afterEvaluate { project ->
|
||||
kotlinTask.kotlinOptions.outputFile = kotlinTask.outputFile.absolutePath
|
||||
val outputDir = kotlinTask.outputFile.parentFile
|
||||
project.runOnceAfterEvaluated("Kotlin2JsSourceSetProcessor.doTargetSpecificProcessing", kotlinTask) {
|
||||
val kotlinTaskInstance = kotlinTask.doGetTask()
|
||||
kotlinTaskInstance.kotlinOptions.outputFile = kotlinTaskInstance.outputFile.absolutePath
|
||||
val outputDir = kotlinTaskInstance.outputFile.parentFile
|
||||
|
||||
val subpluginEnvironment: SubpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinPluginVersion)
|
||||
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
|
||||
project, kotlinTask, null, null, null, kotlinCompilation
|
||||
project, kotlinTaskInstance, null, null, null, kotlinCompilation
|
||||
)
|
||||
|
||||
if (outputDir.isParentOf(project.rootDir))
|
||||
throw InvalidUserDataException(
|
||||
"The output directory '$outputDir' (defined by outputFile of $kotlinTask) contains or " +
|
||||
"The output directory '$outputDir' (defined by outputFile of $kotlinTaskInstance) contains or " +
|
||||
"matches the project root directory '${project.rootDir}'.\n" +
|
||||
"Gradle will not be able to build the project because of the root directory lock.\n" +
|
||||
"To fix this, consider using the default outputFile location instead of providing it explicitly."
|
||||
)
|
||||
|
||||
kotlinTask.destinationDir = outputDir
|
||||
kotlinTaskInstance.destinationDir = outputDir
|
||||
|
||||
if (!isSeparateClassesDirSupported && kotlinCompilation is KotlinWithJavaCompilation<*>) {
|
||||
kotlinCompilation.javaSourceSet.output.setClassesDirCompatible(kotlinTask.destinationDir)
|
||||
kotlinCompilation.javaSourceSet.output.setClassesDirCompatible(kotlinTaskInstance.destinationDir)
|
||||
}
|
||||
|
||||
appliedPlugins
|
||||
.flatMap { it.getSubpluginKotlinTasks(project, kotlinTask) }
|
||||
.flatMap { it.getSubpluginKotlinTasks(project, kotlinTaskInstance) }
|
||||
.forEach { task -> kotlinCompilation.allKotlinSourceSets.forEach { sourceSet -> task.source(sourceSet.kotlin) } }
|
||||
}
|
||||
}
|
||||
|
||||
private fun createCleanSourceMapTask() {
|
||||
private fun registerCleanSourceMapTask() {
|
||||
val taskName = kotlinCompilation.composeName("clean", "sourceMap")
|
||||
val task = project.tasks.create(taskName, Delete::class.java)
|
||||
task.onlyIf { kotlinTask.kotlinOptions.sourceMap }
|
||||
task.delete(object : Closure<String>(this) {
|
||||
override fun call(): String? = (kotlinTask.property("outputFile") as File).canonicalPath + ".map"
|
||||
})
|
||||
registerTask(project, taskName, Delete::class.java) {
|
||||
it.onlyIf { kotlinTask.doGetTask().kotlinOptions.sourceMap }
|
||||
it.delete(object : Closure<String>(this) {
|
||||
override fun call(): String? = (kotlinTask.doGetTask().property("outputFile") as File).canonicalPath + ".map"
|
||||
})
|
||||
}
|
||||
project.tasks.findByName("clean")?.dependsOn(taskName)
|
||||
}
|
||||
}
|
||||
@@ -313,25 +335,27 @@ internal class KotlinCommonSourceSetProcessor(
|
||||
kotlinCompilation = compilation
|
||||
) {
|
||||
override fun doTargetSpecificProcessing() {
|
||||
project.tasks.findByName(kotlinCompilation.compileAllTaskName)!!.dependsOn(kotlinTask)
|
||||
project.tasks.findByName(kotlinCompilation.compileAllTaskName)!!.dependsOn(kotlinTask.getTaskOrProvider())
|
||||
// can be missing (e.g. in case of tests)
|
||||
if (kotlinCompilation.compilationName == KotlinCompilation.MAIN_COMPILATION_NAME) {
|
||||
project.tasks.findByName(kotlinCompilation.target.artifactsTaskName)?.dependsOn(kotlinTask)
|
||||
project.tasks.findByName(kotlinCompilation.target.artifactsTaskName)?.dependsOn(kotlinTask.getTaskOrProvider())
|
||||
}
|
||||
|
||||
project.afterEvaluate { project ->
|
||||
project.runOnceAfterEvaluated("KotlinCommonSourceSetProcessor.doTargetSpecificProcessing", kotlinTask) {
|
||||
val kotlinTaskInstance = kotlinTask.doGetTask()
|
||||
val subpluginEnvironment: SubpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinPluginVersion)
|
||||
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
|
||||
project, kotlinTask, null, null, null, kotlinCompilation
|
||||
project, kotlinTaskInstance, null, null, null, kotlinCompilation
|
||||
)
|
||||
appliedPlugins
|
||||
.flatMap { it.getSubpluginKotlinTasks(project, kotlinTask) }
|
||||
.flatMap { it.getSubpluginKotlinTasks(project, kotlinTaskInstance) }
|
||||
.forEach { kotlinCompilation.allKotlinSourceSets.forEach { sourceSet -> it.source(sourceSet.kotlin) } }
|
||||
}
|
||||
}
|
||||
|
||||
override fun doCreateTask(project: Project, taskName: String): KotlinCompileCommon =
|
||||
tasksProvider.createKotlinCommonTask(project, taskName, kotlinCompilation)
|
||||
// protected abstract fun doRegisterTask(project: Project, taskName: String, configureAction: (T) -> (Unit)): TaskHolder<out T>
|
||||
override fun doRegisterTask(project: Project, taskName: String, configureAction: (KotlinCompileCommon) -> (Unit)): TaskHolder<out KotlinCompileCommon> =
|
||||
tasksProvider.registerKotlinCommonTask(project, taskName, kotlinCompilation, configureAction)
|
||||
}
|
||||
|
||||
internal abstract class AbstractKotlinPlugin(
|
||||
@@ -387,11 +411,12 @@ internal abstract class AbstractKotlinPlugin(
|
||||
)
|
||||
return
|
||||
}
|
||||
val inspectTask = project.tasks.create("inspectClassesForKotlinIC", InspectClassesForMultiModuleIC::class.java)
|
||||
inspectTask.sourceSetName = SourceSet.MAIN_SOURCE_SET_NAME
|
||||
inspectTask.jarTask = jarTask
|
||||
inspectTask.dependsOn(classesTask)
|
||||
jarTask.dependsOn(inspectTask)
|
||||
val inspectTask = registerTask(project, "inspectClassesForKotlinIC", InspectClassesForMultiModuleIC::class.java) {
|
||||
it.sourceSetName = SourceSet.MAIN_SOURCE_SET_NAME
|
||||
it.jarTask = jarTask
|
||||
it.dependsOn(classesTask)
|
||||
}
|
||||
jarTask.dependsOn(inspectTask.getTaskOrProvider())
|
||||
}
|
||||
|
||||
private fun setUpJavaSourceSets(
|
||||
@@ -739,16 +764,17 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
|
||||
|
||||
val kotlinTaskName = compilation.compileKotlinTaskName
|
||||
// todo: Investigate possibility of creating and configuring kotlinTask before evaluation
|
||||
val kotlinTask = tasksProvider.createKotlinJVMTask(project, kotlinTaskName, compilation)
|
||||
kotlinTask.parentKotlinOptionsImpl = rootKotlinOptions
|
||||
val kotlinTask = tasksProvider.registerKotlinJVMTask(project, kotlinTaskName, compilation) {
|
||||
it.parentKotlinOptionsImpl = rootKotlinOptions
|
||||
|
||||
// store kotlin classes in separate directory. They will serve as class-path to java compiler
|
||||
kotlinTask.destinationDir = File(project.buildDir, "tmp/kotlin-classes/$variantDataName")
|
||||
kotlinTask.description = "Compiles the $variantDataName kotlin."
|
||||
// store kotlin classes in separate directory. They will serve as class-path to java compiler
|
||||
it.destinationDir = File(project.buildDir, "tmp/kotlin-classes/$variantDataName")
|
||||
it.description = "Compiles the $variantDataName kotlin."
|
||||
}
|
||||
|
||||
// Register the source only after the task is created, because the task is required for that:
|
||||
compilation.source(defaultSourceSet)
|
||||
configureSources(kotlinTask, variantData, compilation)
|
||||
configureSources(kotlinTask.doGetTask(), variantData, compilation)
|
||||
|
||||
// In MPPs, add the common main Kotlin sources to non-test variants, the common test sources to test variants
|
||||
val commonSourceSetName = if (getTestedVariantData(variantData) == null)
|
||||
@@ -758,7 +784,7 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
|
||||
compilation.source(it)
|
||||
}
|
||||
|
||||
wireKotlinTasks(project, compilation, androidPlugin, androidExt, variantData, javaTask, kotlinTask)
|
||||
wireKotlinTasks(project, compilation, androidPlugin, androidExt, variantData, javaTask, kotlinTask.doGetTask())
|
||||
}
|
||||
|
||||
private fun applySubplugins(
|
||||
@@ -825,7 +851,7 @@ internal fun configureJavaTask(kotlinTask: KotlinCompile, javaTask: AbstractComp
|
||||
|
||||
internal fun syncOutputTaskName(variantName: String) = "copy${variantName.capitalize()}KotlinClasses"
|
||||
|
||||
internal fun createSyncOutputTask(
|
||||
internal fun registerSyncOutputTask(
|
||||
project: Project,
|
||||
kotlinCompile: KotlinCompile,
|
||||
javaTask: AbstractCompile,
|
||||
@@ -835,19 +861,21 @@ internal fun createSyncOutputTask(
|
||||
val javaDir = javaTask.destinationDir
|
||||
val taskName = syncOutputTaskName(variantName)
|
||||
|
||||
val syncTask = project.tasks.create(taskName, SyncOutputTask::class.java)
|
||||
syncTask.kotlinOutputDir = kotlinDir
|
||||
syncTask.javaOutputDir = javaDir
|
||||
syncTask.kotlinTask = kotlinCompile
|
||||
// registerTask(project: Project, name: String, type: Class<T>, disableLazy: Boolean, body: (T)->(Unit)) : TaskHolder<T> {
|
||||
val syncTask = registerTask(project, taskName, SyncOutputTask::class.java) {
|
||||
it.kotlinOutputDir = kotlinDir
|
||||
it.javaOutputDir = javaDir
|
||||
it.kotlinTask = kotlinCompile
|
||||
it.kaptClassesDir = getKaptGeneratedClassesDir(project, variantName)
|
||||
// copying should be executed after a latter task
|
||||
javaTask.finalizedByIfNotFailed(it)
|
||||
}
|
||||
|
||||
kotlinCompile.javaOutputDir = javaDir
|
||||
syncTask.kaptClassesDir = getKaptGeneratedClassesDir(project, variantName)
|
||||
|
||||
// copying should be executed after a latter task
|
||||
javaTask.finalizedByIfNotFailed(syncTask)
|
||||
project.logger.kotlinDebug { "Created task ${syncTask.doGetTask().path} to copy kotlin classes from $kotlinDir to $javaDir" }
|
||||
|
||||
project.logger.kotlinDebug { "Created task ${syncTask.path} to copy kotlin classes from $kotlinDir to $javaDir" }
|
||||
|
||||
return syncTask
|
||||
return syncTask.doGetTask()
|
||||
}
|
||||
|
||||
private fun ifKaptEnabled(project: Project, block: () -> Unit) {
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ internal class LegacyAndroidAndroidProjectHandler(kotlinConfigurationTools: Kotl
|
||||
}
|
||||
|
||||
configureJavaTask(kotlinTask, javaTask, logger)
|
||||
createSyncOutputTask(project, kotlinTask, javaTask, getVariantName(variantData))
|
||||
registerSyncOutputTask(project, kotlinTask, javaTask, getVariantName(variantData))
|
||||
|
||||
// In lib modules, the androidTest variants get the classes jar in their classpath instead of the Java
|
||||
// destination dir. Attach the JAR to be consumed as friend path:
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import org.gradle.api.Task
|
||||
|
||||
class LegacyTaskHolder<T : Task>(private val task: T) : TaskHolder<T> {
|
||||
override fun doGetTask() = task
|
||||
|
||||
override fun getTaskOrProvider(): Any = task
|
||||
|
||||
override fun configure(action: (T) -> (Unit)) {
|
||||
with(task, action)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "TaskHolder instance: [className: ${javaClass.name}, task name: '${doGetTask().name}']"
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.logging.Logging
|
||||
|
||||
/**
|
||||
* This class encapsulated logic which should be invoked during not before the script evaluation is ready and
|
||||
* not earlier than the task is configured
|
||||
*/
|
||||
internal class RunOnceAfterEvaluated(private val name: String, private val action: () -> (Unit)) {
|
||||
private val logger = Logging.getLogger(this.javaClass)!!
|
||||
private var executed = false
|
||||
private var configured = false
|
||||
private var evaluated = false
|
||||
|
||||
private fun execute() {
|
||||
logger.debug("[$name] RunOnceAfterEvaluated - execute executed=$executed evaluated=$evaluated configured=$configured")
|
||||
if (!executed) {
|
||||
logger.debug("[$name] RunOnceAfterEvaluated - EXECUTING executed=$executed evaluated=$evaluated configured=$configured")
|
||||
action()
|
||||
}
|
||||
executed = true
|
||||
}
|
||||
|
||||
fun onEvaluated() {
|
||||
logger.debug("[$name] RunOnceAfterEvaluated - onEvaluated executed=$executed evaluated=$evaluated configured=$configured")
|
||||
evaluated = true
|
||||
if (configured) {
|
||||
execute()
|
||||
}
|
||||
}
|
||||
|
||||
fun onConfigure() {
|
||||
logger.debug("[$name] RunOnceAfterEvaluated - onConfigure executed=$executed evaluated=$evaluated configured=$configured")
|
||||
configured = true
|
||||
if (evaluated) {
|
||||
execute()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Project.runOnceAfterEvaluated(name: String, task: TaskHolder<*>, action: () -> (Unit)) {
|
||||
val runOnce = RunOnceAfterEvaluated(name, action)
|
||||
runOnceAfterEvaluated(runOnce, task)
|
||||
}
|
||||
|
||||
internal fun Project.runOnceAfterEvaluated(runOnce: RunOnceAfterEvaluated, task: TaskHolder<*>) {
|
||||
if (state.executed) {
|
||||
runOnce.onEvaluated()
|
||||
} else {
|
||||
afterEvaluate { runOnce.onEvaluated() }
|
||||
}
|
||||
task.configure {
|
||||
runOnce.onConfigure()
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.Project
|
||||
|
||||
|
||||
/**
|
||||
* Reference to a org.gradle.api.Task or org.gradle.api.TaskProvider necessary in order to support flexible creation of tasks.
|
||||
* For gradle versions < 4.9 tasks are created meanwhile for gradle with version >= 4.9 tasks are registered
|
||||
*/
|
||||
interface TaskHolder<T : Task> {
|
||||
|
||||
/**
|
||||
* Returns Task itself if task was created or TaskProvider<Task> if task was registered.
|
||||
*/
|
||||
fun getTaskOrProvider(): Any
|
||||
|
||||
/**
|
||||
* Returns instance of task. If task created using lazy api, it will be instantiated
|
||||
*/
|
||||
fun doGetTask(): T
|
||||
|
||||
|
||||
/**
|
||||
* Invokes task configuration. If task was registered the configuration action is added but not invoked
|
||||
*/
|
||||
fun configure(action: (T) -> (Unit))
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
|
||||
class TaskProviderHolder<T : Task>(project: Project, private val name: String, type: Class<T>, configureAction: (T) -> (Unit)) :
|
||||
TaskHolder<T> {
|
||||
private val provider: TaskProvider<T> = project.tasks.register(name, type, configureAction)
|
||||
|
||||
override fun getTaskOrProvider(): Any = provider
|
||||
|
||||
override fun doGetTask(): T = provider.get()
|
||||
|
||||
override fun configure(action: (T) -> (Unit)) {
|
||||
provider.configure(action)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "TaskProviderHolder instance: [className: ${javaClass.name}, task name: '$name']"
|
||||
}
|
||||
}
|
||||
+9
-1
@@ -74,18 +74,26 @@ abstract class AbstractKotlinCompilation<T : KotlinCommonOptions>(
|
||||
}
|
||||
|
||||
open fun addSourcesToCompileTask(sourceSet: KotlinSourceSet, addAsCommonSources: Boolean) {
|
||||
(target.project.tasks.getByName(compileKotlinTaskName) as AbstractKotlinCompile<*>).apply {
|
||||
fun AbstractKotlinCompile<*>.configureAction() {
|
||||
source(sourceSet.kotlin)
|
||||
sourceFilesExtensions(sourceSet.customSourceFilesExtensions)
|
||||
if (addAsCommonSources) {
|
||||
commonSourceSet += sourceSet.kotlin
|
||||
}
|
||||
}
|
||||
// Note! Invocation of getByName results in preliminary task instantiation. After fix of this issue the following code should be uncommented:
|
||||
// if (useLazyTaskConfiguration) {
|
||||
// (target.project.tasks.named(compileKotlinTaskName) as TaskProvider<AbstractKotlinCompile<*>>).configure {
|
||||
// it.configureAction()
|
||||
// }
|
||||
// }
|
||||
(target.project.tasks.getByName(compileKotlinTaskName) as AbstractKotlinCompile<*>).configureAction()
|
||||
}
|
||||
|
||||
override fun source(sourceSet: KotlinSourceSet) {
|
||||
if (kotlinSourceSets.add(sourceSet)) {
|
||||
with(target.project) {
|
||||
//TODO possibly issue with forced instantiation
|
||||
whenEvaluated {
|
||||
sourceSet.getSourceSetHierarchy().forEach { sourceSet ->
|
||||
val isCommonSource =
|
||||
|
||||
+7
-1
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.gradle.internal.KaptGenerateStubsTask
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.scripting.ScriptingExtension
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.tasks.useLazyTaskConfiguration
|
||||
import org.jetbrains.kotlin.scripting.compiler.plugin.ScriptDefinitionsFromClasspathDiscoverySource
|
||||
import java.io.File
|
||||
|
||||
@@ -52,7 +53,7 @@ class ScriptingGradleSubplugin : Plugin<Project> {
|
||||
val javaPluginConvention = project.convention.findPlugin(JavaPluginConvention::class.java)
|
||||
if (javaPluginConvention?.sourceSets?.isEmpty() == false) {
|
||||
|
||||
project.tasks.withType(KotlinCompile::class.java) { task ->
|
||||
val configureAction: (KotlinCompile) -> (Unit) = { task ->
|
||||
|
||||
if (task !is KaptGenerateStubsTask) {
|
||||
|
||||
@@ -63,6 +64,11 @@ class ScriptingGradleSubplugin : Plugin<Project> {
|
||||
?: project.logger.warn("kotlin scripting plugin: $project.${task.name} - configuration not found: $discoveryClasspathConfigurationName, $MISCONFIGURATION_MESSAGE_SUFFIX")
|
||||
}
|
||||
}
|
||||
if (useLazyTaskConfiguration) {
|
||||
project.tasks.withType(KotlinCompile::class.java).configureEach(configureAction)
|
||||
} else {
|
||||
project.tasks.withType(KotlinCompile::class.java, configureAction)
|
||||
}
|
||||
} else {
|
||||
project.logger.warn("kotlin scripting plugin: applied to a non-JVM project $project, $MISCONFIGURATION_MESSAGE_SUFFIX")
|
||||
}
|
||||
|
||||
+61
-21
@@ -17,57 +17,95 @@
|
||||
package org.jetbrains.kotlin.gradle.tasks
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.defaultSourceSetName
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.applyLanguageSettingsToKotlinTask
|
||||
|
||||
internal val useLazyTaskConfiguration = org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast(4, 9)
|
||||
|
||||
/**
|
||||
* Registers the task with name @param name and type @param type and initialization script @param body
|
||||
* If gradle with version <4.9 is used the task will be created
|
||||
*/
|
||||
internal fun <T : Task> registerTask(project: Project, name: String, type: Class<T>, body: (T) -> (Unit)): TaskHolder<T> {
|
||||
return if (useLazyTaskConfiguration) {
|
||||
TaskProviderHolder(project, name, type) { with(it, body) }
|
||||
} else {
|
||||
val result = LegacyTaskHolder(project.tasks.create(name, type))
|
||||
with(result.doGetTask(), body)
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
internal open class KotlinTasksProvider(val targetName: String) {
|
||||
open fun createKotlinJVMTask(
|
||||
open fun registerKotlinJVMTask(
|
||||
project: Project,
|
||||
name: String,
|
||||
compilation: KotlinCompilation<*>
|
||||
): KotlinCompile {
|
||||
compilation: KotlinCompilation<*>,
|
||||
configureAction: (KotlinCompile) -> (Unit)
|
||||
): TaskHolder<out KotlinCompile> {
|
||||
val properties = PropertiesProvider(project)
|
||||
val taskClass = taskOrWorkersTask<KotlinCompile, KotlinCompileWithWorkers>(properties)
|
||||
return project.tasks.create(name, taskClass).apply {
|
||||
configure(this, project, properties, compilation)
|
||||
val result = registerTask(project, name, taskClass) {
|
||||
configureAction(it)
|
||||
}
|
||||
configure(result, project, properties, compilation)
|
||||
return result
|
||||
}
|
||||
|
||||
fun createKotlinJSTask(project: Project, name: String, compilation: KotlinCompilation<*>): Kotlin2JsCompile {
|
||||
fun registerKotlinJSTask(
|
||||
project: Project,
|
||||
name: String,
|
||||
compilation: KotlinCompilation<*>,
|
||||
configureAction: (Kotlin2JsCompile) -> Unit
|
||||
): TaskHolder<out Kotlin2JsCompile> {
|
||||
val properties = PropertiesProvider(project)
|
||||
val taskClass = taskOrWorkersTask<Kotlin2JsCompile, Kotlin2JsCompileWithWorkers>(properties)
|
||||
return project.tasks.create(name, taskClass).apply {
|
||||
configure(this, project, properties, compilation)
|
||||
val result = registerTask(project, name, taskClass) {
|
||||
configureAction(it)
|
||||
}
|
||||
configure(result, project, properties, compilation)
|
||||
return result
|
||||
}
|
||||
|
||||
fun createKotlinCommonTask(project: Project, name: String, compilation: KotlinCompilation<*>): KotlinCompileCommon {
|
||||
fun registerKotlinCommonTask(
|
||||
project: Project,
|
||||
name: String,
|
||||
compilation: KotlinCompilation<*>,
|
||||
configureAction: (KotlinCompileCommon) -> (Unit)
|
||||
): TaskHolder<out KotlinCompileCommon> {
|
||||
val properties = PropertiesProvider(project)
|
||||
val taskClass = taskOrWorkersTask<KotlinCompileCommon, KotlinCompileCommonWithWorkers>(properties)
|
||||
return project.tasks.create(name, taskClass).apply {
|
||||
configure(this, project, properties, compilation)
|
||||
val result = registerTask(project, name, taskClass) {
|
||||
configureAction(it)
|
||||
}
|
||||
configure(result, project, properties, compilation)
|
||||
return result
|
||||
}
|
||||
|
||||
open fun configure(
|
||||
kotlinTask: AbstractKotlinCompile<*>,
|
||||
kotlinTaskHolder: TaskHolder<out AbstractKotlinCompile<*>>,
|
||||
project: Project,
|
||||
propertiesProvider: PropertiesProvider,
|
||||
compilation: KotlinCompilation<*>
|
||||
) {
|
||||
kotlinTask.sourceSetName = compilation.name
|
||||
kotlinTask.friendTaskName = taskToFriendTaskMapper[kotlinTask]
|
||||
propertiesProvider.mapKotlinTaskProperties(kotlinTask)
|
||||
|
||||
project.whenEvaluated {
|
||||
val configureAfterEvaluated = RunOnceAfterEvaluated("TaskProvider.configure") {
|
||||
val languageSettings = project.kotlinExtension.sourceSets.findByName(compilation.defaultSourceSetName)?.languageSettings
|
||||
?: return@whenEvaluated
|
||||
?: return@RunOnceAfterEvaluated
|
||||
|
||||
val kotlinTask = kotlinTaskHolder.doGetTask()
|
||||
kotlinTask as org.jetbrains.kotlin.gradle.dsl.KotlinCompile<*>
|
||||
applyLanguageSettingsToKotlinTask(languageSettings, kotlinTask)
|
||||
}
|
||||
kotlinTaskHolder.configure {
|
||||
it.sourceSetName = compilation.name
|
||||
it.friendTaskName = taskToFriendTaskMapper[it]
|
||||
propertiesProvider.mapKotlinTaskProperties(it)
|
||||
configureAfterEvaluated.onConfigure()
|
||||
}
|
||||
project.runOnceAfterEvaluated(configureAfterEvaluated, kotlinTaskHolder)
|
||||
}
|
||||
|
||||
protected open val taskToFriendTaskMapper: TaskToFriendTaskMapper =
|
||||
@@ -82,12 +120,14 @@ internal class AndroidTasksProvider(targetName: String) : KotlinTasksProvider(ta
|
||||
RegexTaskToFriendTaskMapper.Android(targetName)
|
||||
|
||||
override fun configure(
|
||||
kotlinTask: AbstractKotlinCompile<*>,
|
||||
kotlinTaskHolder: TaskHolder<out AbstractKotlinCompile<*>>,
|
||||
project: Project,
|
||||
propertiesProvider: PropertiesProvider,
|
||||
compilation: KotlinCompilation<*>
|
||||
) {
|
||||
super.configure(kotlinTask, project, propertiesProvider, compilation)
|
||||
kotlinTask.useModuleDetection = true
|
||||
super.configure(kotlinTaskHolder, project, propertiesProvider, compilation)
|
||||
kotlinTaskHolder.configure {
|
||||
it.useModuleDetection = true
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user