diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/ConfigurationAvoidanceIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/ConfigurationAvoidanceIT.kt index 607c7578a4e..eed0fdcbbbb 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/ConfigurationAvoidanceIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/ConfigurationAvoidanceIT.kt @@ -27,8 +27,7 @@ class ConfigurationAvoidanceIT : KGPBaseTest() { @JvmGradlePluginTests @GradleTestVersions( - maxVersion = TestVersions.Gradle.G_7_5, - additionalVersions = [TestVersions.Gradle.G_7_3, TestVersions.Gradle.G_7_4] + additionalVersions = [TestVersions.Gradle.G_7_3] ) @DisplayName("KGP/Jvm does not eagerly configure any tasks") @GradleTest @@ -49,6 +48,29 @@ class ConfigurationAvoidanceIT : KGPBaseTest() { } } + @OtherGradlePluginTests + @GradleTestVersions( + additionalVersions = [TestVersions.Gradle.G_7_3] + ) + @DisplayName("KGP/Kapt does not eagerly configure any tasks") + @GradleTest + fun testKaptConfigurationAvoidance(gradleVersion: GradleVersion) { + project("kapt2/simple", gradleVersion) { + buildGradle.appendText( + """ + | + |tasks.configureEach { + | if (name != "help" && name != "clean") { + | throw new GradleException("Configuration avoidance failure for ${'$'}name!") + | } + |} + """.trimMargin() + ) + + build("--dry-run") + } + } + @AndroidGradlePluginTests @DisplayName("Android unrelated tasks are not configured") @AndroidTestVersions(minVersion = TestVersions.AGP.AGP_42) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/simple/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/simple/build.gradle index 84961752565..c940dd01607 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/simple/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/simple/build.gradle @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile + plugins { id "java" id "org.jetbrains.kotlin.jvm" @@ -16,4 +18,6 @@ dependencies { testImplementation 'junit:junit:4.13.2' } -compileKotlin.kotlinOptions.allWarningsAsErrors = true +tasks.named("compileKotlin", KotlinJvmCompile) { + compilerOptions.allWarningsAsErrors = true +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt index 98f68086e94..10f2e5373d0 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin.Companion.isUse import org.jetbrains.kotlin.gradle.model.builder.KaptModelBuilder import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaCompilation import org.jetbrains.kotlin.gradle.tasks.* import org.jetbrains.kotlin.gradle.tasks.configuration.* import org.jetbrains.kotlin.gradle.utils.SingleWarningPerBuild @@ -283,15 +284,12 @@ class Kapt3GradleSubplugin @Inject internal constructor(private val registry: To ) val kaptGenerateStubsTaskProvider: TaskProvider = context.createKaptGenerateStubsTask() - val kaptTaskProvider: TaskProvider = context.createKaptKotlinTask() + val kaptTaskProvider: TaskProvider = context.createKaptKotlinTask( + kaptGenerateStubsTaskProvider + ) kaptGenerateStubsTaskProvider.configure { kaptGenerateStubsTask -> kaptGenerateStubsTask.dependsOn(*buildDependencies.toTypedArray()) - kaptGenerateStubsTask.dependsOn( - project.provider { - kotlinCompilation.compileKotlinTask.dependsOn.filter { it !is TaskProvider<*> || it.name != kaptTaskProvider.name } - } - ) if (androidVariantData != null) { kaptGenerateStubsTask.additionalSources.from( @@ -305,9 +303,6 @@ class Kapt3GradleSubplugin @Inject internal constructor(private val registry: To } } - kaptTaskProvider.configure { kaptTask -> - kaptTask.dependsOn(kaptGenerateStubsTaskProvider) - } context.kotlinCompile.configure { it.dependsOn(kaptTaskProvider) } /** Plugin options are applied to kapt*Compile inside [createKaptKotlinTask] */ @@ -357,9 +352,16 @@ class Kapt3GradleSubplugin @Inject internal constructor(private val registry: To ).get() } - private fun Kapt3SubpluginContext.createKaptKotlinTask(): TaskProvider { + private fun Kapt3SubpluginContext.createKaptKotlinTask( + generateStubsTask: TaskProvider + ): TaskProvider { val taskName = getKaptTaskName("kapt") - val taskConfigAction = KaptWithoutKotlincConfig(kotlinCompilation.compileKotlinTaskProvider.get() as KotlinCompile, kaptExtension) + @Suppress("UNCHECKED_CAST") + val taskConfigAction = KaptWithoutKotlincConfig( + kotlinCompilation.project, + generateStubsTask, + kaptExtension + ) val kaptClasspathConfiguration = project.configurations.create("kaptClasspath_$taskName") .setExtendsFrom(kaptClasspathConfigurations).also { @@ -367,6 +369,8 @@ class Kapt3GradleSubplugin @Inject internal constructor(private val registry: To it.isCanBeConsumed = false } taskConfigAction.configureTaskProvider { taskProvider -> + taskProvider.dependsOn(generateStubsTask) + if (javaCompile != null) { val androidVariantData = KaptWithAndroid.androidVariantData(this) if (androidVariantData != null) { @@ -379,7 +383,14 @@ class Kapt3GradleSubplugin @Inject internal constructor(private val registry: To disableAnnotationProcessingInJavaTask() } - kotlinCompilation.output.classesDirs.from(taskProvider.flatMap { it.classesDir }) + // Workaround for changes in Gradle 7.3 causing eager task realization + // For details check `KotlinSourceSetProcessor.prepareKotlinCompileTask()` + if (kotlinCompilation is KotlinWithJavaCompilation<*, *>) { + val kotlinSourceDirectorySet = kotlinCompilation.defaultSourceSet.kotlin + kotlinSourceDirectorySet.compiledBy(taskProvider, KaptTask::classesDir) + } else { + kotlinCompilation.output.classesDirs.from(taskProvider.flatMap { it.classesDir }) + } kotlinCompilation.compileTaskProvider.configure { task -> with(task as AbstractKotlinCompile<*>) { diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/configuration/KaptConfig.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/configuration/KaptConfig.kt index 2873a22e677..1d179f87fb8 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/configuration/KaptConfig.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/configuration/KaptConfig.kt @@ -24,12 +24,10 @@ import org.jetbrains.kotlin.gradle.internal.kapt.incremental.CLASS_STRUCTURE_ART import org.jetbrains.kotlin.gradle.internal.kapt.incremental.StructureTransformAction import org.jetbrains.kotlin.gradle.internal.kapt.incremental.StructureTransformLegacyAction import org.jetbrains.kotlin.gradle.plugin.* -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.gradle.tasks.toCompilerPluginOptions import org.jetbrains.kotlin.gradle.utils.listProperty import org.jetbrains.kotlin.gradle.utils.markResolvable import java.io.File -import java.util.concurrent.Callable internal open class KaptConfig( project: Project, @@ -49,7 +47,7 @@ internal open class KaptConfig( task.includeCompileClasspath.set(ext.includeCompileClasspath ?: project.isIncludeCompileClasspath()) task.classpathStructure.from(kaptClasspathSnapshot) - task.localStateDirectories.from(Callable { task.incAptCache.orNull }) + task.localStateDirectories.from({ task.incAptCache.orNull }) task.onlyIf { it as KaptTask it.includeCompileClasspath.get() || !it.kaptClasspath.isEmpty @@ -58,18 +56,26 @@ internal open class KaptConfig( } } - internal constructor(kotlinCompileTask: KotlinCompile, ext: KaptExtension) : this(kotlinCompileTask.project, ext) { + internal constructor( + project: Project, + kaptGenerateStubsTask: TaskProvider, + ext: KaptExtension + ) : this(project, ext) { configureTask { task -> - task.classpath.from(kotlinCompileTask.libraries - project.files(task.classesDir)) - task.compiledSources.from( - kotlinCompileTask.destinationDirectory, - Callable { kotlinCompileTask.javaOutputDir.takeIf { it.isPresent } }) + task.classpath.from( + kaptGenerateStubsTask.map { it.libraries } + ) + task.compiledSources + .from( + kaptGenerateStubsTask.flatMap { it.kotlinCompileDestinationDirectory }, + { kaptGenerateStubsTask.get().javaOutputDir.takeIf { it.isPresent } } + ) .disallowChanges() - task.sourceSetName.value(kotlinCompileTask.sourceSetName).disallowChanges() + task.sourceSetName.value(kaptGenerateStubsTask.flatMap { it.sourceSetName }).disallowChanges() val kaptSources = objectFactory.fileCollection() - .from(kotlinCompileTask.javaSources, task.stubsDir) + .from(kaptGenerateStubsTask.map { it.javaSources }, task.stubsDir) .asFileTree .matching { it.include("**/*.java") } .filter { @@ -175,14 +181,21 @@ internal class KaptWithoutKotlincConfig : KaptConfig { ) task.kaptJars.from(project.configurations.getByName(Kapt3GradleSubplugin.KAPT_WORKER_DEPENDENCIES_CONFIGURATION_NAME)) task.mapDiagnosticLocations = ext.mapDiagnosticLocations - task.annotationProcessorFqNames.set(providers.provider { ext.processors.split(',').filter { it.isNotEmpty() } }) + task.annotationProcessorFqNames.set(providers.provider { + @Suppress("DEPRECATION") + ext.processors.split(',').filter { it.isNotEmpty() } + }) task.disableClassloaderCacheForProcessors = project.disableClassloaderCacheForProcessors() task.classLoadersCacheSize = project.classLoadersCacheSize() task.javacOptions.set(getJavaOptions(task.defaultJavaSourceCompatibility)) } } - constructor(kotlinCompileTask: KotlinCompile, ext: KaptExtension) : super(kotlinCompileTask, ext) { + constructor( + project: Project, + kaptGenerateStubsTask: TaskProvider, + ext: KaptExtension + ) : super(project, kaptGenerateStubsTask, ext) { project.configurations.findByName(Kapt3GradleSubplugin.KAPT_WORKER_DEPENDENCIES_CONFIGURATION_NAME) ?: project.configurations.create(Kapt3GradleSubplugin.KAPT_WORKER_DEPENDENCIES_CONFIGURATION_NAME).apply { dependencies.addAllLater(project.listProperty {