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 c08710c1ec..ec595434ba 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 @@ -35,7 +35,6 @@ import org.gradle.api.provider.Property import org.gradle.api.provider.Provider import org.gradle.api.tasks.* import org.gradle.api.tasks.Optional -import org.gradle.api.tasks.compile.AbstractCompile import org.gradle.api.tasks.compile.JavaCompile import org.gradle.language.jvm.tasks.ProcessResources import org.gradle.process.CommandLineArgumentProvider @@ -189,7 +188,7 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool override fun applyToCompilation(kotlinCompilation: KotlinCompilation<*>): Provider> { val project = kotlinCompilation.target.project - val kotlinCompileProvider: TaskProvider = + val kotlinCompileProvider: TaskProvider> = project.locateTask(kotlinCompilation.compileKotlinTaskName) ?: return project.provider { emptyList() } val javaCompile = findJavaTaskForKotlinCompilation(kotlinCompilation)?.get() val kspExtension = project.extensions.getByType(KspExtension::class.java) @@ -244,7 +243,6 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool ) kspTask.commandLineArgumentProviders.addAll(kspExtension.commandLineArgumentProviders) kspTask.destination = kspOutputDir - kspTask.kspOutputDir.value(kspOutputDir) kspTask.blockOtherCompilerPlugins = kspExtension.blockOtherCompilerPlugins kspTask.apOptions.value(kspExtension.arguments).disallowChanges() kspTask.kspCacheDir.fileValue(getKspCachesDir(project, sourceSetName, target)).disallowChanges() @@ -262,8 +260,8 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool kspTask.isKspIncremental = isIncremental } - fun configureAsAbstractCompile(kspTask: AbstractCompile) { - kspTask.getDestinationDirectory().set(kspOutputDir) + fun configureAsAbstractKotlinCompileTool(kspTask: AbstractKotlinCompileTool<*>) { + kspTask.destinationDirectory.set(kspOutputDir) kspTask.outputs.dirs( kotlinOutputDir, javaOutputDir, @@ -277,17 +275,16 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool it.safeAs()?.name == kspTaskName } kspTask.dependsOn(deps) - kspTask.source(kotlinCompileTask.source) - if (kotlinCompileTask is AbstractKotlinCompile<*>) { - val sourceRoots = kotlinCompileTask.getSourceRoots() - if (sourceRoots is SourceRoots.ForJvm) { - kspTask.source(sourceRoots.javaSourceRoots) - } + kspTask.setSource(kotlinCompileTask.sources) + if (kotlinCompileTask is KotlinCompile) { + kspTask.setSource(kotlinCompileTask.javaSources) } } else { - kotlinCompilation.allKotlinSourceSets.forEach { sourceSet -> kspTask.source(sourceSet.kotlin) } + kotlinCompilation.allKotlinSourceSets.forEach { sourceSet -> + kspTask.setSource(sourceSet.kotlin) + } if (kotlinCompilation is KotlinCommonCompilation) { - kspTask.source(kotlinCompilation.defaultSourceSet.kotlin) + kspTask.setSource(kotlinCompilation.defaultSourceSet.kotlin) } } @@ -309,9 +306,9 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool val isIncremental = project.findProperty("ksp.incremental")?.toString()?.toBoolean() ?: true project.tasks.register(kspTaskName, kspTaskClass) { kspTask -> configureAsKspTask(kspTask, isIncremental) - configureAsAbstractCompile(kspTask) + configureAsAbstractKotlinCompileTool(kspTask) - kspTask.classpath = kotlinCompileTask.project.files(Callable { kotlinCompileTask.classpath }) + kspTask.libraries.setFrom(kotlinCompileTask.project.files(Callable { kotlinCompileTask.libraries })) kspTask.configureCompilation( kotlinCompilation as KotlinCompilationData<*>, kotlinCompileTask, @@ -331,7 +328,7 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool kotlinCompileTask.compilation.konanTarget.enabledOnCurrentHost } configureAsKspTask(kspTask, false) - configureAsAbstractCompile(kspTask) + configureAsAbstractKotlinCompileTool(kspTask) // KotlinNativeCompile computes -Xplugin=... from compilerPluginClasspath. kspTask.compilerPluginClasspath = project.configurations.getByName(pluginConfigurationName) @@ -344,9 +341,9 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool kotlinCompileProvider.configure { kotlinCompile -> kotlinCompile.dependsOn(kspTaskProvider) - kotlinCompile.source(kotlinOutputDir, javaOutputDir) + kotlinCompile.setSource(kotlinOutputDir, javaOutputDir) when (kotlinCompile) { - is AbstractKotlinCompile<*> -> kotlinCompile.classpath += project.files(classOutputDir) + is AbstractKotlinCompile<*> -> kotlinCompile.libraries.from(project.files(classOutputDir)) // is KotlinNativeCompile -> TODO: support binary generation? } } @@ -442,9 +439,6 @@ interface KspTask : Task { @get:Input var isKspIncremental: Boolean - @get:Internal - val kspOutputDir: Property - fun configureCompilation( kotlinCompilation: KotlinCompilationData<*>, kotlinCompile: AbstractKotlinCompile<*>, @@ -453,22 +447,15 @@ interface KspTask : Task { @CacheableTask abstract class KspTaskJvm @Inject constructor( - workerExecutor: WorkerExecutor -) : KotlinCompile(KotlinJvmOptionsImpl(), workerExecutor), KspTask { + workerExecutor: WorkerExecutor, + objectFactory: ObjectFactory +) : KotlinCompile(KotlinJvmOptionsImpl(), workerExecutor, objectFactory), KspTask { @get:PathSensitive(PathSensitivity.NONE) @get:Optional @get:InputFiles @get:Incremental abstract val classpathStructure: ConfigurableFileCollection - @PathSensitive(PathSensitivity.RELATIVE) - @InputFiles - @SkipWhenEmpty - @IgnoreEmptyDirectories - override fun getSource() = super.getSource().filter { - !kspOutputDir.get().isParentOf(it) - }.asFileTree - @get:Input var isIntermoduleIncremental: Boolean = false @@ -493,7 +480,7 @@ abstract class KspTaskJvm @Inject constructor( isKspIncremental if (isIntermoduleIncremental) { val classStructureIfIncremental = project.configurations.detachedConfiguration( - project.dependencies.create(project.files(project.provider { kotlinCompile.classpath })) + project.dependencies.create(project.files(project.provider { kotlinCompile.libraries })) ) maybeRegisterTransform(project) @@ -506,6 +493,9 @@ abstract class KspTaskJvm @Inject constructor( } else { classpathSnapshotProperties.useClasspathSnapshot.value(false).disallowChanges() } + + // Used only in incremental compilation and is not applicable to KSP. + useKotlinAbiSnapshot.value(false) } private fun maybeRegisterTransform(project: Project) { @@ -563,7 +553,7 @@ abstract class KspTaskJvm @Inject constructor( val currentSnapshot = ClasspathSnapshot.ClasspathSnapshotFactory.createCurrent( cacheDir, - classpath.files.toList(), + libraries.files.toList(), processorClasspath.files.toList(), allDataFiles ) @@ -620,7 +610,7 @@ abstract class KspTaskJvm @Inject constructor( @Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER", "EXPOSED_PARAMETER_TYPE") fun `callCompilerAsync$kotlin_gradle_plugin`( args: K2JVMCompilerArguments, - sourceRoots: SourceRoots, + kotlinSources: Set, inputChanges: InputChanges, taskOutputsBackup: TaskOutputsBackup? ) { @@ -641,10 +631,35 @@ abstract class KspTaskJvm @Inject constructor( clearIncCache() } args.addChangedFiles(changedFiles) - super.callCompilerAsync(args, sourceRoots, inputChanges, taskOutputsBackup) + super.callCompilerAsync(args, kotlinSources, inputChanges, taskOutputsBackup) } - override fun skipCondition(): Boolean = false + override fun skipCondition(): Boolean = sources.isEmpty && javaSources.isEmpty + + override val incrementalProps: List + get() = listOf( + sources, + javaSources, + commonSourceSet, + classpathSnapshotProperties.classpath, + classpathSnapshotProperties.classpathSnapshot + ) + + @get:InputFiles + @get:SkipWhenEmpty + @get:IgnoreEmptyDirectories + @get:PathSensitive(PathSensitivity.RELATIVE) + override val sources: FileCollection = super.sources.filter { + !destination.isParentOf(it) + } + + @get:InputFiles + @get:SkipWhenEmpty + @get:IgnoreEmptyDirectories + @get:PathSensitive(PathSensitivity.RELATIVE) + override val javaSources: FileCollection = super.javaSources.filter { + !destination.isParentOf(it) + } } @CacheableTask @@ -659,14 +674,6 @@ abstract class KspTaskJS @Inject constructor( "-Xir-produce-klib-file" ) - @PathSensitive(PathSensitivity.RELATIVE) - @InputFiles - @SkipWhenEmpty - @IgnoreEmptyDirectories - override fun getSource() = super.getSource().filter { - !kspOutputDir.get().isParentOf(it) - }.asFileTree - override fun configureCompilation( kotlinCompilation: KotlinCompilationData<*>, kotlinCompile: AbstractKotlinCompile<*>, @@ -723,7 +730,7 @@ abstract class KspTaskJS @Inject constructor( @Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER", "EXPOSED_PARAMETER_TYPE") fun `callCompilerAsync$kotlin_gradle_plugin`( args: K2JSCompilerArguments, - sourceRoots: SourceRoots, + kotlinSources: Set, inputChanges: InputChanges, taskOutputsBackup: TaskOutputsBackup? ) { @@ -733,19 +740,28 @@ abstract class KspTaskJS @Inject constructor( } else { args.addChangedFiles(changedFiles) } - super.callCompilerAsync(args, sourceRoots, inputChanges, taskOutputsBackup) + super.callCompilerAsync(args, kotlinSources, inputChanges, taskOutputsBackup) } // Overrding an internal function is hacky. // TODO: Ask upstream to open it. @Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER", "EXPOSED_PARAMETER_TYPE") fun `isIncrementalCompilationEnabled$kotlin_gradle_plugin`(): Boolean = false + + @get:InputFiles + @get:SkipWhenEmpty + @get:IgnoreEmptyDirectories + @get:PathSensitive(PathSensitivity.RELATIVE) + override val sources: FileCollection = super.sources.filter { + !destination.isParentOf(it) + } } @CacheableTask abstract class KspTaskMetadata @Inject constructor( - workerExecutor: WorkerExecutor -) : KotlinCompileCommon(KotlinMultiplatformCommonOptionsImpl(), workerExecutor), KspTask { + workerExecutor: WorkerExecutor, + objectFactory: ObjectFactory +) : KotlinCompileCommon(KotlinMultiplatformCommonOptionsImpl(), workerExecutor, objectFactory), KspTask { override fun configureCompilation( kotlinCompilation: KotlinCompilationData<*>, kotlinCompile: AbstractKotlinCompile<*>, @@ -760,14 +776,6 @@ abstract class KspTaskMetadata @Inject constructor( ) } - @PathSensitive(PathSensitivity.RELATIVE) - @InputFiles - @SkipWhenEmpty - @IgnoreEmptyDirectories - override fun getSource() = super.getSource().filter { - !kspOutputDir.get().isParentOf(it) - }.asFileTree - @get:Internal internal abstract val compileKotlinArgumentsContributor: Property> @@ -798,7 +806,7 @@ abstract class KspTaskMetadata @Inject constructor( } args.addPluginOptions(options.get()) args.destination = destination.canonicalPath - val classpathList = classpath.files.filter { it.exists() }.toMutableList() + val classpathList = libraries.files.filter { it.exists() }.toMutableList() args.classpath = classpathList.joinToString(File.pathSeparator) args.friendPaths = friendPaths.files.map { it.absolutePath }.toTypedArray() args.refinesPaths = refinesMetadataPaths.map { it.absolutePath }.toTypedArray() @@ -811,7 +819,7 @@ abstract class KspTaskMetadata @Inject constructor( @Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER", "EXPOSED_PARAMETER_TYPE") fun `callCompilerAsync$kotlin_gradle_plugin`( args: K2MetadataCompilerArguments, - sourceRoots: SourceRoots, + kotlinSources: Set, inputChanges: InputChanges, taskOutputsBackup: TaskOutputsBackup? ) { @@ -821,14 +829,23 @@ abstract class KspTaskMetadata @Inject constructor( } else { args.addChangedFiles(changedFiles) } - super.callCompilerAsync(args, sourceRoots, inputChanges, taskOutputsBackup) + super.callCompilerAsync(args, kotlinSources, inputChanges, taskOutputsBackup) + } + + @get:InputFiles + @get:SkipWhenEmpty + @get:IgnoreEmptyDirectories + @get:PathSensitive(PathSensitivity.RELATIVE) + override val sources: FileCollection = super.sources.filter { + !destination.isParentOf(it) } } @CacheableTask abstract class KspTaskNative @Inject constructor( - injected: KotlinNativeCompilationData<*>, -) : KotlinNativeCompile(injected), KspTask { + compilation: KotlinNativeCompilationData<*>, + objectFactory: ObjectFactory +) : KotlinNativeCompile(compilation, objectFactory), KspTask { override val additionalCompilerOptions: Provider> get() { return project.provider { @@ -837,14 +854,6 @@ abstract class KspTaskNative @Inject constructor( } } - @PathSensitive(PathSensitivity.RELATIVE) - @InputFiles - @SkipWhenEmpty - @IgnoreEmptyDirectories - override fun getSource() = super.getSource().filter { - !kspOutputDir.get().isParentOf(it) - }.asFileTree - override var compilerPluginClasspath: FileCollection? = null get() { if (blockOtherCompilerPlugins) { @@ -870,6 +879,14 @@ abstract class KspTaskNative @Inject constructor( } super.compile() } + + @get:InputFiles + @get:SkipWhenEmpty + @get:IgnoreEmptyDirectories + @get:PathSensitive(PathSensitivity.RELATIVE) + override val sources: FileCollection = super.sources.filter { + !destination.isParentOf(it) + } } // This forces rebuild. diff --git a/gradle.properties b/gradle.properties index 4ec199b195..5c2913ae70 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ # Copied from kotlinc org.gradle.jvmargs=-Duser.country=US -Dkotlin.daemon.jvm.options=-Xmx2200m -Dfile.encoding=UTF-8 -kotlinBaseVersion=1.7.0-dev-2437 +kotlinBaseVersion=1.7.0-dev-3025 agpBaseVersion=7.0.0 intellijVersion=203.8084.24 junitVersion=4.12 diff --git a/integration-tests/src/test/resources/playground/workload/build.gradle.kts b/integration-tests/src/test/resources/playground/workload/build.gradle.kts index 3c44d53184..6cb48fad09 100644 --- a/integration-tests/src/test/resources/playground/workload/build.gradle.kts +++ b/integration-tests/src/test/resources/playground/workload/build.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompileTool + val testRepo: String by project plugins { @@ -24,11 +26,11 @@ ksp { arg("option2", "value2") } -val compileKotlin: AbstractCompile by tasks +val compileKotlin: AbstractKotlinCompileTool<*> by tasks tasks.register("copyG") { from("G.kt") into(File(buildDir, "generatedSources").apply { mkdirs() }) }.let { // Magic. `map` creates a provider to propagate task dependency. - compileKotlin.source(it.map { it.destinationDir }) + compileKotlin.setSource(it.map { it.destinationDir }) }