Drop Gradle versions older than 4.9

* Replace `TaskHolder` with `TaskProvider`, remove `TaskHolder`
* Migrate Gradle integration tests to Gradle 4.9+
This commit is contained in:
Sergey Igushkin
2019-08-06 20:49:45 +03:00
parent 9f0c5675bd
commit 43c3122a13
51 changed files with 219 additions and 426 deletions
@@ -21,7 +21,7 @@ open class KotlinAndroid32GradleIT : KotlinAndroid3GradleIT() {
get() = AGPVersion.v3_2_0 get() = AGPVersion.v3_2_0
override val defaultGradleVersion: GradleVersionRequired override val defaultGradleVersion: GradleVersionRequired
get() = GradleVersionRequired.AtLeast("4.6") get() = GradleVersionRequired.None
@Test @Test
fun testAndroidWithNewMppApp() = with(Project("new-mpp-android", GradleVersionRequired.AtLeast("5.0"))) { fun testAndroidWithNewMppApp() = with(Project("new-mpp-android", GradleVersionRequired.AtLeast("5.0"))) {
@@ -399,10 +399,7 @@ class KotlinAndroid30GradleIT : KotlinAndroid3GradleIT() {
get() = GradleVersionRequired.Until("4.10.2") get() = GradleVersionRequired.Until("4.10.2")
@Test @Test
fun testOmittedStdlibVersion() = Project( fun testOmittedStdlibVersion() = Project("AndroidProject").run {
"AndroidProject",
defaultGradleVersion.maxVersion?.let { GradleVersionRequired.InRange("4.4", it) } ?: GradleVersionRequired.AtLeast("4.4")
).run {
setupWorkingDir() setupWorkingDir()
gradleBuildScript("Lib").modify { gradleBuildScript("Lib").modify {
@@ -25,7 +25,7 @@ class BuildCacheIT : BaseGradleIT() {
super.defaultBuildOptions().copy(withBuildCache = true) super.defaultBuildOptions().copy(withBuildCache = true)
companion object { companion object {
private val GRADLE_VERSION = GradleVersionRequired.AtLeast("4.3") private val GRADLE_VERSION = GradleVersionRequired.None
} }
@Test @Test
@@ -48,7 +48,7 @@ class BuildCacheRelocationIT : BaseGradleIT() {
val (firstProject, secondProject) = (0..1).map { id -> val (firstProject, secondProject) = (0..1).map { id ->
workingDir = workingDirs[id] workingDir = workingDirs[id]
Project(projectName, GradleVersionRequired.AtLeast("4.4"), projectDirectoryPrefix).apply { Project(projectName, directoryPrefix = projectDirectoryPrefix).apply {
setupWorkingDir() setupWorkingDir()
initProject() initProject()
prepareLocalBuildCache(localBuildCacheDirectory) prepareLocalBuildCache(localBuildCacheDirectory)
@@ -17,7 +17,7 @@ import kotlin.test.fail
class CocoaPodsIT : BaseGradleIT() { class CocoaPodsIT : BaseGradleIT() {
// We use Kotlin DSL. Earlier Gradle versions fail at accessors codegen. // We use Kotlin DSL. Earlier Gradle versions fail at accessors codegen.
val gradleVersion = GradleVersionRequired.AtLeast("4.9") val gradleVersion = GradleVersionRequired.None
val PODFILE_IMPORT_DIRECTIVE_PLACEHOLDER = "<import_mode_directive>" val PODFILE_IMPORT_DIRECTIVE_PLACEHOLDER = "<import_mode_directive>"
@@ -21,7 +21,7 @@ import org.junit.Assume
sealed class GradleVersionRequired(val minVersion: String, val maxVersion: String?) { sealed class GradleVersionRequired(val minVersion: String, val maxVersion: String?) {
companion object { companion object {
const val OLDEST_SUPPORTED = "4.3" const val OLDEST_SUPPORTED = "4.9"
} }
class Exact(version: String) : GradleVersionRequired(version, version) class Exact(version: String) : GradleVersionRequired(version, version)
@@ -11,7 +11,7 @@ import org.junit.Test
class JavaUpToDateIT : BaseGradleIT() { class JavaUpToDateIT : BaseGradleIT() {
@Test @Test
fun testKotlinMethodBodyIsChanged() { fun testKotlinMethodBodyIsChanged() {
val project = Project("javaUpToDate", GradleVersionRequired.AtLeast("4.3")) val project = Project("javaUpToDate")
project.build("build") { project.build("build") {
assertSuccessful() assertSuccessful()
@@ -33,7 +33,7 @@ class JavaUpToDateIT : BaseGradleIT() {
@Test @Test
fun testKotlinNewLineAdded() { fun testKotlinNewLineAdded() {
val project = Project("javaUpToDate", GradleVersionRequired.AtLeast("4.3")) val project = Project("javaUpToDate")
project.build("build") { project.build("build") {
assertSuccessful() assertSuccessful()
@@ -50,7 +50,7 @@ class JavaUpToDateIT : BaseGradleIT() {
@Test @Test
fun testPrivateMethodSignatureChanged() { fun testPrivateMethodSignatureChanged() {
val project = Project("javaUpToDate", GradleVersionRequired.AtLeast("4.3")) val project = Project("javaUpToDate")
project.build("build") { project.build("build") {
assertSuccessful() assertSuccessful()
@@ -16,7 +16,7 @@ open class Kapt3Android32IT : Kapt3AndroidIT() {
get() = AGPVersion.v3_2_0 get() = AGPVersion.v3_2_0
override val defaultGradleVersion: GradleVersionRequired override val defaultGradleVersion: GradleVersionRequired
get() = GradleVersionRequired.AtLeast("4.6") get() = GradleVersionRequired.None
} }
open class Kapt3Android33IT : Kapt3AndroidIT() { open class Kapt3Android33IT : Kapt3AndroidIT() {
@@ -81,7 +81,7 @@ class Kapt3Android31IT : Kapt3AndroidIT() {
// there is a weird validation exception in testICWithAnonymousClasses with 5.0 todo: fix it // there is a weird validation exception in testICWithAnonymousClasses with 5.0 todo: fix it
override val defaultGradleVersion: GradleVersionRequired override val defaultGradleVersion: GradleVersionRequired
get() = GradleVersionRequired.InRange("4.4", "4.10.2") get() = GradleVersionRequired.Until("4.10.2")
} }
open class Kapt3AndroidIT : Kapt3BaseIT() { open class Kapt3AndroidIT : Kapt3BaseIT() {
@@ -46,12 +46,8 @@ class Kapt3WorkersIT : Kapt3IT() {
@Test @Test
fun testJavacIsLoadedOnce() { fun testJavacIsLoadedOnce() {
// todo: actual minimum version is 4.3, but I had some problems. Investigate later.
// todo: consider minimum version for the whole class, with Gradle <4.3 all tests duplicate tests without workers
val gradleVersionRequired = GradleVersionRequired.AtLeast("4.5.1")
val project = val project =
Project("javacIsLoadedOnce", directoryPrefix = "kapt2", gradleVersionRequirement = gradleVersionRequired) Project("javacIsLoadedOnce", directoryPrefix = "kapt2")
project.build("build") { project.build("build") {
assertSuccessful() assertSuccessful()
assertSubstringCount("Loaded com.sun.tools.javac.util.Context from", 1) assertSubstringCount("Loaded com.sun.tools.javac.util.Context from", 1)
@@ -60,10 +56,8 @@ class Kapt3WorkersIT : Kapt3IT() {
@Test @Test
fun testKaptSkipped() { fun testKaptSkipped() {
val gradleVersionRequired = GradleVersionRequired.AtLeast("4.3")
val project = val project =
Project("kaptSkipped", directoryPrefix = "kapt2", gradleVersionRequirement = gradleVersionRequired) Project("kaptSkipped", directoryPrefix = "kapt2")
project.build("build") { project.build("build") {
assertSuccessful() assertSuccessful()
} }
@@ -36,13 +36,7 @@ open class KaptIncrementalIT : BaseGradleIT() {
assertSuccessful() assertSuccessful()
assertTasksExecuted(":kaptGenerateStubsKotlin", ":compileKotlin") assertTasksExecuted(":kaptGenerateStubsKotlin", ":compileKotlin")
assertTasksUpToDate(":kaptKotlin") assertTasksUpToDate(":kaptKotlin")
assertTasksUpToDate(":compileJava")
// compileJava is up-to-date with Gradle >= 4.3, executed otherwise
if (project.testGradleVersionAtLeast("4.3")) {
assertTasksUpToDate(":compileJava")
} else {
assertTasksExecuted(":compileJava")
}
} }
} }
@@ -366,7 +366,7 @@ class KotlinGradleIT : BaseGradleIT() {
@Test @Test
fun testOmittedStdlibVersion() { fun testOmittedStdlibVersion() {
val project = Project("kotlinProject", GradleVersionRequired.AtLeast("4.4")) val project = Project("kotlinProject")
project.setupWorkingDir() project.setupWorkingDir()
File(project.projectDir, "build.gradle").modify { File(project.projectDir, "build.gradle").modify {
it.replace("kotlin-stdlib:\$kotlin_version", "kotlin-stdlib").apply { check(!equals(it)) } + "\n" + """ it.replace("kotlin-stdlib:\$kotlin_version", "kotlin-stdlib").apply { check(!equals(it)) } + "\n" + """
@@ -739,7 +739,7 @@ class KotlinGradleIT : BaseGradleIT() {
@Test @Test
fun testDefaultKotlinVersionIsNotAffectedByTransitiveDependencies() = fun testDefaultKotlinVersionIsNotAffectedByTransitiveDependencies() =
with(Project("simpleProject", GradleVersionRequired.AtLeast("4.4"))) { with(Project("simpleProject")) {
setupWorkingDir() setupWorkingDir()
// Add a dependency with an explicit lower Kotlin version that has a kotlin-stdlib transitive dependency: // Add a dependency with an explicit lower Kotlin version that has a kotlin-stdlib transitive dependency:
gradleBuildScript().appendText("\ndependencies { compile 'org.jetbrains.kotlin:kotlin-reflect:1.2.71' }") gradleBuildScript().appendText("\ndependencies { compile 'org.jetbrains.kotlin:kotlin-reflect:1.2.71' }")
@@ -753,7 +753,7 @@ class KotlinGradleIT : BaseGradleIT() {
@Test @Test
fun testKotlinJvmProjectPublishesKotlinApiDependenciesAsCompile() = fun testKotlinJvmProjectPublishesKotlinApiDependenciesAsCompile() =
with(Project("simpleProject", GradleVersionRequired.AtLeast("4.4"))) { with(Project("simpleProject")) {
setupWorkingDir() setupWorkingDir()
gradleBuildScript().appendText( gradleBuildScript().appendText(
"\n" + """ "\n" + """
@@ -786,11 +786,10 @@ class KotlinGradleIT : BaseGradleIT() {
@Test @Test
fun testNoTaskConfigurationForcing() { fun testNoTaskConfigurationForcing() {
val gradleVersionRequirement = GradleVersionRequired.AtLeast("4.9")
val projects = listOf( val projects = listOf(
Project("simpleProject", gradleVersionRequirement), Project("simpleProject"),
Project("kotlin2JsNoOutputFileProject", gradleVersionRequirement), Project("kotlin2JsNoOutputFileProject"),
Project("sample-app", gradleVersionRequirement, "new-mpp-lib-and-app") Project("sample-app", directoryPrefix = "new-mpp-lib-and-app")
) )
projects.forEach { projects.forEach {
@@ -925,7 +924,7 @@ class KotlinGradleIT : BaseGradleIT() {
@Test @Test
fun testUserDefinedAttributesInSinglePlatformProject() = fun testUserDefinedAttributesInSinglePlatformProject() =
with(Project("multiprojectWithDependency", GradleVersionRequired.AtLeast("4.7"))) { with(Project("multiprojectWithDependency")) {
setupWorkingDir() setupWorkingDir()
gradleBuildScript("projA").appendText( gradleBuildScript("projA").appendText(
"\n" + """ "\n" + """
@@ -52,7 +52,7 @@ fun configure(): NativeTargets {
} }
class NewMultiplatformIT : BaseGradleIT() { class NewMultiplatformIT : BaseGradleIT() {
val gradleVersion = GradleVersionRequired.AtLeast("4.7") val gradleVersion = GradleVersionRequired.None
val nativeHostTargetName = configure().current val nativeHostTargetName = configure().current
val supportedNativeTargets = configure().supported val supportedNativeTargets = configure().supported
@@ -70,17 +70,15 @@ class NewMultiplatformIT : BaseGradleIT() {
@Test @Test
fun testLibAndAppWithGradleKotlinDsl() = doTestLibAndApp( fun testLibAndAppWithGradleKotlinDsl() = doTestLibAndApp(
"sample-lib-gradle-kotlin-dsl", "sample-lib-gradle-kotlin-dsl",
"sample-app-gradle-kotlin-dsl", "sample-app-gradle-kotlin-dsl"
GradleVersionRequired.AtLeast("4.9") // earlier Gradle versions fail at accessors codegen
) )
private fun doTestLibAndApp( private fun doTestLibAndApp(
libProjectName: String, appProjectName: String, libProjectName: String, appProjectName: String
gradleVersionRequired: GradleVersionRequired = gradleVersion
) { ) {
val libProject = transformProjectWithPluginsDsl(libProjectName, gradleVersionRequired, "new-mpp-lib-and-app") val libProject = transformProjectWithPluginsDsl(libProjectName, directoryPrefix = "new-mpp-lib-and-app")
val appProject = transformProjectWithPluginsDsl(appProjectName, gradleVersionRequired, "new-mpp-lib-and-app") val appProject = transformProjectWithPluginsDsl(appProjectName, directoryPrefix = "new-mpp-lib-and-app")
val oldStyleAppProject = Project("sample-old-style-app", gradleVersionRequired, "new-mpp-lib-and-app") val oldStyleAppProject = Project("sample-old-style-app", directoryPrefix = "new-mpp-lib-and-app")
val compileTasksNames = val compileTasksNames =
listOf("Jvm6", "NodeJs", "Metadata", "Wasm32", nativeHostTargetName.capitalize()).map { ":compileKotlin$it" } listOf("Jvm6", "NodeJs", "Metadata", "Wasm32", nativeHostTargetName.capitalize()).map { ":compileKotlin$it" }
@@ -2017,7 +2015,7 @@ class NewMultiplatformIT : BaseGradleIT() {
} }
@Test @Test
fun testSuggestionToEnableMetadata() = with(Project("sample-lib", GradleVersionRequired.AtLeast("4.7"), "new-mpp-lib-and-app")) { fun testSuggestionToEnableMetadata() = with(Project("sample-lib", directoryPrefix = "new-mpp-lib-and-app")) {
build { build {
assertNotContains(GRADLE_NO_METADATA_WARNING) assertNotContains(GRADLE_NO_METADATA_WARNING)
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.gradle.util.testResolveAllConfigurations
import org.junit.Test import org.junit.Test
class VariantAwareDependenciesIT : BaseGradleIT() { class VariantAwareDependenciesIT : BaseGradleIT() {
private val gradleVersion = GradleVersionRequired.AtLeast("4.8") private val gradleVersion = GradleVersionRequired.None
@Test @Test
fun testJvmKtAppResolvesMppLib() { fun testJvmKtAppResolvesMppLib() {
@@ -245,7 +245,7 @@ class VariantAwareDependenciesIT : BaseGradleIT() {
@Test @Test
fun testJvmWithJavaProjectCanBeResolvedInAllConfigurations() = fun testJvmWithJavaProjectCanBeResolvedInAllConfigurations() =
with(Project("new-mpp-jvm-with-java-multi-module", GradleVersionRequired.AtLeast("4.7"))) { with(Project("new-mpp-jvm-with-java-multi-module")) {
testResolveAllConfigurations("app") testResolveAllConfigurations("app")
} }
@@ -19,7 +19,7 @@ class WorkersIT : BaseGradleIT() {
} }
private fun parallelTasksImpl(isParallel: Boolean) = private fun parallelTasksImpl(isParallel: Boolean) =
with(Project("new-mpp-parallel", GradleVersionRequired.AtLeast("4.7"))) { with(Project("new-mpp-parallel")) {
val options = defaultBuildOptions().copy(parallelTasksInProject = isParallel, withDaemon = false) val options = defaultBuildOptions().copy(parallelTasksInProject = isParallel, withDaemon = false)
val traceLoading = "-Dorg.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.trace.loading=true" val traceLoading = "-Dorg.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.trace.loading=true"
build("assemble", traceLoading, options = options) { build("assemble", traceLoading, options = options) {
@@ -17,7 +17,7 @@ import kotlin.test.assertTrue
class KotlinAndroidExtensionIT : BaseGradleIT() { class KotlinAndroidExtensionIT : BaseGradleIT() {
override val defaultGradleVersion: GradleVersionRequired override val defaultGradleVersion: GradleVersionRequired
get() = GradleVersionRequired.AtLeast("4.4") get() = GradleVersionRequired.None
override fun defaultBuildOptions(): BuildOptions { override fun defaultBuildOptions(): BuildOptions {
return super.defaultBuildOptions().copy( return super.defaultBuildOptions().copy(
@@ -17,7 +17,7 @@ import kotlin.test.assertTrue
class KotlinProjectIT : BaseGradleIT() { class KotlinProjectIT : BaseGradleIT() {
override val defaultGradleVersion: GradleVersionRequired override val defaultGradleVersion: GradleVersionRequired
get() = GradleVersionRequired.AtLeast("4.4") get() = GradleVersionRequired.None
override fun defaultBuildOptions(): BuildOptions { override fun defaultBuildOptions(): BuildOptions {
return super.defaultBuildOptions().copy( return super.defaultBuildOptions().copy(
@@ -47,11 +47,7 @@ open class KotlinMultiplatformExtension : KotlinProjectExtension(), KotlinTarget
fun targetFromPreset(preset: KotlinTargetPreset<*>, configure: Closure<*>) = targetFromPreset(preset, preset.name, configure) fun targetFromPreset(preset: KotlinTargetPreset<*>, configure: Closure<*>) = targetFromPreset(preset, preset.name, configure)
internal val rootSoftwareComponent: KotlinSoftwareComponent by lazy { internal val rootSoftwareComponent: KotlinSoftwareComponent by lazy {
if (isGradleVersionAtLeast(4, 7)) { KotlinSoftwareComponentWithCoordinatesAndPublication("kotlin", targets)
KotlinSoftwareComponentWithCoordinatesAndPublication("kotlin", targets)
} else {
KotlinSoftwareComponent("kotlin", targets)
}
} }
} }
@@ -31,7 +31,6 @@ import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.tasks.CompilerPluginOptions import org.jetbrains.kotlin.gradle.tasks.CompilerPluginOptions
import org.jetbrains.kotlin.gradle.tasks.KotlinCompileTaskData import org.jetbrains.kotlin.gradle.tasks.KotlinCompileTaskData
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.gradle.tasks.isWorkerAPISupported
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.io.File import java.io.File
@@ -121,7 +120,7 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
} }
fun Project.isUseWorkerApi(): Boolean { fun Project.isUseWorkerApi(): Boolean {
return isWorkerAPISupported() && hasProperty(USE_WORKER_API) && property(USE_WORKER_API) == "true" return hasProperty(USE_WORKER_API) && property(USE_WORKER_API) == "true"
} }
fun Project.isIncrementalKapt(): Boolean { fun Project.isIncrementalKapt(): Boolean {
@@ -302,12 +301,9 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
val androidOptions = kaptVariantData?.annotationProcessorOptions ?: emptyMap() val androidOptions = kaptVariantData?.annotationProcessorOptions ?: emptyMap()
val apOptionsFromProviders = val apOptionsFromProviders =
if (isGradleVersionAtLeast(4, 6)) kaptVariantData?.annotationProcessorOptionProviders
kaptVariantData?.annotationProcessorOptionProviders ?.flatMap { (it as CommandLineArgumentProvider).asArguments() }
?.flatMap { (it as CommandLineArgumentProvider).asArguments() } .orEmpty()
.orEmpty()
else
emptyList()
val subluginOptionsFromProvidedApOptions = apOptionsFromProviders.map { val subluginOptionsFromProvidedApOptions = apOptionsFromProviders.map {
// Use the internal subplugin option type to exclude them from Gradle input/output checks, as their providers are already // Use the internal subplugin option type to exclude them from Gradle input/output checks, as their providers are already
@@ -394,11 +390,7 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
kaptTask.isIncremental = project.isIncrementalKapt() kaptTask.isIncremental = project.isIncrementalKapt()
if (kaptTask.isIncremental) { if (kaptTask.isIncremental) {
kaptTask.incAptCache = getKaptIncrementalAnnotationProcessingCache() kaptTask.incAptCache = getKaptIncrementalAnnotationProcessingCache()
if (isGradleVersionAtLeast(4, 3)) { kaptTask.localState.register(kaptTask.incAptCache)
kaptTask.localState.register(kaptTask.incAptCache)
} else {
kaptTask.outputs.files(kaptTask.incAptCache).withPropertyName("incrementalAptCache")
}
maybeRegisterTransform(project) maybeRegisterTransform(project)
val classStructure = project.configurations.create("_classStructure${taskName}") val classStructure = project.configurations.create("_classStructure${taskName}")
@@ -522,13 +514,11 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
options.compilerArgs = newCompilerArgs as List<String> options.compilerArgs = newCompilerArgs as List<String>
if (isGradleVersionAtLeast(4, 6)) { // Filter out the argument providers that are related to annotation processing and therefore already used by Kapt.
// Filter out the argument providers that are related to annotation processing and therefore already used by Kapt. // This is done to avoid outputs intersections between Kapt and and javaCompile and make the up-to-date check for
// This is done to avoid outputs intersections between Kapt and and javaCompile and make the up-to-date check for // javaCompile more granular as it does not perform annotation processing:
// javaCompile more granular as it does not perform annotation processing: if (kaptVariantData != null) {
if (kaptVariantData != null) { options.compilerArgumentProviders.removeAll(kaptVariantData.annotationProcessorOptionProviders)
options.compilerArgumentProviders.removeAll(kaptVariantData.annotationProcessorOptionProviders)
}
} }
} }
} }
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.gradle.internal.tasks.TaskWithLocalState
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.gradle.tasks.cacheOnlyIfEnabledForKotlin import org.jetbrains.kotlin.gradle.tasks.cacheOnlyIfEnabledForKotlin
import org.jetbrains.kotlin.gradle.tasks.clearLocalState import org.jetbrains.kotlin.gradle.tasks.clearLocalState
import org.jetbrains.kotlin.gradle.tasks.isBuildCacheSupported
import org.jetbrains.kotlin.gradle.utils.isJavaFile import org.jetbrains.kotlin.gradle.utils.isJavaFile
import java.io.File import java.io.File
import java.util.jar.JarFile import java.util.jar.JarFile
@@ -24,10 +23,8 @@ abstract class KaptTask : ConventionTask(), TaskWithLocalState {
init { init {
cacheOnlyIfEnabledForKotlin() cacheOnlyIfEnabledForKotlin()
if (isBuildCacheSupported()) { val reason = "Caching is disabled for kapt with 'kapt.useBuildCache'"
val reason = "Caching is disabled for kapt with 'kapt.useBuildCache'" outputs.cacheIf(reason) { useBuildCache }
outputs.cacheIf(reason) { useBuildCache }
}
} }
override fun localStateDirectories(): FileCollection = project.files() override fun localStateDirectories(): FileCollection = project.files()
@@ -22,10 +22,7 @@ import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.plugins.MavenPluginConvention import org.gradle.api.plugins.MavenPluginConvention
import org.gradle.api.publish.PublishingExtension import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.tasks.CompileClasspathNormalizer import org.gradle.api.tasks.*
import org.gradle.api.tasks.Delete
import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.Upload
import org.gradle.api.tasks.compile.AbstractCompile import org.gradle.api.tasks.compile.AbstractCompile
import org.gradle.api.tasks.compile.JavaCompile import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.jvm.tasks.Jar import org.gradle.jvm.tasks.Jar
@@ -65,7 +62,7 @@ internal abstract class KotlinSourceSetProcessor<T : AbstractKotlinCompile<*>>(
protected val sourceSetName: String = kotlinCompilation.compilationName protected val sourceSetName: String = kotlinCompilation.compilationName
protected val kotlinTask: TaskHolder<out T> = registerKotlinCompileTask() protected val kotlinTask: TaskProvider<out T> = registerKotlinCompileTask()
protected val javaSourceSet: SourceSet? = (kotlinCompilation as? KotlinWithJavaCompilation<*>)?.javaSourceSet protected val javaSourceSet: SourceSet? = (kotlinCompilation as? KotlinWithJavaCompilation<*>)?.javaSourceSet
@@ -80,7 +77,7 @@ internal abstract class KotlinSourceSetProcessor<T : AbstractKotlinCompile<*>>(
return File(project.buildDir, "classes/kotlin/$targetSubDirectory${kotlinCompilation.compilationName}") return File(project.buildDir, "classes/kotlin/$targetSubDirectory${kotlinCompilation.compilationName}")
} }
private fun registerKotlinCompileTask(): TaskHolder<out T> { private fun registerKotlinCompileTask(): TaskProvider<out T> {
val name = kotlinCompilation.compileKotlinTaskName val name = kotlinCompilation.compileKotlinTaskName
logger.kotlinDebug("Creating kotlin compile task $name") logger.kotlinDebug("Creating kotlin compile task $name")
@@ -91,7 +88,7 @@ internal abstract class KotlinSourceSetProcessor<T : AbstractKotlinCompile<*>>(
return doRegisterTask(project, name) { return doRegisterTask(project, name) {
it.description = taskDescription it.description = taskDescription
it.mapClasspath { kotlinCompilation.compileDependencyFiles } it.mapClasspath { kotlinCompilation.compileDependencyFiles }
kotlinCompilation.output.addClassesDir { project.files(kotlinTask.doGetTask().destinationDir).builtBy(kotlinTask.doGetTask()) } kotlinCompilation.output.addClassesDir { project.files(kotlinTask.get().destinationDir).builtBy(kotlinTask.get()) }
} }
} }
@@ -142,24 +139,20 @@ internal abstract class KotlinSourceSetProcessor<T : AbstractKotlinCompile<*>>(
val expectedClassesTaskName = "${kotlinCompilation.defaultSourceSetName}Classes" val expectedClassesTaskName = "${kotlinCompilation.defaultSourceSetName}Classes"
project.tasks.run { project.tasks.run {
var shouldCreateTask = false var shouldCreateTask = false
if (useLazyTaskConfiguration) { try {
try { named(expectedClassesTaskName)
named(expectedClassesTaskName) } catch (e: UnknownDomainObjectException) {
} catch (e: Exception) { shouldCreateTask = true
shouldCreateTask = true
}
} else {
shouldCreateTask = findByName(expectedClassesTaskName) == null
} }
if (shouldCreateTask) { if (shouldCreateTask) {
registerTask(project, expectedClassesTaskName, IDEClassesTask::class.java) { project.createOrRegisterTask(expectedClassesTaskName, IDEClassesTask::class.java) {
it.dependsOn(getByName(kotlinCompilation.compileAllTaskName)) it.dependsOn(getByName(kotlinCompilation.compileAllTaskName))
} }
} }
} }
} }
protected abstract fun doRegisterTask(project: Project, taskName: String, configureAction: (T) -> (Unit)): TaskHolder<out T> protected abstract fun doRegisterTask(project: Project, taskName: String, configureAction: (T) -> (Unit)): TaskProvider<out T>
} }
internal class Kotlin2JvmSourceSetProcessor( internal class Kotlin2JvmSourceSetProcessor(
@@ -170,7 +163,11 @@ internal class Kotlin2JvmSourceSetProcessor(
) : KotlinSourceSetProcessor<KotlinCompile>( ) : KotlinSourceSetProcessor<KotlinCompile>(
project, tasksProvider, "Compiles the $kotlinCompilation.", kotlinCompilation project, tasksProvider, "Compiles the $kotlinCompilation.", kotlinCompilation
) { ) {
override fun doRegisterTask(project: Project, taskName: String, configureAction: (KotlinCompile)->(Unit)): TaskHolder<out KotlinCompile> = override fun doRegisterTask(
project: Project,
taskName: String,
configureAction: (KotlinCompile) -> (Unit)
): TaskProvider<out KotlinCompile> =
tasksProvider.registerKotlinJVMTask(project, taskName, kotlinCompilation, configureAction) tasksProvider.registerKotlinJVMTask(project, taskName, kotlinCompilation, configureAction)
override fun doTargetSpecificProcessing() { override fun doTargetSpecificProcessing() {
@@ -181,7 +178,7 @@ internal class Kotlin2JvmSourceSetProcessor(
ScriptingGradleSubplugin.configureForSourceSet(project, kotlinCompilation.compilationName) ScriptingGradleSubplugin.configureForSourceSet(project, kotlinCompilation.compilationName)
project.runOnceAfterEvaluated("Kotlin2JvmSourceSetProcessor.doTargetSpecificProcessing", kotlinTask) { project.runOnceAfterEvaluated("Kotlin2JvmSourceSetProcessor.doTargetSpecificProcessing", kotlinTask) {
val kotlinTaskInstance = kotlinTask.doGetTask() val kotlinTaskInstance = kotlinTask.get()
val javaTask = javaSourceSet?.let { project.tasks.findByName(it.compileJavaTaskName) as JavaCompile } val javaTask = javaSourceSet?.let { project.tasks.findByName(it.compileJavaTaskName) as JavaCompile }
val subpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinPluginVersion) val subpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinPluginVersion)
@@ -249,11 +246,13 @@ internal class Kotlin2JsSourceSetProcessor(
project: Project, project: Project,
taskName: String, taskName: String,
configureAction: (Kotlin2JsCompile) -> (Unit) configureAction: (Kotlin2JsCompile) -> (Unit)
): TaskHolder<out Kotlin2JsCompile> = ): TaskProvider<out Kotlin2JsCompile> =
tasksProvider.registerKotlinJSTask(project, taskName, kotlinCompilation, configureAction) tasksProvider.registerKotlinJSTask(project, taskName, kotlinCompilation, configureAction)
override fun doTargetSpecificProcessing() { override fun doTargetSpecificProcessing() {
project.tasks.findByName(kotlinCompilation.compileAllTaskName)!!.dependsOn(kotlinTask.getTaskOrProvider()) project.tasks.named(kotlinCompilation.compileAllTaskName).configure {
it.dependsOn(kotlinTask)
}
registerCleanSourceMapTask() registerCleanSourceMapTask()
@@ -263,7 +262,7 @@ internal class Kotlin2JsSourceSetProcessor(
// outputFile can be set later during the configuration phase, get it only after the phase: // outputFile can be set later during the configuration phase, get it only after the phase:
project.runOnceAfterEvaluated("Kotlin2JsSourceSetProcessor.doTargetSpecificProcessing", kotlinTask) { project.runOnceAfterEvaluated("Kotlin2JsSourceSetProcessor.doTargetSpecificProcessing", kotlinTask) {
val kotlinTaskInstance = kotlinTask.doGetTask() val kotlinTaskInstance = kotlinTask.get()
kotlinTaskInstance.kotlinOptions.outputFile = kotlinTaskInstance.outputFile.absolutePath kotlinTaskInstance.kotlinOptions.outputFile = kotlinTaskInstance.outputFile.absolutePath
val outputDir = kotlinTaskInstance.outputFile.parentFile val outputDir = kotlinTaskInstance.outputFile.parentFile
@@ -291,9 +290,9 @@ internal class Kotlin2JsSourceSetProcessor(
private fun registerCleanSourceMapTask() { private fun registerCleanSourceMapTask() {
val taskName = kotlinCompilation.composeName("clean", "sourceMap") val taskName = kotlinCompilation.composeName("clean", "sourceMap")
registerTask(project, taskName, Delete::class.java) { registerTask(project, taskName, Delete::class.java) {
it.onlyIf { kotlinTask.doGetTask().kotlinOptions.sourceMap } it.onlyIf { kotlinTask.get().kotlinOptions.sourceMap }
it.delete(object : Closure<String>(this) { it.delete(object : Closure<String>(this) {
override fun call(): String? = (kotlinTask.doGetTask().property("outputFile") as File).canonicalPath + ".map" override fun call(): String? = (kotlinTask.get().property("outputFile") as File).canonicalPath + ".map"
}) })
} }
project.tasks.findByName("clean")?.dependsOn(taskName) project.tasks.findByName("clean")?.dependsOn(taskName)
@@ -310,14 +309,14 @@ internal class KotlinCommonSourceSetProcessor(
kotlinCompilation = compilation kotlinCompilation = compilation
) { ) {
override fun doTargetSpecificProcessing() { override fun doTargetSpecificProcessing() {
project.tasks.findByName(kotlinCompilation.compileAllTaskName)!!.dependsOn(kotlinTask.getTaskOrProvider()) project.tasks.findByName(kotlinCompilation.compileAllTaskName)!!.dependsOn(kotlinTask)
// can be missing (e.g. in case of tests) // can be missing (e.g. in case of tests)
if (kotlinCompilation.compilationName == KotlinCompilation.MAIN_COMPILATION_NAME) { if (kotlinCompilation.compilationName == KotlinCompilation.MAIN_COMPILATION_NAME) {
project.tasks.findByName(kotlinCompilation.target.artifactsTaskName)?.dependsOn(kotlinTask.getTaskOrProvider()) project.tasks.findByName(kotlinCompilation.target.artifactsTaskName)?.dependsOn(kotlinTask)
} }
project.runOnceAfterEvaluated("KotlinCommonSourceSetProcessor.doTargetSpecificProcessing", kotlinTask) { project.runOnceAfterEvaluated("KotlinCommonSourceSetProcessor.doTargetSpecificProcessing", kotlinTask) {
val kotlinTaskInstance = kotlinTask.doGetTask() val kotlinTaskInstance = kotlinTask.get()
val subpluginEnvironment: SubpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinPluginVersion) val subpluginEnvironment: SubpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinPluginVersion)
val appliedPlugins = subpluginEnvironment.addSubpluginOptions( val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
project, kotlinTaskInstance, null, null, null, kotlinCompilation project, kotlinTaskInstance, null, null, null, kotlinCompilation
@@ -329,7 +328,11 @@ internal class KotlinCommonSourceSetProcessor(
} }
// protected abstract fun doRegisterTask(project: Project, taskName: String, configureAction: (T) -> (Unit)): TaskHolder<out T> // 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> = override fun doRegisterTask(
project: Project,
taskName: String,
configureAction: (KotlinCompileCommon) -> (Unit)
): TaskProvider<out KotlinCompileCommon> =
tasksProvider.registerKotlinCommonTask(project, taskName, kotlinCompilation, configureAction) tasksProvider.registerKotlinCommonTask(project, taskName, kotlinCompilation, configureAction)
} }
@@ -430,7 +433,7 @@ internal abstract class AbstractKotlinPlugin(
it.jarTask = jarTask it.jarTask = jarTask
it.dependsOn(classesTask) it.dependsOn(classesTask)
} }
jarTask.dependsOn(inspectTask.getTaskOrProvider()) jarTask.dependsOn(inspectTask)
} }
internal fun setUpJavaSourceSets( internal fun setUpJavaSourceSets(
@@ -532,30 +535,21 @@ internal abstract class AbstractKotlinPlugin(
internal fun configureDefaultVersionsResolutionStrategy(project: Project, kotlinPluginVersion: String) { internal fun configureDefaultVersionsResolutionStrategy(project: Project, kotlinPluginVersion: String) {
project.configurations.all { configuration -> project.configurations.all { configuration ->
if (isGradleVersionAtLeast(4, 4)) { fun MutableVersionConstraint.chooseVersion(version: String) {
fun MutableVersionConstraint.chooseVersion(version: String) { if (isGradleVersionAtLeast(5, 0)) {
if (isGradleVersionAtLeast(5, 0)) { // In Gradle 5.0, the semantics of 'prefer' has changed to be much less imperative, and now it's 'require' that we need:
// In Gradle 5.0, the semantics of 'prefer' has changed to be much less imperative, and now it's 'require' that we need: val requireMethod = javaClass.getMethod("require", String::class.java)
val requireMethod = javaClass.getMethod("require", String::class.java) requireMethod(this, version)
requireMethod(this, version) } else {
} else { prefer(version)
prefer(version)
}
} }
}
// Use the API introduced in Gradle 4.4 to modify the dependencies directly before they are resolved: // Use the API introduced in Gradle 4.4 to modify the dependencies directly before they are resolved:
configuration.withDependencies { dependencySet -> configuration.withDependencies { dependencySet ->
dependencySet.filterIsInstance<ExternalDependency>() dependencySet.filterIsInstance<ExternalDependency>()
.filter { it.group == "org.jetbrains.kotlin" && it.version.isNullOrEmpty() } .filter { it.group == "org.jetbrains.kotlin" && it.version.isNullOrEmpty() }
.forEach { it.version { constraint -> constraint.chooseVersion(kotlinPluginVersion) } } .forEach { it.version { constraint -> constraint.chooseVersion(kotlinPluginVersion) } }
}
} else {
configuration.resolutionStrategy.eachDependency { details ->
val requested = details.requested
if (requested.group == "org.jetbrains.kotlin" && requested.version.isNullOrEmpty()) {
details.useVersion(kotlinPluginVersion)
}
}
} }
} }
} }
@@ -995,13 +989,9 @@ internal fun configureJavaTask(kotlinTask: KotlinCompile, javaTask: AbstractComp
// Make Gradle check if the javaTask is up-to-date based on the Kotlin classes // Make Gradle check if the javaTask is up-to-date based on the Kotlin classes
javaTask.inputsCompatible.run { javaTask.inputsCompatible.run {
if (isBuildCacheSupported()) { dir(kotlinTask.destinationDir)
dir(kotlinTask.destinationDir) .withNormalizer(CompileClasspathNormalizer::class.java)
.withNormalizer(CompileClasspathNormalizer::class.java) .withPropertyName("${kotlinTask.name}OutputClasses")
.withPropertyName("${kotlinTask.name}OutputClasses")
} else {
dirCompatible(kotlinTask.destinationDir)
}
} }
// Also, use kapt1 annotations file for up-to-date check since annotation processing is done with javac // Also, use kapt1 annotations file for up-to-date check since annotation processing is done with javac
javaTask.dependsOn(kotlinTask) javaTask.dependsOn(kotlinTask)
@@ -1,29 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.Task
class LegacyTaskHolder<out T : Task>(private val task: T) : TaskHolder<T> {
override val project: Project
get() = task.project
override val name: String
get() = task.name
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}']"
}
}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.logging.Logging import org.gradle.api.logging.Logging
import org.gradle.api.tasks.TaskProvider
/** /**
* This class encapsulated logic which should be invoked during not before the script evaluation is ready and * This class encapsulated logic which should be invoked during not before the script evaluation is ready and
@@ -44,12 +45,12 @@ internal class RunOnceAfterEvaluated(private val name: String, private val actio
} }
} }
internal fun Project.runOnceAfterEvaluated(name: String, task: TaskHolder<*>, action: () -> (Unit)) { internal fun Project.runOnceAfterEvaluated(name: String, task: TaskProvider<*>, action: () -> (Unit)) {
val runOnce = RunOnceAfterEvaluated(name, action) val runOnce = RunOnceAfterEvaluated(name, action)
runOnceAfterEvaluated(runOnce, task) runOnceAfterEvaluated(runOnce, task)
} }
internal fun Project.runOnceAfterEvaluated(runOnce: RunOnceAfterEvaluated, task: TaskHolder<*>) { internal fun Project.runOnceAfterEvaluated(runOnce: RunOnceAfterEvaluated, task: TaskProvider<*>) {
if (state.executed) { if (state.executed) {
runOnce.onEvaluated() runOnce.onEvaluated()
} else { } else {
@@ -1,46 +0,0 @@
/*
* 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<out T : Task> {
val project: Project
val name: String
/**
* 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))
}
@@ -1,39 +0,0 @@
/*
* 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<out T : Task>(
override val name: String,
override val project: Project,
private val provider: TaskProvider<T>
) : TaskHolder<T> {
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']"
}
}
@@ -161,10 +161,6 @@ class KotlinMultiplatformPlugin(
SingleWarningPerBuild.show(project, GRADLE_NO_METADATA_WARNING) SingleWarningPerBuild.show(project, GRADLE_NO_METADATA_WARNING)
} }
if (!isGradleVersionAtLeast(4, 8) && project.multiplatformExtension.isGradleMetadataAvailable) {
SingleWarningPerBuild.show(project, GRADLE_OLD_METADATA_WARNING)
}
val targets = project.multiplatformExtension.targets val targets = project.multiplatformExtension.targets
val kotlinSoftwareComponent = project.multiplatformExtension.rootSoftwareComponent val kotlinSoftwareComponent = project.multiplatformExtension.rootSoftwareComponent
@@ -178,7 +174,7 @@ class KotlinMultiplatformPlugin(
} }
// Publish the root publication only if Gradle metadata publishing is enabled: // Publish the root publication only if Gradle metadata publishing is enabled:
project.tasks.withType(AbstractPublishToMaven::class.java).all { publishTask -> project.tasks.withType(AbstractPublishToMaven::class.java).configureEach { publishTask ->
publishTask.onlyIf { publishTask.publication != rootPublication || project.multiplatformExtension.isGradleMetadataAvailable } publishTask.onlyIf { publishTask.publication != rootPublication || project.multiplatformExtension.isGradleMetadataAvailable }
} }
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import org.jetbrains.kotlin.gradle.plugin.ProjectLocalConfigurations import org.jetbrains.kotlin.gradle.plugin.ProjectLocalConfigurations
open class KotlinSoftwareComponent( abstract class KotlinSoftwareComponent(
private val name: String, private val name: String,
protected val kotlinTargets: Iterable<KotlinTarget> protected val kotlinTargets: Iterable<KotlinTarget>
) : SoftwareComponentInternal, ComponentWithVariants { ) : SoftwareComponentInternal, ComponentWithVariants {
@@ -10,6 +10,7 @@ import org.gradle.api.Project
import org.gradle.api.attributes.AttributeContainer import org.gradle.api.attributes.AttributeContainer
import org.gradle.api.file.FileCollection import org.gradle.api.file.FileCollection
import org.gradle.api.plugins.BasePluginConvention import org.gradle.api.plugins.BasePluginConvention
import org.gradle.api.tasks.TaskProvider
import org.gradle.util.ConfigureUtil import org.gradle.util.ConfigureUtil
import org.jetbrains.kotlin.gradle.dsl.* import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.*
@@ -47,7 +48,7 @@ abstract class AbstractKotlinCompilation<T : KotlinCommonOptions>(
override val compileKotlinTask: KotlinCompile<T> override val compileKotlinTask: KotlinCompile<T>
get() = (target.project.tasks.getByName(compileKotlinTaskName) as KotlinCompile<T>) get() = (target.project.tasks.getByName(compileKotlinTaskName) as KotlinCompile<T>)
val compileKotlinTaskHolder: TaskHolder<KotlinCompile<T>> val compileKotlinTaskHolder: TaskProvider<KotlinCompile<T>>
get() = target.project.locateTask(compileKotlinTaskName)!! get() = target.project.locateTask(compileKotlinTaskName)!!
// Don't declare this property in the constructor to avoid NPE // Don't declare this property in the constructor to avoid NPE
@@ -67,11 +67,7 @@ abstract class AbstractKotlinTarget(
targetName targetName
else PRIMARY_SINGLE_COMPONENT_NAME else PRIMARY_SINGLE_COMPONENT_NAME
val result = if (isGradleVersionAtLeast(4, 7)) { val result = createKotlinVariant(componentName, mainCompilation, usageContexts)
createKotlinVariant(componentName, mainCompilation, usageContexts)
} else {
KotlinVariant(mainCompilation, usageContexts)
}
result.sourcesArtifacts = setOf( result.sourcesArtifacts = setOf(
sourcesJarArtifact(mainCompilation, componentName, dashSeparatedName(targetName.toLowerCase())) sourcesJarArtifact(mainCompilation, componentName, dashSeparatedName(targetName.toLowerCase()))
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.gradle.plugin.sources
import org.gradle.api.InvalidUserDataException import org.gradle.api.InvalidUserDataException
import org.gradle.api.file.FileCollection import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.compile.AbstractCompile import org.gradle.api.tasks.compile.AbstractCompile
import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.gradle.internal.KaptGenerateStubsTask
import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.scripting.ScriptingExtension import org.jetbrains.kotlin.gradle.scripting.ScriptingExtension
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.gradle.tasks.useLazyTaskConfiguration
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
import org.jetbrains.kotlin.scripting.compiler.plugin.impl.reporter import org.jetbrains.kotlin.scripting.compiler.plugin.impl.reporter
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsFromClasspathDiscoverySource import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsFromClasspathDiscoverySource
@@ -81,11 +80,8 @@ class ScriptingGradleSubplugin : Plugin<Project> {
} }
} }
} }
if (useLazyTaskConfiguration) {
project.tasks.withType(KotlinCompile::class.java).configureEach(configureAction) project.tasks.withType(KotlinCompile::class.java).configureEach(configureAction)
} else {
project.tasks.withType(KotlinCompile::class.java, configureAction)
}
} else { } else {
// TODO: implement support for discovery in MPP project: use KotlinSourceSet directly and do not rely on java convevtion sourcesets // TODO: implement support for discovery in MPP project: use KotlinSourceSet directly and do not rely on java convevtion sourcesets
if (project.multiplatformExtensionOrNull == null) { if (project.multiplatformExtensionOrNull == null) {
@@ -129,12 +129,12 @@ class Android25ProjectHandler(
} }
// TODO the return type is actually `AbstractArchiveTask | TaskProvider<out AbstractArchiveTask>`; // TODO the return type is actually `AbstractArchiveTask | TaskProvider<out AbstractArchiveTask>`;
// change the signature once the Gradle versions that don't support task providers (< 4.8) are dropped // change the signature once the Android Gradle plugin versions that don't support task providers are dropped
override fun getLibraryOutputTask(variant: BaseVariant): Any? { override fun getLibraryOutputTask(variant: BaseVariant): Any? {
val getPackageLibraryProvider = variant.javaClass.methods val getPackageLibraryProvider = variant.javaClass.methods
.find { it.name == "getPackageLibraryProvider" && it.parameterCount == 0 } .find { it.name == "getPackageLibraryProvider" && it.parameterCount == 0 }
return if (getPackageLibraryProvider != null && isGradleVersionAtLeast(4, 8)) { return if (getPackageLibraryProvider != null) {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
getPackageLibraryProvider(variant) as TaskProvider<out AbstractArchiveTask> getPackageLibraryProvider(variant) as TaskProvider<out AbstractArchiveTask>
} else { } else {
@@ -94,9 +94,6 @@ open class KotlinAndroidTarget(
// Capture the type parameter T for `AbstractAndroidProjectHandler` // Capture the type parameter T for `AbstractAndroidProjectHandler`
private fun <T> AbstractAndroidProjectHandler<T>.doCreateComponents(): Set<KotlinTargetComponent> { private fun <T> AbstractAndroidProjectHandler<T>.doCreateComponents(): Set<KotlinTargetComponent> {
if (!isGradleVersionAtLeast(4, 7))
return emptySet()
val publishableVariants = mutableListOf<T>() val publishableVariants = mutableListOf<T>()
.apply { forEachVariant(project) { add(it) } } .apply { forEachVariant(project) { add(it) } }
.toList() // Defensive copy against unlikely modification by the lambda that captures the list above in forEachVariant { } .toList() // Defensive copy against unlikely modification by the lambda that captures the list above in forEachVariant { }
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.gradle.targets.js
import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.tasks.TaskProvider
import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.AbstractKotlinTargetConfigurator.Companion.runTaskNameSuffix import org.jetbrains.kotlin.gradle.plugin.AbstractKotlinTargetConfigurator.Companion.runTaskNameSuffix
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
@@ -30,7 +31,7 @@ class KotlinJsTarget(project: Project, platformType: KotlinPlatformType) :
internal set internal set
val testTaskName get() = testRuns.getByName(KotlinTargetWithTests.DEFAULT_TEST_RUN_NAME).testTaskName val testTaskName get() = testRuns.getByName(KotlinTargetWithTests.DEFAULT_TEST_RUN_NAME).testTaskName
val testTask: TaskHolder<KotlinTestReport> val testTask: TaskProvider<KotlinTestReport>
get() = checkNotNull(project.locateTask(testTaskName)) get() = checkNotNull(project.locateTask(testTaskName))
val runTaskName get() = lowerCamelCaseName(disambiguationClassifier, runTaskNameSuffix) val runTaskName get() = lowerCamelCaseName(disambiguationClassifier, runTaskNameSuffix)
@@ -40,8 +40,7 @@ open class KotlinJsTargetConfigurator(kotlinPluginVersion: String) :
} }
} }
@Suppress("UNCHECKED_CAST") result.executionTask = testTask
result.executionTask = testTask.getTaskOrProvider() as TaskProvider<KotlinTestReport>
return result return result
} }
@@ -32,7 +32,7 @@ internal class DukatCompilationResolverPlugin(
it.dependsOn(nodeJs.npmInstallTask, npmProject.packageJsonTask) it.dependsOn(nodeJs.npmInstallTask, npmProject.packageJsonTask)
} }
compilation.compileKotlinTask.dependsOn(task.getTaskOrProvider()) compilation.compileKotlinTask.dependsOn(task)
} }
override fun hookDependencies( override fun hookDependencies(
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.gradle.targets.js.nodejs
import org.gradle.api.tasks.AbstractExecTask import org.gradle.api.tasks.AbstractExecTask
import org.gradle.api.tasks.Input import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Internal import org.gradle.api.tasks.Internal
import org.jetbrains.kotlin.gradle.plugin.TaskHolder import org.gradle.api.tasks.TaskProvider
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency
import org.jetbrains.kotlin.gradle.targets.js.npm.RequiresNpmDependencies import org.jetbrains.kotlin.gradle.targets.js.npm.RequiresNpmDependencies
@@ -53,7 +53,7 @@ open class NodeJsExec : AbstractExecTask<NodeJsExec>(NodeJsExec::class.java), Re
compilation: KotlinJsCompilation, compilation: KotlinJsCompilation,
name: String, name: String,
configuration: NodeJsExec.() -> Unit = {} configuration: NodeJsExec.() -> Unit = {}
): TaskHolder<NodeJsExec> { ): TaskProvider<NodeJsExec> {
val target = compilation.target val target = compilation.target
val project = target.project val project = target.project
val nodeJs = NodeJsRootPlugin.apply(project.rootProject) val nodeJs = NodeJsRootPlugin.apply(project.rootProject)
@@ -74,7 +74,7 @@ internal class KotlinCompilationNpmResolver(
@Synchronized @Synchronized
fun getResolutionOrResolveIfForced(): KotlinCompilationNpmResolution? { fun getResolutionOrResolveIfForced(): KotlinCompilationNpmResolution? {
if (resolution != null) return resolution if (resolution != null) return resolution
if (packageJsonTaskHolder.doGetTask().state.upToDate) return resolve(skipWriting = true) if (packageJsonTaskHolder.get().state.upToDate) return resolve(skipWriting = true)
if (resolver.forceFullResolve && resolution == null) return resolve() if (resolver.forceFullResolve && resolution == null) return resolve()
return null return null
} }
@@ -105,7 +105,7 @@ internal class KotlinProjectNpmResolver(
projectNpmResolver.project.tasks.forEach { task -> projectNpmResolver.project.tasks.forEach { task ->
if (task.enabled && task is RequiresNpmDependencies) { if (task.enabled && task is RequiresNpmDependencies) {
addTaskRequirements(task) addTaskRequirements(task)
task.dependsOn(projectNpmResolver[task.compilation].packageJsonTaskHolder.getTaskOrProvider()) task.dependsOn(projectNpmResolver[task.compilation].packageJsonTaskHolder)
task.dependsOn(projectNpmResolver.resolver.nodeJs.npmInstallTask) task.dependsOn(projectNpmResolver.resolver.nodeJs.npmInstallTask)
} }
} }
@@ -7,11 +7,7 @@ package org.jetbrains.kotlin.gradle.targets.js.npm.tasks
import org.gradle.api.DefaultTask import org.gradle.api.DefaultTask
import org.gradle.api.plugins.BasePlugin import org.gradle.api.plugins.BasePlugin
import org.gradle.api.tasks.Input import org.gradle.api.tasks.*
import org.gradle.api.tasks.Nested
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
import org.jetbrains.kotlin.gradle.plugin.TaskHolder
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
@@ -49,7 +45,7 @@ open class KotlinPackageJsonTask : DefaultTask() {
} }
companion object { companion object {
fun create(compilation: KotlinJsCompilation): TaskHolder<KotlinPackageJsonTask> { fun create(compilation: KotlinJsCompilation): TaskProvider<KotlinPackageJsonTask> {
val target = compilation.target val target = compilation.target
val project = target.project val project = target.project
val npmProject = compilation.npmProject val npmProject = compilation.npmProject
@@ -68,11 +64,11 @@ open class KotlinPackageJsonTask : DefaultTask() {
task.mustRunAfter(rootClean) task.mustRunAfter(rootClean)
} }
npmInstallTask.mustRunAfter(rootClean, packageJsonTask.getTaskOrProvider()) npmInstallTask.mustRunAfter(rootClean, packageJsonTask)
compilation.compileKotlinTask.dependsOn( compilation.compileKotlinTask.dependsOn(
npmInstallTask, npmInstallTask,
packageJsonTask.getTaskOrProvider() packageJsonTask
) )
return packageJsonTask return packageJsonTask
@@ -75,6 +75,6 @@ class KotlinBrowserJs(target: KotlinJsTarget) :
it.outputs.upToDateWhen { false } it.outputs.upToDateWhen { false }
} }
target.runTask.dependsOn(run.getTaskOrProvider()) target.runTask.dependsOn(run)
} }
} }
@@ -93,12 +93,13 @@ abstract class KotlinJsSubTarget(
testJs.configureConventions() testJs.configureConventions()
} }
testRun.executionTask = testJs.getTaskOrProvider() as TaskProvider<KotlinJsTest> testRun.executionTask = testJs
target.testRuns.matching { it.name == testRun.name }.all { parentTestRun -> target.testRuns.matching { it.name == testRun.name }.all { parentTestRun ->
target.project.kotlinTestRegistry.registerTestTask( target.project.kotlinTestRegistry.registerTestTask(
project,
testJs, testJs,
parentTestRun.executionTask.get() parentTestRun.executionTask
) )
} }
@@ -28,6 +28,6 @@ class KotlinNodeJs(target: KotlinJsTarget) :
override fun configureRun(compilation: KotlinJsCompilation) { override fun configureRun(compilation: KotlinJsCompilation) {
val runTaskHolder = NodeJsExec.create(compilation, disambiguateCamelCased("run")) val runTaskHolder = NodeJsExec.create(compilation, disambiguateCamelCased("run"))
target.runTask.dependsOn(runTaskHolder.getTaskOrProvider()) target.runTask.dependsOn(runTaskHolder)
} }
} }
@@ -33,7 +33,7 @@ class KotlinJvmTargetConfigurator(kotlinPluginVersion: String) :
testTask.project.tasks.findByName(JavaBasePlugin.CHECK_TASK_NAME)?.dependsOn(testTask) testTask.project.tasks.findByName(JavaBasePlugin.CHECK_TASK_NAME)?.dependsOn(testTask)
} }
executionTask = testTaskOrProvider.getTaskOrProvider() as TaskProvider<KotlinJvmTest> executionTask = testTaskOrProvider
val testCompilation = target.compilations.getByName(KotlinCompilation.TEST_COMPILATION_NAME) val testCompilation = target.compilations.getByName(KotlinCompilation.TEST_COMPILATION_NAME)
@@ -47,7 +47,7 @@ class KotlinJvmTargetConfigurator(kotlinPluginVersion: String) :
} }
} }
target.project.kotlinTestRegistry.registerTestTask(testTaskOrProvider) target.project.kotlinTestRegistry.registerTestTask(target.project, testTaskOrProvider)
} }
override fun buildCompilationProcessor(compilation: KotlinJvmCompilation): KotlinSourceSetProcessor<*> { override fun buildCompilationProcessor(compilation: KotlinJvmCompilation): KotlinSourceSetProcessor<*> {
@@ -11,6 +11,7 @@ import org.gradle.api.attributes.Usage
import org.gradle.api.file.FileCollection import org.gradle.api.file.FileCollection
import org.gradle.api.internal.component.SoftwareComponentInternal import org.gradle.api.internal.component.SoftwareComponentInternal
import org.gradle.api.plugins.BasePlugin import org.gradle.api.plugins.BasePlugin
import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.bundling.Jar import org.gradle.api.tasks.bundling.Jar
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
@@ -132,7 +133,7 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
} }
sourceSetsWithMetadataCompilations.forEach { (sourceSet, metadataCompilation) -> sourceSetsWithMetadataCompilations.forEach { (sourceSet, metadataCompilation) ->
val compileMetadataTransformationTasksForHierarchy = mutableSetOf<TaskHolder<TransformKotlinGranularMetadata>>() val compileMetadataTransformationTasksForHierarchy = mutableSetOf<TaskProvider<TransformKotlinGranularMetadata>>()
// Adjust metadata compilation to support source set hierarchies, i.e. use both the outputs of dependsOn source set compilation // Adjust metadata compilation to support source set hierarchies, i.e. use both the outputs of dependsOn source set compilation
// and their dependencies metadata transformed for compilation: // and their dependencies metadata transformed for compilation:
@@ -156,8 +157,8 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
val generateMetadata = createGenerateProjectStructureMetadataTask() val generateMetadata = createGenerateProjectStructureMetadataTask()
allMetadataJar.from(project.files(Callable { allMetadataJar.from(project.files(Callable {
generateMetadata.doGetTask().resultXmlFile generateMetadata.get().resultXmlFile
}).builtBy(generateMetadata.getTaskOrProvider())) { spec -> }).builtBy(generateMetadata)) { spec ->
spec.into("META-INF").rename { MULTIPLATFORM_PROJECT_METADATA_FILE_NAME } spec.into("META-INF").rename { MULTIPLATFORM_PROJECT_METADATA_FILE_NAME }
} }
} }
@@ -286,13 +287,13 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
private fun createTransformedMetadataClasspath( private fun createTransformedMetadataClasspath(
fromFiles: Iterable<File>, fromFiles: Iterable<File>,
project: Project, project: Project,
transformationTaskHolders: Set<TaskHolder<TransformKotlinGranularMetadata>> transformationTaskHolders: Set<TaskProvider<TransformKotlinGranularMetadata>>
): FileCollection { ): FileCollection {
return project.files(Callable { return project.files(Callable {
val allResolutionsByArtifactFile: Map<File, Iterable<MetadataDependencyResolution>> = val allResolutionsByArtifactFile: Map<File, Iterable<MetadataDependencyResolution>> =
mutableMapOf<File, MutableList<MetadataDependencyResolution>>().apply { mutableMapOf<File, MutableList<MetadataDependencyResolution>>().apply {
transformationTaskHolders.forEach { transformationTaskHolders.forEach {
val resolutions = it.doGetTask().metadataDependencyResolutions val resolutions = it.get().metadataDependencyResolutions
resolutions.forEach { resolution -> resolutions.forEach { resolution ->
val artifacts = resolution.dependency.moduleArtifacts.map { it.file } val artifacts = resolution.dependency.moduleArtifacts.map { it.file }
@@ -305,7 +306,7 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
} }
val transformedFilesByResolution: Map<MetadataDependencyResolution, FileCollection> = val transformedFilesByResolution: Map<MetadataDependencyResolution, FileCollection> =
transformationTaskHolders.flatMap { it.doGetTask().filesByResolution.toList() }.toMap() transformationTaskHolders.flatMap { it.get().filesByResolution.toList() }.toMap()
mutableSetOf<Any /* File | FileCollection */>().apply { mutableSetOf<Any /* File | FileCollection */>().apply {
fromFiles.forEach { file -> fromFiles.forEach { file ->
@@ -324,7 +325,7 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
} }
} }
} }
}).builtBy(transformationTaskHolders.map { it.getTaskOrProvider() }) }).builtBy(transformationTaskHolders)
} }
private fun getPublishedCommonSourceSets(project: Project): Set<KotlinSourceSet> { private fun getPublishedCommonSourceSets(project: Project): Set<KotlinSourceSet> {
@@ -346,7 +347,7 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
.keys .keys
} }
private fun Project.createGenerateProjectStructureMetadataTask(): TaskHolder<GenerateProjectStructureMetadata> = private fun Project.createGenerateProjectStructureMetadataTask(): TaskProvider<GenerateProjectStructureMetadata> =
project.createOrRegisterTask("generateProjectStructureMetadata") { task -> project.createOrRegisterTask("generateProjectStructureMetadata") { task ->
task.lazyKotlinProjectStructureMetadata = lazy { checkNotNull(buildKotlinProjectStructureMetadata(project)) } task.lazyKotlinProjectStructureMetadata = lazy { checkNotNull(buildKotlinProjectStructureMetadata(project)) }
} }
@@ -9,10 +9,7 @@ package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.Project import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.KotlinOnlyTargetConfigurator
import org.jetbrains.kotlin.gradle.plugin.sources.applyLanguageSettingsToKotlinTask import org.jetbrains.kotlin.gradle.plugin.sources.applyLanguageSettingsToKotlinTask
import org.jetbrains.kotlin.gradle.targets.metadata.KotlinMetadataTargetConfigurator import org.jetbrains.kotlin.gradle.targets.metadata.KotlinMetadataTargetConfigurator
@@ -49,9 +46,9 @@ class KotlinMetadataTargetPreset(
mainCompilation.source(commonMainSourceSet) mainCompilation.source(commonMainSourceSet)
project.afterEvaluate { project.whenEvaluated {
// Since there's no default source set, apply language settings from commonMain: // Since there's no default source set, apply language settings from commonMain:
val compileKotlinMetadata = project.tasks.getByName(mainCompilation.compileKotlinTaskName) as KotlinCompile<*> val compileKotlinMetadata = mainCompilation.compileKotlinTask
applyLanguageSettingsToKotlinTask(commonMainSourceSet.languageSettings, compileKotlinMetadata) applyLanguageSettingsToKotlinTask(commonMainSourceSet.languageSettings, compileKotlinMetadata)
} }
} }
@@ -29,12 +29,9 @@ open class KotlinNativeTarget(
attributes.attribute(konanTargetAttribute, konanTarget.name) attributes.attribute(konanTargetAttribute, konanTarget.name)
} }
val binaries = if(isGradleVersionAtLeast(4, 2)) { val binaries =
// Use newInstance to allow accessing binaries by their names in Groovy using the extension mechanism. // Use newInstance to allow accessing binaries by their names in Groovy using the extension mechanism.
project.objects.newInstance(KotlinNativeBinaryContainer::class.java, this, WrapUtil.toDomainObjectSet(NativeBinary::class.java)) project.objects.newInstance(KotlinNativeBinaryContainer::class.java, this, WrapUtil.toDomainObjectSet(NativeBinary::class.java))
} else {
KotlinNativeBinaryContainer(this, WrapUtil.toDomainObjectSet(NativeBinary::class.java))
}
fun binaries(configure: KotlinNativeBinaryContainer.() -> Unit) { fun binaries(configure: KotlinNativeBinaryContainer.() -> Unit) {
binaries.configure() binaries.configure()
@@ -412,11 +412,10 @@ class KotlinNativeTargetWithTestsConfigurator(kotlinPluginVersion: String)
testTask.configureConventions() testTask.configureConventions()
} }
@Suppress("UNCHECKED_CAST") executionTask = testTaskOrProvider
executionTask = testTaskOrProvider.getTaskOrProvider() as TaskProvider<KotlinNativeTest>
setExecutionSourceFrom(target.binaries.getTest(NativeBuildType.DEBUG)) setExecutionSourceFrom(target.binaries.getTest(NativeBuildType.DEBUG))
project.kotlinTestRegistry.registerTestTask(testTaskOrProvider) project.kotlinTestRegistry.registerTestTask(project, testTaskOrProvider)
} }
} }
@@ -20,24 +20,11 @@ import org.gradle.api.Task
import org.gradle.util.GradleVersion import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.utils.outputsCompatible import org.jetbrains.kotlin.gradle.utils.outputsCompatible
internal fun isBuildCacheSupported(): Boolean =
gradleVersion >= GradleVersion.version("4.3")
internal fun isWorkerAPISupported(): Boolean =
gradleVersion >= GradleVersion.version("4.3")
internal fun isBuildCacheEnabledForKotlin(): Boolean = internal fun isBuildCacheEnabledForKotlin(): Boolean =
isBuildCacheSupported() && System.getProperty(KOTLIN_CACHING_ENABLED_PROPERTY)?.toBoolean() ?: true
System.getProperty(KOTLIN_CACHING_ENABLED_PROPERTY)?.toBoolean() ?: true
internal fun <T : Task> T.cacheOnlyIfEnabledForKotlin() { internal fun <T : Task> T.cacheOnlyIfEnabledForKotlin() {
// The `cacheIf` method may be missing if the Gradle version is too low: outputsCompatible.cacheIf { isBuildCacheEnabledForKotlin() }
try {
outputsCompatible.cacheIf { isBuildCacheEnabledForKotlin() }
} catch (_: NoSuchMethodError) {
}
} }
private val gradleVersion = GradleVersion.current()
private const val KOTLIN_CACHING_ENABLED_PROPERTY = "kotlin.caching.enabled" private const val KOTLIN_CACHING_ENABLED_PROPERTY = "kotlin.caching.enabled"
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.gradle.tasks
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.Task import org.gradle.api.Task
import org.gradle.api.UnknownTaskException import org.gradle.api.UnknownTaskException
import org.gradle.api.tasks.TaskProvider
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinCompilation
@@ -26,73 +27,46 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.defaultSourceSetName
import org.jetbrains.kotlin.gradle.plugin.sources.applyLanguageSettingsToKotlinTask import org.jetbrains.kotlin.gradle.plugin.sources.applyLanguageSettingsToKotlinTask
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
internal val useLazyTaskConfiguration = org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast(4, 9)
internal val canLocateTask = org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast(5, 0)
/** /**
* Registers the task with [name] and [type] and initialization script [body] * Registers the task with [name] and [type] and initialization script [body]
* If Gradle with version <4.9 is used the task will be created
*/ */
@JvmName("registerTaskOld") @JvmName("registerTaskOld")
@Deprecated("please use Project.createOrRegisterTask", ReplaceWith("project.createOrRegisterTask(name, body)")) @Deprecated("please use Project.createOrRegisterTask", ReplaceWith("project.createOrRegisterTask(name, body)"))
internal fun <T : Task> registerTask(project: Project, name: String, type: Class<T>, body: (T) -> (Unit)): TaskHolder<T> = internal fun <T : Task> registerTask(project: Project, name: String, type: Class<T>, body: (T) -> (Unit)): TaskProvider<T> =
project.createOrRegisterTask(name, type, emptyList(), body) project.createOrRegisterTask(name, type, emptyList(), body)
internal inline fun <reified T : Task> Project.createOrRegisterTask( internal inline fun <reified T : Task> Project.createOrRegisterTask(
name: String, name: String,
args: List<Any> = emptyList(), args: List<Any> = emptyList(),
noinline body: (T) -> (Unit) noinline body: (T) -> (Unit)
): TaskHolder<T> = ): TaskProvider<T> =
createOrRegisterTask(name, T::class.java, args, body) createOrRegisterTask(name, T::class.java, args, body)
internal fun <T : Task> Project.createOrRegisterTask( internal fun <T : Task> Project.createOrRegisterTask(
name: String, name: String,
type: Class<T>, type: Class<T>,
constructorArgs: List<Any> = emptyList(), // note: args are only allowed with Gradle 4.7+ constructorArgs: List<Any> = emptyList(),
body: (T) -> (Unit) body: (T) -> (Unit)
): TaskHolder<T> { ): TaskProvider<T> {
return if (useLazyTaskConfiguration) { return project.tasks.register(name, type, *constructorArgs.toTypedArray()).apply { configure(body) }
val provider = project.tasks.register(name, type, *constructorArgs.toTypedArray()).apply { configure(body) }
TaskProviderHolder(name, project, provider)
} else {
val result = LegacyTaskHolder(if (constructorArgs.isEmpty()) {
project.tasks.create(name, type)
} else {
if (!isGradleVersionAtLeast(4, 7)) {
error("Cannot inject the arguments list into a task. This requires Gradle 4.7+.")
}
project.tasks.create(name, type, *constructorArgs.toTypedArray())
})
with(result.doGetTask(), body)
result
}
} }
/** /**
* Locates a task by [name] and [type], without triggering its creation or configuration. * Locates a task by [name] and [type], without triggering its creation or configuration.
*/ */
internal inline fun <reified T : Task> Project.locateTask(name: String): TaskHolder<T>? = internal inline fun <reified T : Task> Project.locateTask(name: String): TaskProvider<T>? =
if (canLocateTask) { try {
try { tasks.withType(T::class.java).named(name)
TaskProviderHolder(name, this, tasks.named(name, T::class.java)) } catch (e: UnknownTaskException) {
} catch (e: UnknownTaskException) { null
null
}
} else {
tasks.findByName(name)?.let {
check(T::class.java.isInstance(it))
@Suppress("UNCHECKED_CAST")
LegacyTaskHolder(it as T)
}
} }
/** /**
* Locates a task by [name] and [type], without triggering its creation or configuration or registers new task * Locates a task by [name] and [type], without triggering its creation or configuration or registers new task
* with [name], type [T] and initialization script [body] * with [name], type [T] and initialization script [body]
*/ */
internal inline fun <reified T : Task> Project.locateOrRegisterTask(name: String, noinline body: (T) -> (Unit)): TaskHolder<T> { internal inline fun <reified T : Task> Project.locateOrRegisterTask(name: String, noinline body: (T) -> (Unit)): TaskProvider<T> {
return project.locateTask(name) ?: registerTask(project, name, T::class.java, body) return project.locateTask(name) ?: registerTask(project, name, T::class.java, body)
} }
@@ -102,7 +76,7 @@ internal open class KotlinTasksProvider(val targetName: String) {
name: String, name: String,
compilation: AbstractKotlinCompilation<*>, compilation: AbstractKotlinCompilation<*>,
configureAction: (KotlinCompile) -> (Unit) configureAction: (KotlinCompile) -> (Unit)
): TaskHolder<out KotlinCompile> { ): TaskProvider<out KotlinCompile> {
val properties = PropertiesProvider(project) val properties = PropertiesProvider(project)
val taskClass = taskOrWorkersTask<KotlinCompile, KotlinCompileWithWorkers>(properties) val taskClass = taskOrWorkersTask<KotlinCompile, KotlinCompileWithWorkers>(properties)
val result = registerTask(project, name, taskClass) { val result = registerTask(project, name, taskClass) {
@@ -117,10 +91,10 @@ internal open class KotlinTasksProvider(val targetName: String) {
name: String, name: String,
compilation: AbstractKotlinCompilation<*>, compilation: AbstractKotlinCompilation<*>,
configureAction: (Kotlin2JsCompile) -> Unit configureAction: (Kotlin2JsCompile) -> Unit
): TaskHolder<Kotlin2JsCompile> { ): TaskProvider<out Kotlin2JsCompile> {
val properties = PropertiesProvider(project) val properties = PropertiesProvider(project)
val taskClass = taskOrWorkersTask<Kotlin2JsCompile, Kotlin2JsCompileWithWorkers>(properties) val taskClass = taskOrWorkersTask<Kotlin2JsCompile, Kotlin2JsCompileWithWorkers>(properties)
val result = registerTask(project, name, taskClass) { val result = project.createOrRegisterTask(name, taskClass) {
configureAction(it) configureAction(it)
} }
configure(result, project, properties, compilation) configure(result, project, properties, compilation)
@@ -132,10 +106,10 @@ internal open class KotlinTasksProvider(val targetName: String) {
name: String, name: String,
compilation: AbstractKotlinCompilation<*>, compilation: AbstractKotlinCompilation<*>,
configureAction: (KotlinCompileCommon) -> (Unit) configureAction: (KotlinCompileCommon) -> (Unit)
): TaskHolder<KotlinCompileCommon> { ): TaskProvider<out KotlinCompileCommon> {
val properties = PropertiesProvider(project) val properties = PropertiesProvider(project)
val taskClass = taskOrWorkersTask<KotlinCompileCommon, KotlinCompileCommonWithWorkers>(properties) val taskClass = taskOrWorkersTask<KotlinCompileCommon, KotlinCompileCommonWithWorkers>(properties)
val result = registerTask(project, name, taskClass) { val result = project.createOrRegisterTask(name, taskClass) {
configureAction(it) configureAction(it)
} }
configure(result, project, properties, compilation) configure(result, project, properties, compilation)
@@ -143,25 +117,23 @@ internal open class KotlinTasksProvider(val targetName: String) {
} }
open fun configure( open fun configure(
kotlinTaskHolder: TaskHolder<AbstractKotlinCompile<*>>, kotlinTaskHolder: TaskProvider<out AbstractKotlinCompile<*>>,
project: Project, project: Project,
propertiesProvider: PropertiesProvider, propertiesProvider: PropertiesProvider,
compilation: AbstractKotlinCompilation<*> compilation: AbstractKotlinCompilation<*>
) { ) {
val configureAfterEvaluated = RunOnceAfterEvaluated("TaskProvider.configure") {
val languageSettings = project.kotlinExtension.sourceSets.findByName(compilation.defaultSourceSetName)?.languageSettings
?: return@RunOnceAfterEvaluated
val kotlinTask = kotlinTaskHolder.doGetTask()
kotlinTask as org.jetbrains.kotlin.gradle.dsl.KotlinCompile<*>
applyLanguageSettingsToKotlinTask(languageSettings, kotlinTask)
}
kotlinTaskHolder.configure { kotlinTaskHolder.configure {
it.friendTaskName = taskToFriendTaskMapper[it] it.friendTaskName = taskToFriendTaskMapper[it]
propertiesProvider.mapKotlinTaskProperties(it)
configureAfterEvaluated.onConfigure()
} }
project.runOnceAfterEvaluated(configureAfterEvaluated, kotlinTaskHolder)
project.runOnceAfterEvaluated("apply properties and language settings to ${kotlinTaskHolder.name}", kotlinTaskHolder) {
propertiesProvider.mapKotlinTaskProperties(kotlinTaskHolder.get())
applyLanguageSettingsToKotlinTask(
compilation.defaultSourceSet.languageSettings,
kotlinTaskHolder.get() as org.jetbrains.kotlin.gradle.dsl.KotlinCompile<*>
)
}
} }
protected open val taskToFriendTaskMapper: TaskToFriendTaskMapper = protected open val taskToFriendTaskMapper: TaskToFriendTaskMapper =
@@ -176,7 +148,7 @@ internal class AndroidTasksProvider(targetName: String) : KotlinTasksProvider(ta
RegexTaskToFriendTaskMapper.Android(targetName) RegexTaskToFriendTaskMapper.Android(targetName)
override fun configure( override fun configure(
kotlinTaskHolder: TaskHolder<AbstractKotlinCompile<*>>, kotlinTaskHolder: TaskProvider<out AbstractKotlinCompile<*>>,
project: Project, project: Project,
propertiesProvider: PropertiesProvider, propertiesProvider: PropertiesProvider,
compilation: AbstractKotlinCompilation<*> compilation: AbstractKotlinCompilation<*>
@@ -10,6 +10,7 @@ import org.gradle.api.execution.TaskExecutionGraph
import org.gradle.api.tasks.Input import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Internal import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.testing.* import org.gradle.api.tasks.testing.*
import org.jetbrains.kotlin.gradle.internal.testing.KotlinTestRunnerListener import org.jetbrains.kotlin.gradle.internal.testing.KotlinTestRunnerListener
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
@@ -41,12 +42,12 @@ import java.net.URI
*/ */
open class KotlinTestReport : TestReport() { open class KotlinTestReport : TestReport() {
@Internal @Internal
val testTasks = mutableListOf<AbstractTestTask>() val testTasks = mutableListOf<TaskProvider<out AbstractTestTask>>()
private var parent: KotlinTestReport? = null private var parent: KotlinTestReport? = null
@Internal @Internal
val children = mutableListOf<KotlinTestReport>() val children = mutableListOf<TaskProvider<KotlinTestReport>>()
private val projectProperties = PropertiesProvider(project) private val projectProperties = PropertiesProvider(project)
@@ -61,7 +62,7 @@ open class KotlinTestReport : TestReport() {
private var hasOwnFailedTests = false private var hasOwnFailedTests = false
private val hasFailedTests: Boolean private val hasFailedTests: Boolean
get() = hasOwnFailedTests || children.any { it.hasFailedTests } get() = hasOwnFailedTests || children.map { it.get() }.any { it.hasFailedTests }
private val ownSuppressedRunningFailures = mutableListOf<Pair<KotlinTest, Error>>() private val ownSuppressedRunningFailures = mutableListOf<Pair<KotlinTest, Error>>()
@@ -82,15 +83,19 @@ open class KotlinTestReport : TestReport() {
} }
} }
fun addChild(child: KotlinTestReport) { fun addChild(childProvider: TaskProvider<KotlinTestReport>) {
val child = childProvider.get()
check(child.parent == null) { "$child already registers as child of ${child.parent}" } check(child.parent == null) { "$child already registers as child of ${child.parent}" }
child.parent = this child.parent = this
children.add(child) children.add(childProvider)
reportOnChildTasks(child) reportOnChildTasks(childProvider)
} }
private fun reportOnChildTasks(child: KotlinTestReport) { private fun reportOnChildTasks(childProvider: TaskProvider<KotlinTestReport>): Unit {
val child = childProvider.get()
child.testTasks.forEach { child.testTasks.forEach {
reportOn(it) reportOn(it)
} }
@@ -99,8 +104,11 @@ open class KotlinTestReport : TestReport() {
} }
} }
fun registerTestTask(task: AbstractTestTask) { fun registerTestTask(taskProvider: TaskProvider<out AbstractTestTask>) {
testTasks.add(task) testTasks.add(taskProvider)
val task = taskProvider.get()
task.addTestListener(failedTestsListener) task.addTestListener(failedTestsListener)
if (task is KotlinTest) task.addRunListener(object : KotlinTestRunnerListener { if (task is KotlinTest) task.addRunListener(object : KotlinTestRunnerListener {
override fun runningFailure(failure: Error) { override fun runningFailure(failure: Error) {
@@ -165,7 +173,7 @@ open class KotlinTestReport : TestReport() {
} }
report.children.forEach { report.children.forEach {
visitSuppressedRunningFailures(it) visitSuppressedRunningFailures(it.get())
} }
} }
@@ -227,13 +235,17 @@ open class KotlinTestReport : TestReport() {
disableTestReporting(it) disableTestReporting(it)
} }
children.forEach { children.forEach { child ->
it.checkFailedTests = false child.configure {
it.disableIndividualTestTaskReportingAndFailing() it.checkFailedTests = false
it.disableIndividualTestTaskReportingAndFailing()
}
} }
} }
private fun disableTestReporting(task: AbstractTestTask) { private fun disableTestReporting(taskProvider: TaskProvider<out AbstractTestTask>) {
val task = taskProvider.get()
task.ignoreFailures = true task.ignoreFailures = true
if (task is KotlinTest) { if (task is KotlinTest) {
task.ignoreRunFailures = true task.ignoreRunFailures = true
@@ -8,9 +8,9 @@ package org.jetbrains.kotlin.gradle.testing.internal
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.Task import org.gradle.api.Task
import org.gradle.api.plugins.JavaBasePlugin import org.gradle.api.plugins.JavaBasePlugin
import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.testing.AbstractTestTask import org.gradle.api.tasks.testing.AbstractTestTask
import org.gradle.language.base.plugins.LifecycleBasePlugin import org.gradle.language.base.plugins.LifecycleBasePlugin
import org.jetbrains.kotlin.gradle.plugin.TaskHolder
import org.jetbrains.kotlin.gradle.tasks.createOrRegisterTask import org.jetbrains.kotlin.gradle.tasks.createOrRegisterTask
import org.jetbrains.kotlin.gradle.tasks.locateTask import org.jetbrains.kotlin.gradle.tasks.locateTask
@@ -19,27 +19,28 @@ import org.jetbrains.kotlin.gradle.tasks.locateTask
* See [KotlinTestReport] for more details about aggregated test tasks. * See [KotlinTestReport] for more details about aggregated test tasks.
*/ */
class KotlinTestsRegistry(val project: Project, val allTestsTaskName: String = "allTests") { class KotlinTestsRegistry(val project: Project, val allTestsTaskName: String = "allTests") {
val allTestsTask: TaskHolder<KotlinTestReport> val allTestsTask: TaskProvider<KotlinTestReport>
get() = doGetOrCreateAggregatedTestTask( get() = doGetOrCreateAggregatedTestTask(
name = allTestsTaskName, name = allTestsTaskName,
description = "Runs the tests for all targets and create aggregated report" description = "Runs the tests for all targets and create aggregated report"
) { ) {
project.tasks.maybeCreate(LifecycleBasePlugin.CHECK_TASK_NAME) project.tasks.maybeCreate(LifecycleBasePlugin.CHECK_TASK_NAME)
.dependsOn(it.getTaskOrProvider()) .dependsOn(it)
} }
fun registerTestTask( fun registerTestTask(
taskHolder: TaskHolder<AbstractTestTask>, project: Project,
aggregate: KotlinTestReport = allTestsTask.doGetTask() taskHolder: TaskProvider<out AbstractTestTask>,
aggregate: TaskProvider<KotlinTestReport> = allTestsTask
) { ) {
val project = taskHolder.project
project.tasks.getByName(LifecycleBasePlugin.CHECK_TASK_NAME).dependsOn(taskHolder.name) project.tasks.getByName(LifecycleBasePlugin.CHECK_TASK_NAME).dependsOn(taskHolder.name)
project.cleanAllTestTask.dependsOn(cleanTaskName(taskHolder.name)) project.cleanAllTestTask.dependsOn(cleanTaskName(taskHolder.name))
aggregate.dependsOn(taskHolder.name) aggregate.configure {
it.dependsOn(taskHolder.name)
it.registerTestTask(taskHolder)
}
taskHolder.configure { task -> taskHolder.configure { task ->
aggregate.registerTestTask(task)
ijListenTestTask(task) ijListenTestTask(task)
} }
} }
@@ -47,25 +48,25 @@ class KotlinTestsRegistry(val project: Project, val allTestsTaskName: String = "
fun getOrCreateAggregatedTestTask( fun getOrCreateAggregatedTestTask(
name: String, name: String,
description: String, description: String,
parent: TaskHolder<KotlinTestReport>? = allTestsTask parent: TaskProvider<KotlinTestReport>? = allTestsTask
): TaskHolder<KotlinTestReport> { ): TaskProvider<KotlinTestReport> {
if (name == parent?.name) return parent if (name == parent?.name) return parent
return doGetOrCreateAggregatedTestTask(name, description, parent?.doGetTask()) return doGetOrCreateAggregatedTestTask(name, description, parent)
} }
private fun doGetOrCreateAggregatedTestTask( private fun doGetOrCreateAggregatedTestTask(
name: String, name: String,
description: String, description: String,
parent: KotlinTestReport? = null, parent: TaskProvider<KotlinTestReport>? = null,
configure: (TaskHolder<KotlinTestReport>) -> Unit = {} configure: (TaskProvider<KotlinTestReport>) -> Unit = {}
): TaskHolder<KotlinTestReport> { ): TaskProvider<KotlinTestReport> {
val existed = project.locateTask<KotlinTestReport>(name) val existed = project.locateTask<KotlinTestReport>(name)
if (existed != null) return existed if (existed != null) return existed
val reportName = name val reportName = name
val aggregate: TaskHolder<KotlinTestReport> = project.createOrRegisterTask(name) { aggregate -> val aggregate: TaskProvider<KotlinTestReport> = project.createOrRegisterTask(name) { aggregate ->
aggregate.description = description aggregate.description = description
aggregate.group = JavaBasePlugin.VERIFICATION_GROUP aggregate.group = JavaBasePlugin.VERIFICATION_GROUP
@@ -78,11 +79,12 @@ class KotlinTestsRegistry(val project: Project, val allTestsTaskName: String = "
project.gradle.taskGraph.whenReady { graph -> project.gradle.taskGraph.whenReady { graph ->
aggregate.maybeOverrideReporting(graph) aggregate.maybeOverrideReporting(graph)
} }
parent?.addChild(aggregate)
} }
parent?.dependsOn(aggregate.getTaskOrProvider()) parent?.configure {
it.addChild(aggregate)
it.dependsOn(aggregate)
}
configure(aggregate) configure(aggregate)
@@ -51,7 +51,7 @@ internal fun TaskInputs.dirCompatible(dirPath: Any) {
inputsDirMethod(this, dirPath) inputsDirMethod(this, dirPath)
} }
internal fun checkGradleCompatibility(minSupportedVersion: GradleVersion = GradleVersion.version("4.3")) { internal fun checkGradleCompatibility(minSupportedVersion: GradleVersion = GradleVersion.version("4.9")) {
val currentVersion = GradleVersion.current() val currentVersion = GradleVersion.current()
if (currentVersion < minSupportedVersion) { if (currentVersion < minSupportedVersion) {
throw GradleException( throw GradleException(