diff --git a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspAATask.kt b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspAATask.kt index b9791a3041..94bd3b9e72 100644 --- a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspAATask.kt +++ b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspAATask.kt @@ -21,7 +21,6 @@ import org.gradle.workers.WorkParameters import org.gradle.workers.WorkerExecutor import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptions import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation -import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinCommonCompilation import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompileTool import java.io.File @@ -58,7 +57,6 @@ abstract class KspAATask @Inject constructor( kotlinCompilation: KotlinCompilation<*>, kotlinCompileProvider: TaskProvider>, processorClasspath: Configuration, - kspGeneratedSourceSet: KotlinSourceSet, ): TaskProvider { val project = kotlinCompilation.target.project val target = kotlinCompilation.target.name @@ -74,12 +72,19 @@ abstract class KspAATask @Inject constructor( kspAATask.kspConfig.let { cfg -> cfg.processorClasspath.from(processorClasspath) cfg.moduleName.value(kotlinCompilation.defaultSourceSet.name) - kotlinCompilation.allKotlinSourceSetsObservable - .forAll { sourceSet -> - if (sourceSet == kspGeneratedSourceSet) return@forAll - cfg.sourceRoots.from(sourceSet.kotlin) - cfg.javaSourceRoots.from(sourceSet.kotlin) + val kotlinOutputDir = KspGradleSubplugin.getKspKotlinOutputDir(project, sourceSetName, target) + val javaOutputDir = KspGradleSubplugin.getKspJavaOutputDir(project, sourceSetName, target) + kotlinCompilation.allKotlinSourceSetsObservable.forAll { sourceSet -> + val filtered = sourceSet.kotlin.srcDirs.filter { + !kotlinOutputDir.isParentOf(it) && !javaOutputDir.isParentOf(it) + }.map { + // @SkipWhenEmpty doesn't work well with File. + project.objects.fileTree().from(it) } + cfg.sourceRoots.from(filtered) + cfg.javaSourceRoots.from(filtered) + kspAATask.dependsOn(sourceSet.kotlin.nonSelfDeps(kspTaskName)) + } if (kotlinCompilation is KotlinCommonCompilation) { cfg.commonSourceRoots.from(kotlinCompilation.defaultSourceSet.kotlin) } @@ -99,8 +104,8 @@ abstract class KspAATask @Inject constructor( cfg.projectBaseDir.value(File(project.project.projectDir.canonicalPath)) cfg.cachesDir.value(KspGradleSubplugin.getKspCachesDir(project, sourceSetName, target)) cfg.outputBaseDir.value(KspGradleSubplugin.getKspOutputDir(project, sourceSetName, target)) - cfg.kotlinOutputDir.value(KspGradleSubplugin.getKspKotlinOutputDir(project, sourceSetName, target)) - cfg.javaOutputDir.value(KspGradleSubplugin.getKspJavaOutputDir(project, sourceSetName, target)) + cfg.kotlinOutputDir.value(kotlinOutputDir) + cfg.javaOutputDir.value(javaOutputDir) cfg.classOutputDir.value(KspGradleSubplugin.getKspClassOutputDir(project, sourceSetName, target)) cfg.resourceOutputDir.value( KspGradleSubplugin.getKspResourceOutputDir( diff --git a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt index f0c0365b54..9143306795 100644 --- a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt +++ b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt @@ -37,7 +37,6 @@ import org.gradle.util.GradleVersion import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.LanguageVersion.Companion.LATEST_STABLE import org.jetbrains.kotlin.gradle.dsl.KotlinVersion -import org.jetbrains.kotlin.gradle.dsl.kotlinExtension import org.jetbrains.kotlin.gradle.internal.kapt.incremental.CLASS_STRUCTURE_ARTIFACT_TYPE import org.jetbrains.kotlin.gradle.internal.kapt.incremental.ClasspathSnapshot import org.jetbrains.kotlin.gradle.internal.kapt.incremental.KaptClasspathChanges @@ -59,7 +58,6 @@ import org.jetbrains.kotlin.gradle.tasks.* import org.jetbrains.kotlin.incremental.ChangedFiles import org.jetbrains.kotlin.incremental.isJavaFile import org.jetbrains.kotlin.incremental.isKotlinFile -import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty import java.io.File import java.util.concurrent.Callable @@ -262,10 +260,6 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool assert(kotlinCompileProvider.name.startsWith("compile")) val kspTaskName = kotlinCompileProvider.name.replaceFirst("compile", "ksp") - val kspGeneratedSourceSet = - project.kotlinExtension.sourceSets.create("generatedBy" + kspTaskName.capitalizeAsciiOnly()) - sourceSetMap.put(kotlinCompilation.defaultSourceSet, kspGeneratedSourceSet) - val processorClasspath = project.configurations.maybeCreate("${kspTaskName}ProcessorClasspath") .extendsFrom(*nonEmptyKspConfigurations.toTypedArray()).markResolvable() @@ -276,28 +270,6 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool kspTask.options.addAll( kspTask.project.provider { - val commonSources: List = when (processingModel) { - "hierarchical" -> { - fun unclaimedDeps(roots: Set): Set { - val unclaimedParents = - roots.flatMap { it.dependsOn }.filterNot { it in sourceSetMap }.toSet() - return if (unclaimedParents.isEmpty()) { - unclaimedParents - } else { - unclaimedParents + unclaimedDeps(unclaimedParents) - } - } - // Source sets that are not claimed by other compilations. - // I.e., those that should be processed by this compilation. - val unclaimed = - kotlinCompilation.kotlinSourceSets + unclaimedDeps(kotlinCompilation.kotlinSourceSets) - val commonSourceSets = kotlinCompilation.allKotlinSourceSets - unclaimed - commonSourceSets.flatMap { it.kotlin.files } - } - - else -> emptyList() - } - getSubpluginOptions( project, kspExtension, @@ -306,7 +278,7 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool isIncremental, kspExtension.allWarningsAsErrors, kspTask.commandLineArgumentProviders, - commonSources, + emptyList(), ) } ) @@ -326,48 +298,35 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool val kotlinCompileTask = kotlinCompileProvider.get() if (kspExtension.allowSourcesFromOtherPlugins) { - fun FileCollection.nonSelfDeps(): List = - buildDependencies.getDependencies(null).filterNot { - it.name == kspTaskName - } - fun setSource(source: FileCollection) { // kspTask.setSource(source) would create circular dependency. // Therefore we need to manually extract input deps, filter them, and tell kspTask. kspTask.setSource(project.provider { source.files }) - kspTask.dependsOn(project.provider { source.nonSelfDeps() }) + kspTask.dependsOn(project.provider { source.nonSelfDeps(kspTaskName) }) } - setSource(kotlinCompileTask.sources - kspGeneratedSourceSet.kotlin) + setSource( + kotlinCompileTask.sources.filter { + !kotlinOutputDir.isParentOf(it) && !javaOutputDir.isParentOf(it) + } + ) if (kotlinCompileTask is KotlinCompile) { - setSource(kotlinCompileTask.javaSources - kspGeneratedSourceSet.kotlin) + setSource( + kotlinCompileTask.javaSources.filter { + !kotlinOutputDir.isParentOf(it) && !javaOutputDir.isParentOf(it) + } + ) } } else { kotlinCompilation.allKotlinSourceSetsObservable.forAll { sourceSet -> - if (sourceSet == kspGeneratedSourceSet) return@forAll - kspTask.setSource(sourceSet.kotlin) - } - - if (kotlinCompilation is KotlinCommonCompilation) { - kspTask.setSource(kotlinCompilation.defaultSourceSet.kotlin) - } - val generated = when (processingModel) { - "hierarchical" -> { - // boundary parent source sets that are going to be compiled by other compilations - fun claimedParents(root: KotlinSourceSet): Set { - val (claimed, unclaimed) = root.dependsOn.partition { it in sourceSetMap } - return claimed.toSet() + unclaimed.flatMap { claimedParents(it) } + kspTask.setSource( + sourceSet.kotlin.srcDirs.filter { + !kotlinOutputDir.isParentOf(it) && !javaOutputDir.isParentOf(it) } - kotlinCompilation.kotlinSourceSets.flatMap { claimedParents(it) }.map { sourceSetMap[it]!! } - } - - else -> emptyList() - } - generated.forEach { - kspTask.setSource(it.kotlin) + ) + kspTask.dependsOn(sourceSet.kotlin.nonSelfDeps(kspTaskName)) } } - kspTask.exclude { kspOutputDir.isParentOf(it.file) } kspTask.libraries.setFrom( kotlinCompileTask.project.files( @@ -428,7 +387,6 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool kotlinCompilation, kotlinCompileProvider, processorClasspath, - kspGeneratedSourceSet ) } else { KotlinFactories.registerKotlinJvmCompileTask(project, kspTaskName, kotlinCompilation).also { @@ -554,16 +512,19 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool } // No else; The cases should be exhaustive } - kspGeneratedSourceSet.kotlin.srcDir(project.files(kotlinOutputDir, javaOutputDir).builtBy(kspTaskProvider)) + + val generatedSources = arrayOf( + project.files(kotlinOutputDir).builtBy(kspTaskProvider), + project.files(javaOutputDir).builtBy(kspTaskProvider), + ) if (kotlinCompilation is KotlinCommonCompilation) { - // Do not make common source sets depend on generated source sets. - // They will be observed by downstreams and confuse processors. - kotlinCompileProvider.configure { - it.source(kspGeneratedSourceSet.kotlin) - } + // Do not add generated sources to common source sets. + // They will be observed by downstreams and violate current build scheme. + kotlinCompileProvider.configure { it.source(*generatedSources) } } else { - kotlinCompilation.defaultSourceSet.dependsOn(kspGeneratedSourceSet) + kotlinCompilation.defaultSourceSet.kotlin.srcDirs(*generatedSources) } + kotlinCompileProvider.configure { kotlinCompile -> when (kotlinCompile) { is AbstractKotlinCompile<*> -> kotlinCompile.libraries.from(project.files(classOutputDir)) @@ -793,3 +754,8 @@ internal fun Configuration.markResolvable(): Configuration = apply { isCanBeConsumed = false isVisible = false } + +internal fun FileCollection.nonSelfDeps(selfTaskName: String): List = + buildDependencies.getDependencies(null).filterNot { + it.name == selfTaskName + } diff --git a/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/HmppIT.kt b/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/HmppIT.kt index 9da354ed61..430bdf86b6 100644 --- a/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/HmppIT.kt +++ b/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/HmppIT.kt @@ -2,6 +2,7 @@ package com.google.devtools.ksp.test import org.gradle.testkit.runner.GradleRunner import org.junit.Assert +import org.junit.Ignore import org.junit.Rule import org.junit.Test @@ -64,6 +65,7 @@ class HmppIT { ), ) + @Ignore @Test fun testHmpp() { val gradleRunner = GradleRunner.create().withProjectDir(project.root)