diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt index e24abb3680f..626e462b5ce 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt @@ -324,4 +324,17 @@ open class Kapt3IT : Kapt3BaseIT() { assertContains("Additional warning message from AP") } } + + @Test + fun testKaptConfigurationLazyResolution() = with(Project("simple", GRADLE_VERSION, directoryPrefix = "kapt2")) { + setupWorkingDir() + File(projectDir, "build.gradle").appendText( + "\ndependencies { kapt project.files { throw new GradleException(\"Resolved!\") } }" + ) + // Check that the kapt configuration does not get resolved during the project evaluation: + build("tasks") { + assertSuccessful() + assertNotContains("Resolved!") + } + } } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt3KotlinGradleSubplugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt3KotlinGradleSubplugin.kt index c0e5223ac85..3c4df43c4a2 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt3KotlinGradleSubplugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt3KotlinGradleSubplugin.kt @@ -80,6 +80,7 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin { val KAPT_GROUP_NAME = "org.jetbrains.kotlin" val KAPT_ARTIFACT_NAME = "kotlin-annotation-processing-gradle" + val KAPT_SUBPLUGIN_ID = "org.jetbrains.kotlin.kapt3" fun getKaptConfigurationName(sourceSetName: String): String { return if (sourceSetName != "main") @@ -110,14 +111,15 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin { } private inner class Kapt3SubpluginContext( - val project: Project, - val kotlinCompile: KotlinCompile, - val javaCompile: AbstractCompile, - val kaptVariantData: KaptVariantData<*>?, - val sourceSetName: String, - val javaSourceSet: SourceSet?, - val kaptExtension: KaptExtension, - val kaptClasspath: MutableList) { + val project: Project, + val kotlinCompile: KotlinCompile, + val javaCompile: AbstractCompile, + val kaptVariantData: KaptVariantData<*>?, + val sourceSetName: String, + val javaSourceSet: SourceSet?, + val kaptExtension: KaptExtension, + val kaptClasspathConfigurations: List + ) { val sourcesOutputDir = getKaptGeneratedSourcesDir(project, sourceSetName) val kotlinSourcesOutputDir = getKaptGeneratedKotlinSourcesDir(project, sourceSetName) val classesOutputDir = getKaptGeneratedClassesDir(project, sourceSetName) @@ -137,23 +139,13 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin { ): List { assert((variantData != null) xor (javaSourceSet != null)) - val kaptClasspath = arrayListOf() val buildDependencies = arrayListOf() val kaptConfigurations = arrayListOf() fun handleSourceSet(sourceSetName: String) { - val kaptConfiguration = project.findKaptConfiguration(sourceSetName) - val filteredDependencies = kaptConfiguration?.dependencies?.filter { - it.group != getGroupName() || it.name != getArtifactName() - } ?: emptyList() - - if (kaptConfiguration != null) { + project.findKaptConfiguration(sourceSetName)?.let { kaptConfiguration -> kaptConfigurations += kaptConfiguration buildDependencies += kaptConfiguration.buildDependencies - - if (filteredDependencies.isNotEmpty()) { - kaptClasspath.addAll(kaptConfiguration.resolve()) - } } } @@ -175,8 +167,14 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin { val kaptExtension = project.extensions.getByType(KaptExtension::class.java) - val context = Kapt3SubpluginContext(project, kotlinCompile, javaCompile, - kaptVariantData, sourceSetName, javaSourceSet, kaptExtension, kaptClasspath) + val nonEmptyKaptConfigurations = kaptConfigurations.filter { configuration -> + configuration.dependencies.any { it.group != getGroupName() || it.name != getArtifactName() } + } + + val context = Kapt3SubpluginContext( + project, kotlinCompile, javaCompile, + kaptVariantData, sourceSetName, javaSourceSet, kaptExtension, nonEmptyKaptConfigurations + ) val kaptGenerateStubsTask = context.createKaptGenerateStubsTask() val kaptTask = context.createKaptKotlinTask() @@ -208,8 +206,6 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin { pluginOptions += SubpluginOption("aptMode", aptMode) disableAnnotationProcessingInJavaTask() - kaptClasspath.forEach { pluginOptions += FilesSubpluginOption("apclasspath", listOf(it)) } - javaCompile.source(generatedFilesDir) pluginOptions += FilesSubpluginOption("sources", listOf(generatedFilesDir)) @@ -246,7 +242,7 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin { private fun Kapt3SubpluginContext.buildAndAddOptionsTo(task: Task, container: CompilerPluginOptions, aptMode: String) { val compilerPluginId = getCompilerPluginId() - val kaptSubpluginOptions = wrapPluginOptions(buildOptions(aptMode), "configuration") + val kaptSubpluginOptions = buildOptions(aptMode) task.registerSubpluginOptionsAsInputs(compilerPluginId, kaptSubpluginOptions) for (option in kaptSubpluginOptions) { @@ -320,7 +316,7 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin { registerGeneratedJavaSource(kaptTask, javaCompile) } - kaptTask.kaptClasspath = kaptClasspath + kaptTask.kaptClasspathConfigurations = kaptClasspathConfigurations buildAndAddOptionsTo(kaptTask, kaptTask.pluginOptions, aptMode = "apt") @@ -344,7 +340,7 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin { kaptTask.generatedSourcesDir = sourcesOutputDir mapKotlinTaskProperties(project, kaptTask) - kaptTask.kaptClasspath = kaptClasspath + kaptTask.kaptClasspathConfigurations = kaptClasspathConfigurations buildAndAddOptionsTo(kaptTask, kaptTask.pluginOptions, aptMode = "stubs") return kaptTask @@ -372,7 +368,7 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin { } } - override fun getCompilerPluginId() = "org.jetbrains.kotlin.kapt3" + override fun getCompilerPluginId() = KAPT_SUBPLUGIN_ID override fun getGroupName() = KAPT_GROUP_NAME override fun getArtifactName() = KAPT_ARTIFACT_NAME } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KaptGenerateStubsTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KaptGenerateStubsTask.kt index f7d2b20cdc7..65be5eb088e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KaptGenerateStubsTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KaptGenerateStubsTask.kt @@ -17,11 +17,14 @@ package org.jetbrains.kotlin.gradle.internal import com.intellij.openapi.util.io.FileUtil +import org.gradle.api.artifacts.Configuration +import org.gradle.api.file.FileCollection import org.gradle.api.tasks.* import org.gradle.api.tasks.incremental.IncrementalTaskInputs import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.gradle.plugin.kotlinDebug import org.jetbrains.kotlin.gradle.plugin.kotlinWarn +import org.jetbrains.kotlin.gradle.tasks.CompilerPluginOptions import org.jetbrains.kotlin.gradle.tasks.FilteringSourceRootsContainer import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.incremental.ChangedFiles @@ -44,7 +47,11 @@ open class KaptGenerateStubsTask : KotlinCompile() { lateinit var generatedSourcesDir: File @get:Classpath @get:InputFiles - lateinit var kaptClasspath: List + val kaptClasspath: FileCollection + get() = project.files(*kaptClasspathConfigurations.toTypedArray()) + + @get:Internal + internal lateinit var kaptClasspathConfigurations: List @get:Classpath @get:InputFiles @Suppress("unused") internal val kotlinTaskPluginClasspath get() = kotlinCompileTask.pluginClasspath @@ -66,8 +73,12 @@ open class KaptGenerateStubsTask : KotlinCompile() { override fun setupCompilerArgs(args: K2JVMCompilerArguments, defaultsOnly: Boolean) { kotlinCompileTask.setupCompilerArgs(args) + args.pluginClasspaths = (pluginClasspath + args.pluginClasspaths!!).toSet().toTypedArray() - args.pluginOptions = (pluginOptions.arguments + args.pluginOptions!!).toTypedArray() + + val pluginOptionsWithKapt = pluginOptions.withWrappedKaptOptions(withApClasspath = kaptClasspath) + args.pluginOptions = (pluginOptionsWithKapt.arguments + args.pluginOptions!!).toTypedArray() + args.verbose = project.hasProperty("kapt.verbose") && project.property("kapt.verbose").toString().toBoolean() == true args.classpathAsList = this.compileClasspath.toList() args.destinationAsFile = this.destinationDir diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KaptTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KaptTask.kt index cff75932ddb..2c9787808c9 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KaptTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KaptTask.kt @@ -3,6 +3,7 @@ package org.jetbrains.kotlin.gradle.internal import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.text.StringUtil.compareVersionNumbers import org.gradle.api.GradleException +import org.gradle.api.artifacts.Configuration import org.gradle.api.file.FileCollection import org.gradle.api.internal.ConventionTask import org.gradle.api.tasks.* @@ -41,7 +42,11 @@ open class KaptTask : ConventionTask(), CompilerArgumentAwareWithInput + val kaptClasspath: FileCollection + get() = project.files(*kaptClasspathConfigurations.toTypedArray()) + + @get:Internal + internal lateinit var kaptClasspathConfigurations: List @get:OutputDirectory internal lateinit var classesDir: File @@ -58,7 +63,10 @@ open class KaptTask : ConventionTask(), CompilerArgumentAwareWithInput>): String { return Base64.getEncoder().encodeToString(os.toByteArray()) } +internal fun CompilerPluginOptions.withWrappedKaptOptions(withApClasspath: Iterable): CompilerPluginOptions { + val resultOptionsByPluginId: MutableMap> = + subpluginOptionsByPluginId.toMutableMap() + + resultOptionsByPluginId.compute(Kapt3KotlinGradleSubplugin.KAPT_SUBPLUGIN_ID) { _, kaptOptions -> + val kaptOptionsWithClasspath = + kaptOptions.orEmpty() + withApClasspath.map { FilesSubpluginOption("apclasspath", listOf(it)) } + + wrapPluginOptions(kaptOptionsWithClasspath, "configuration") + } + + val result = CompilerPluginOptions() + classpath.forEach { result.addClasspathEntry(File(it)) } + resultOptionsByPluginId.forEach { pluginId, options -> + options.forEach { option -> result.addPluginArgument(pluginId, option) } + } + return result +} + fun wrapPluginOptions(options: List, newOptionName: String): List { val groupedOptions = options.groupBy { it.key }.mapValues { opt -> opt.value.map { it.value } } val encodedOptions = encodePluginOptions(groupedOptions)