Add Kotlin Gradle DSL to configure coroutines from build.gradle

This commit is contained in:
Alexey Tsvetkov
2017-01-26 23:14:17 +03:00
parent 08caf0a011
commit 1420bd1b33
8 changed files with 118 additions and 25 deletions
@@ -16,6 +16,8 @@
package org.jetbrains.kotlin.gradle
import org.jetbrains.kotlin.gradle.util.getFileByName
import org.jetbrains.kotlin.gradle.util.modify
import org.junit.Test
import java.io.File
@@ -26,6 +28,24 @@ class CoroutinesIT: BaseGradleIT() {
private const val GRADLE_PROPERTIES = "gradle.properties"
}
@Test
fun testCoroutinesProjectDSL() {
val project = Project("coroutinesProjectDSL", GRADLE_VERSION)
project.build("assemble") {
assertSuccessful()
assertContains("-Xcoroutines=enable")
}
project.projectDir.getFileByName("build.gradle").modify {
it.replace("coroutines 'enable'", "coroutines 'error'")
}
project.build("assemble") {
assertFailed()
assertContains("-Xcoroutines=error")
}
}
@Test
fun testCoroutinesJvmEnabled() {
jvmProject.doTest("enable", GRADLE_PROPERTIES)
@@ -0,0 +1,25 @@
buildscript {
repositories {
mavenLocal()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: "kotlin"
repositories {
mavenLocal()
mavenCentral()
}
kotlin {
experimental {
coroutines 'enable'
}
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
@@ -0,0 +1 @@
org.gradle.jvmargs=-Xmx1024m -XX:MaxPermSize=512m
@@ -0,0 +1 @@
suspend fun <T> suspendCoroutine(): T = TODO()
@@ -0,0 +1,47 @@
/*
* Copyright 2010-2017 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.dsl
import org.gradle.api.Project
import org.gradle.api.internal.plugins.DslObject
internal fun Project.createKotlinExtension() {
val kotlinExt = extensions.create("kotlin", KotlinProjectExtension::class.java)
DslObject(kotlinExt).extensions.create("experimental", ExperimentalExtension::class.java)
}
open class KotlinProjectExtension {
val experimental: ExperimentalExtension
get() = DslObject(this).extensions.getByType(ExperimentalExtension::class.java)!!
}
open class ExperimentalExtension {
var coroutines: Coroutines? = null
}
enum class Coroutines {
ENABLE,
WARN,
ERROR;
companion object {
val DEFAULT = WARN
fun byCompilerArgument(argument: String): Coroutines? =
Coroutines.values().firstOrNull { it.name.equals(argument, ignoreCase = true) }
}
}
@@ -19,8 +19,12 @@ package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.internal.file.FileResolver
import org.gradle.api.internal.plugins.DslObject
import org.gradle.api.logging.Logger
import org.gradle.api.logging.Logging
import org.jetbrains.kotlin.gradle.dsl.ExperimentalExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
import org.jetbrains.kotlin.gradle.dsl.createKotlinExtension
import org.jetbrains.kotlin.gradle.internal.KotlinSourceSetProviderImpl
import org.jetbrains.kotlin.gradle.tasks.*
import java.io.FileNotFoundException
@@ -36,6 +40,8 @@ abstract class KotlinBasePluginWrapper(protected val fileResolver: FileResolver)
System.setProperty(org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY, "true")
val kotlinGradleBuildServices = KotlinGradleBuildServices.getInstance(project.gradle)
project.createKotlinExtension()
val plugin = getPlugin(kotlinGradleBuildServices)
plugin.apply(project)
}
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.Coroutines
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import java.util.*
@@ -35,7 +36,7 @@ fun mapKotlinTaskProperties(project: Project, task: AbstractKotlinCompile<*>) {
private val propertyMappings = listOf(
KotlinPropertyMapping("kotlin.incremental", AbstractKotlinCompile<*>::incremental, String::toBoolean),
KotlinPropertyMapping("kotlin.coroutines", AbstractKotlinCompile<*>::coroutines) { CoroutineSupport.byCompilerArgument(it) }
KotlinPropertyMapping("kotlin.coroutines", AbstractKotlinCompile<*>::coroutinesFromGradleProperties) { Coroutines.byCompilerArgument(it) }
)
private class KotlinPropertyMapping<T>(
@@ -59,18 +60,4 @@ private class KotlinPropertyMapping<T>(
val transformedValue = transform(value) ?: return
taskProperty.set(task, transformedValue)
}
}
enum class CoroutineSupport(val compilerArgument: String) {
ENABLED("enable"),
ENABLED_WITH_WARNING("warn"),
DISABLED("error");
companion object {
val DEFAULT = ENABLED_WITH_WARNING
fun byCompilerArgument(argument: String): CoroutineSupport {
return CoroutineSupport.values().find { it.compilerArgument == argument } ?: DEFAULT
}
}
}
@@ -20,6 +20,7 @@ import org.codehaus.groovy.runtime.MethodClosure
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.logging.Logger
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.SourceTask
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.compile.AbstractCompile
@@ -35,7 +36,6 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.compilerRunner.*
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.plugin.CoroutineSupport
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
import org.jetbrains.kotlin.gradle.plugin.kotlinInfo
import org.jetbrains.kotlin.gradle.utils.ParsedGradleVersion
@@ -62,6 +62,9 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractCo
return ArgumentUtils.convertArgumentsToStringList(arguments)
}
private val kotlinExt: KotlinProjectExtension
get() = project.extensions.findByType(KotlinProjectExtension::class.java)!!
// indicates that task should compile kotlin incrementally if possible
// it's not possible when IncrementalTaskInputs#isIncremental returns false (i.e first build)
var incremental: Boolean = false
@@ -73,12 +76,13 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractCo
System.setProperty("kotlin.incremental.compilation.experimental", value.toString())
}
var coroutines: CoroutineSupport = CoroutineSupport.DEFAULT
get() = field
set(value) {
field = value
logger.kotlinDebug { "Set $this.coroutines=${value.compilerArgument}" }
}
internal var coroutinesFromGradleProperties: Coroutines? = null
// Input is needed to force rebuild even if source files are not changed
@get:Input
val coroutines: Coroutines
get() = kotlinExt.experimental.coroutines
?: coroutinesFromGradleProperties
?: Coroutines.DEFAULT
var compilerJarFile: File? = null
internal val compilerJar: File
@@ -124,9 +128,11 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractCo
internal abstract fun callCompiler(args: T, sourceRoots: SourceRoots, changedFiles: ChangedFiles)
private fun CommonCompilerArguments.setupCommonCompilerArgs() {
coroutinesEnable = coroutines == CoroutineSupport.ENABLED
coroutinesWarn = coroutines == CoroutineSupport.ENABLED_WITH_WARNING
coroutinesError = coroutines == CoroutineSupport.DISABLED
coroutines.let {
coroutinesEnable = it == Coroutines.ENABLE
coroutinesWarn = it == Coroutines.WARN
coroutinesError = it == Coroutines.ERROR
}
if (project.logger.isDebugEnabled) {
verbose = true