[Gradle] KotlinJvmCompilation: Implement 'javaSourceSet' as safe Future<SourceSet?>

^KT-60441 Verification Pending
This commit is contained in:
Sebastian Sellmair
2023-07-17 11:56:35 +02:00
committed by Space Team
parent a49db89024
commit a4a0da267e
3 changed files with 35 additions and 21 deletions
@@ -13,6 +13,7 @@ import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.compile.AbstractCompile
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptions
import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.AfterEvaluateBuildscript
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.AfterFinaliseDsl
import org.jetbrains.kotlin.gradle.scripting.internal.ScriptingGradleSubplugin
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
@@ -53,14 +54,14 @@ internal class Kotlin2JvmSourceSetProcessor(
ScriptingGradleSubplugin.configureForSourceSet(project, compilationInfo.compilationName)
project.whenEvaluated {
project.launchInStage(AfterEvaluateBuildscript) {
val subpluginEnvironment = SubpluginEnvironment.loadSubplugins(project)
/* Not supported in KPM yet */
compilationInfo.tcsOrNull?.compilation?.let { compilation ->
subpluginEnvironment.addSubpluginOptions(project, compilation)
}
javaSourceSet?.let { java ->
javaSourceSet.await()?.let { java ->
val javaTask = project.tasks.withType<AbstractCompile>().named(java.compileJavaTaskName)
javaTask.configure { javaCompile ->
javaCompile.classpath += project.files(kotlinTask.flatMap { it.destinationDirectory })
@@ -22,6 +22,8 @@ import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
import org.jetbrains.kotlin.gradle.tasks.configuration.AbstractKotlinCompileConfig
import org.jetbrains.kotlin.gradle.tasks.registerTask
import org.jetbrains.kotlin.gradle.utils.Future
import org.jetbrains.kotlin.gradle.utils.future
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import java.util.concurrent.Callable
@@ -37,11 +39,11 @@ internal abstract class KotlinSourceSetProcessor<T : AbstractKotlinCompile<*>>(
override val kotlinTask: TaskProvider<out T> = prepareKotlinCompileTask()
protected val javaSourceSet: SourceSet?
protected val javaSourceSet: Future<SourceSet?>
get() = when (val compilation = compilationInfo.safeAs<KotlinCompilationInfo.TCS>()?.origin) {
is KotlinWithJavaCompilation<*, *> -> compilation.javaSourceSet
is KotlinWithJavaCompilation<*, *> -> project.future { compilation.javaSourceSet }
is KotlinJvmCompilation -> compilation.javaSourceSet
else -> null
else -> project.future { null }
}
private fun prepareKotlinCompileTask(): TaskProvider<out T> =
@@ -90,32 +92,26 @@ internal abstract class KotlinSourceSetProcessor<T : AbstractKotlinCompile<*>>(
}
override fun run() {
addKotlinDirectoriesToJavaSourceSet()
doTargetSpecificProcessing()
if (compilationInfo.tcsOrNull?.compilation is KotlinWithJavaCompilation<*, *>) {
project.launch { addKotlinDirectoriesToJavaSourceSet() }
createAdditionalClassesTaskForIdeRunner()
}
}
private fun addKotlinDirectoriesToJavaSourceSet() {
val java = javaSourceSet ?: return
private suspend fun addKotlinDirectoriesToJavaSourceSet() {
val java = javaSourceSet.await() ?: return
// Try to avoid duplicate Java sources in allSource; run lazily to allow changing the directory set:
val kotlinSrcDirsToAdd = Callable {
compilationInfo.sources.map { filterOutJavaSrcDirsIfPossible(it) }
compilationInfo.sources.map { it.sourceDirectories.minus(java.java.sourceDirectories) }
}
java.allJava.srcDirs(kotlinSrcDirsToAdd)
java.allSource.srcDirs(kotlinSrcDirsToAdd)
}
private fun filterOutJavaSrcDirsIfPossible(sourceDirectories: SourceDirectorySet): FileCollection {
val java = javaSourceSet ?: return sourceDirectories
// Build a lazily-resolved file collection that filters out Java sources from sources of this sourceDirectorySet
return sourceDirectories.sourceDirectories.minus(java.java.sourceDirectories)
}
private fun createAdditionalClassesTaskForIdeRunner() {
val kotlinCompilation = compilationInfo.tcsOrNull?.compilation ?: return
@@ -12,13 +12,16 @@ import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.compile.JavaCompile
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
import org.jetbrains.kotlin.gradle.plugin.HasCompilerOptions
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationWithResources
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.AfterFinaliseDsl
import org.jetbrains.kotlin.gradle.plugin.internal.JavaSourceSetsAccessor
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinCompilationImpl
import org.jetbrains.kotlin.gradle.plugin.variantImplementationFactory
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
import org.jetbrains.kotlin.gradle.utils.CompletableFuture
import org.jetbrains.kotlin.gradle.utils.Future
import org.jetbrains.kotlin.gradle.utils.lenient
import javax.inject.Inject
open class KotlinJvmCompilation @Inject internal constructor(
@@ -64,18 +67,32 @@ open class KotlinJvmCompilation @Inject internal constructor(
* will be enabled after call to this method.
*/
internal val compileJavaTaskProviderSafe: Provider<JavaCompile> = target.project.providers
.provider { javaSourceSet }
.provider { javaSourceSet.lenient.getOrNull() }
.flatMap { javaSourceSet ->
checkNotNull(javaSourceSet)
project.tasks.named(javaSourceSet.compileJavaTaskName, JavaCompile::class.java)
}
internal val javaSourceSet
get() = if (target.withJavaEnabled) maybeCreateJavaSourceSet() else null
internal val javaSourceSet: Future<SourceSet?> get() = javaSourceSetImpl
private val javaSourceSetImpl: CompletableFuture<SourceSet?> = CompletableFuture<SourceSet?>().also { future ->
/**
* If no SourceSet was set until 'AfterFinaliseDsl', then user really did never call into 'withJava', hence
* we can complete the Future with 'null' notifying everybody, that there won't be any java source set associated with
* this compilation
*/
target.project.launchInStage(AfterFinaliseDsl) {
if (!future.isCompleted) {
future.complete(null)
}
}
}
internal fun maybeCreateJavaSourceSet(): SourceSet {
check(target.withJavaEnabled)
return target.project.javaSourceSets.maybeCreate(compilationName)
val sourceSet = target.project.javaSourceSets.maybeCreate(compilationName)
javaSourceSetImpl.complete(sourceSet)
return sourceSet
}
override val processResourcesTaskName: String