From a42263773898a561f626ec8c8c0e30853a260b88 Mon Sep 17 00:00:00 2001 From: Aurimas Liutikas Date: Wed, 14 May 2025 17:30:35 -0700 Subject: [PATCH] Attempt to fix things --- gradle-plugin/lint-baseline.xml | 115 ++---------------- .../ksp/gradle/AndroidPluginIntegration.kt | 15 +-- .../devtools/ksp/gradle/KotlinFactories.kt | 7 +- .../google/devtools/ksp/gradle/KspAATask.kt | 89 +++++++++----- .../devtools/ksp/gradle/KspConfigurations.kt | 2 +- .../devtools/ksp/gradle/KspSubplugin.kt | 86 +++++++------ 6 files changed, 128 insertions(+), 186 deletions(-) diff --git a/gradle-plugin/lint-baseline.xml b/gradle-plugin/lint-baseline.xml index 675856d96b..4b9e044d23 100644 --- a/gradle-plugin/lint-baseline.xml +++ b/gradle-plugin/lint-baseline.xml @@ -8,7 +8,7 @@ errorLine2=" ~~~"> @@ -19,7 +19,7 @@ errorLine2=" ~~~"> @@ -30,7 +30,7 @@ errorLine2=" ~~~"> @@ -52,7 +52,7 @@ errorLine2=" ~~~"> @@ -63,21 +63,10 @@ errorLine2=" ~~~"> - - - - - - - - @@ -118,85 +96,8 @@ errorLine2=" ~~~~~~~~~~~~~~"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/AndroidPluginIntegration.kt b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/AndroidPluginIntegration.kt index cc1440ed55..ee73e3b00b 100644 --- a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/AndroidPluginIntegration.kt +++ b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/AndroidPluginIntegration.kt @@ -22,12 +22,13 @@ import com.android.build.gradle.BaseExtension import com.android.build.gradle.api.SourceKind import org.gradle.api.Project import org.gradle.api.Task +import org.gradle.api.file.Directory import org.gradle.api.file.FileCollection +import org.gradle.api.provider.Provider import org.gradle.api.tasks.TaskProvider import org.jetbrains.kotlin.gradle.internal.KaptTask import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly -import java.io.File import java.util.concurrent.Callable /** @@ -114,9 +115,9 @@ object AndroidPluginIntegration { project: Project, kotlinCompilation: KotlinJvmAndroidCompilation, kspTaskProvider: TaskProvider<*>, - javaOutputDir: File, - kotlinOutputDir: File, - classOutputDir: File, + javaOutputDir: Provider, + kotlinOutputDir: Provider, + classOutputDir: Provider, resourcesOutputDir: FileCollection, ) { val kspJavaOutput = project.fileTree(javaOutputDir).builtBy(kspTaskProvider) @@ -135,9 +136,9 @@ object AndroidPluginIntegration { project: Project, kotlinCompilation: KotlinJvmAndroidCompilation, kspTaskProvider: TaskProvider<*>, - javaOutputDir: File, - kotlinOutputDir: File, - classOutputDir: File, + javaOutputDir: Provider, + kotlinOutputDir: Provider, + classOutputDir: Provider, resourcesOutputDir: FileCollection ) { // Order is important here as we update task with AGP generated sources and diff --git a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KotlinFactories.kt b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KotlinFactories.kt index ef73272fb0..cc03b02f5f 100644 --- a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KotlinFactories.kt +++ b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KotlinFactories.kt @@ -21,10 +21,10 @@ package com.google.devtools.ksp.gradle import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.FileCollection import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.ListProperty -import org.gradle.api.provider.Property import org.gradle.api.provider.ProviderFactory import org.gradle.api.tasks.CacheableTask import org.gradle.api.tasks.IgnoreEmptyDirectories @@ -199,7 +199,7 @@ abstract class KspTaskJvm @Inject constructor( ), KspTask { @get:OutputDirectory - abstract val destination: Property + abstract val destination: DirectoryProperty @get:PathSensitive(PathSensitivity.NONE) @get:Incremental @@ -241,7 +241,8 @@ abstract class KspTaskJvm @Inject constructor( @get:IgnoreEmptyDirectories @get:PathSensitive(PathSensitivity.RELATIVE) override val javaSources: FileCollection = super.javaSources.filter { - !destination.get().isParentOf(it) + // TODO: This is eager realization of destination directory + !destination.get().asFile.isParentOf(it) } } 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 4ec3c8320f..4020eba542 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 @@ -18,7 +18,13 @@ package com.google.devtools.ksp.gradle import com.google.devtools.ksp.impl.KotlinSymbolProcessing -import com.google.devtools.ksp.processing.* +import com.google.devtools.ksp.processing.ExitCode +import com.google.devtools.ksp.processing.KSPCommonConfig +import com.google.devtools.ksp.processing.KSPConfig +import com.google.devtools.ksp.processing.KSPJsConfig +import com.google.devtools.ksp.processing.KSPJvmConfig +import com.google.devtools.ksp.processing.KSPNativeConfig +import com.google.devtools.ksp.processing.KspGradleLogger import org.gradle.api.DefaultTask import org.gradle.api.artifacts.Configuration import org.gradle.api.file.ConfigurableFileCollection @@ -27,9 +33,23 @@ import org.gradle.api.logging.LogLevel import org.gradle.api.provider.ListProperty import org.gradle.api.provider.MapProperty import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider import org.gradle.api.provider.SetProperty -import org.gradle.api.tasks.* +import org.gradle.api.tasks.CacheableTask +import org.gradle.api.tasks.Classpath +import org.gradle.api.tasks.IgnoreEmptyDirectories +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.LocalState +import org.gradle.api.tasks.Nested import org.gradle.api.tasks.Optional +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity +import org.gradle.api.tasks.SkipWhenEmpty +import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.TaskProvider import org.gradle.process.CommandLineArgumentProvider import org.gradle.work.ChangeType import org.gradle.work.Incremental @@ -173,12 +193,14 @@ abstract class KspAATask @Inject constructor( val filteredTasks = kspExtension.excludedSources.buildDependencies.getDependencies(null).map { it.name } kotlinCompilation.allKotlinSourceSetsObservable.forAll { sourceSet -> - val filtered = sourceSet.kotlin.srcDirs.filter { - !kotlinOutputDir.isParentOf(it) && !javaOutputDir.isParentOf(it) && - it !in kspExtension.excludedSources - }.map { - // @SkipWhenEmpty doesn't work well with File. - project.objects.fileTree().from(it) + val filtered = kotlinOutputDir.zip(javaOutputDir) { kotlinOut, javaOut -> + sourceSet.kotlin.srcDirs.filter { + !kotlinOut.asFile.isParentOf(it) && !javaOut.asFile.isParentOf(it) && + it !in kspExtension.excludedSources + }.map { + // @SkipWhenEmpty doesn't work well with File. + project.objects.fileTree().from(it) + } } cfg.sourceRoots.from(filtered) cfg.javaSourceRoots.from(filtered) @@ -199,7 +221,7 @@ abstract class KspAATask @Inject constructor( project.files( Callable { kotlinCompileProvider.get().libraries.filter { - !kspOutputDir.isParentOf(it) && + !kspOutputDir.get().asFile.isParentOf(it) && !kaptGeneratedClassesDir.isParentOf(it) && !(it.isDirectory && it.listFiles()?.isEmpty() == true) } @@ -215,16 +237,16 @@ abstract class KspAATask @Inject constructor( val compilerOptions = kotlinCompilation.compilerOptions.options val langVer = compilerOptions.languageVersion.orNull?.version ?: KSP_KOTLIN_BASE_VERSION val apiVer = compilerOptions.apiVersion.orNull?.version ?: KSP_KOTLIN_BASE_VERSION - cfg.languageVersion.value(langVer.split('.', '-').take(2).joinToString(".")) - cfg.apiVersion.value(apiVer.split('.', '-').take(2).joinToString(".")) - - 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(kotlinOutputDir) - cfg.javaOutputDir.value(javaOutputDir) - cfg.classOutputDir.value(classOutputDir) - cfg.resourceOutputDir.value( + cfg.languageVersion.set(langVer.split('.', '-').take(2).joinToString(".")) + cfg.apiVersion.set(apiVer.split('.', '-').take(2).joinToString(".")) + + cfg.projectBaseDir.set(File(project.project.projectDir.canonicalPath)) + cfg.cachesDir.set(KspGradleSubplugin.getKspCachesDir(project, sourceSetName, target)) + cfg.outputBaseDir.set(KspGradleSubplugin.getKspOutputDir(project, sourceSetName, target)) + cfg.kotlinOutputDir.set(kotlinOutputDir) + cfg.javaOutputDir.set(javaOutputDir) + cfg.classOutputDir.set(classOutputDir) + cfg.resourceOutputDir.set( KspGradleSubplugin.getKspResourceOutputDir( project, sourceSetName, @@ -322,10 +344,11 @@ abstract class KspAATask @Inject constructor( cfg.konanTargetName.value(konanTargetName) cfg.konanHome.value((kotlinCompileProvider.get() as KotlinNativeCompile).konanHome) - val isKlibCrossCompilationEnabled = - project.findProperty("kotlin.native.enableKlibsCrossCompilation") == "true" + val isKlibCrossCompilationEnabled: Provider = project.providers.gradleProperty( + "kotlin.native.enableKlibsCrossCompilation" + ).orElse("false").map { it.toBoolean() } kspAATask.onlyIf { - isKlibCrossCompilationEnabled || HostManager().enabled.any { + isKlibCrossCompilationEnabled.get() || HostManager().enabled.any { it.name == konanTargetName } } @@ -381,22 +404,22 @@ abstract class KspGradleConfig @Inject constructor() { abstract val projectBaseDir: Property @get:Internal - abstract val outputBaseDir: Property + abstract val outputBaseDir: DirectoryProperty @get:LocalState abstract val cachesDir: DirectoryProperty @get:OutputDirectory - abstract val kotlinOutputDir: Property + abstract val kotlinOutputDir: DirectoryProperty @get:OutputDirectory - abstract val javaOutputDir: Property + abstract val javaOutputDir: DirectoryProperty @get:OutputDirectory - abstract val classOutputDir: Property + abstract val classOutputDir: DirectoryProperty @get:OutputDirectory - abstract val resourceOutputDir: Property + abstract val resourceOutputDir: DirectoryProperty @get:Input abstract val languageVersion: Property @@ -487,7 +510,7 @@ abstract class KspAAWorkerAction : WorkAction { // Clean stale files for now. // TODO: support incremental processing. - gradleCfg.outputBaseDir.get().deleteRecursively() + gradleCfg.outputBaseDir.get().asFile.deleteRecursively() val processorClassloader = URLClassLoader( gradleCfg.processorClasspath.files.map { it.toURI().toURL() }.toTypedArray(), @@ -520,11 +543,11 @@ abstract class KspAAWorkerAction : WorkAction { commonSourceRoots = gradleCfg.commonSourceRoots.files.toList() libraries = gradleCfg.libraries.files.toList() projectBaseDir = gradleCfg.projectBaseDir.get() - outputBaseDir = gradleCfg.outputBaseDir.get() + outputBaseDir = gradleCfg.outputBaseDir.get().asFile cachesDir = gradleCfg.cachesDir.get().asFile - kotlinOutputDir = gradleCfg.kotlinOutputDir.get() - classOutputDir = gradleCfg.classOutputDir.get() - resourceOutputDir = gradleCfg.resourceOutputDir.get() + kotlinOutputDir = gradleCfg.kotlinOutputDir.get().asFile + classOutputDir = gradleCfg.classOutputDir.get().asFile + resourceOutputDir = gradleCfg.resourceOutputDir.get().asFile languageVersion = gradleCfg.languageVersion.get() apiVersion = gradleCfg.apiVersion.get() @@ -548,7 +571,7 @@ abstract class KspAAWorkerAction : WorkAction { this.setupSuper() javaSourceRoots = gradleCfg.javaSourceRoots.files.toList() jdkHome = gradleCfg.jdkHome.get() - javaOutputDir = gradleCfg.javaOutputDir.get() + javaOutputDir = gradleCfg.javaOutputDir.get().asFile jvmTarget = gradleCfg.jvmTarget.get() jvmDefaultMode = gradleCfg.jvmDefaultMode.get() }.build() diff --git a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspConfigurations.kt b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspConfigurations.kt index 6dbcc22022..72d78fd301 100644 --- a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspConfigurations.kt +++ b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspConfigurations.kt @@ -96,7 +96,7 @@ class KspConfigurations(private val project: Project) { } // Create sourceSet-specific KSP configurations for the case when the KotlinBaseApiPlugin is applied instead // of the KotlinBasePluginWrapper (e.g., when AGP's built-in Kotlin support is enabled). - project.plugins.withType(KotlinBaseApiPlugin::class.java) { + project.plugins.withType(KotlinBaseApiPlugin::class.java).configureEach { // FIXME: After KT-70897 is fixed and AGP's built-in Kotlin support adds a `kotlin` extension, call // decorateKotlinProject here instead. createAndroidSourceSetConfigurations(project, kotlinTarget = null) 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 7ebaad4b10..7d0c4e7db2 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 @@ -90,27 +90,27 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool const val KSP_PLUGIN_CLASSPATH_CONFIGURATION_NAME_NON_EMBEDDABLE = "kspPluginClasspathNonEmbeddable" @JvmStatic - fun getKspOutputDir(project: Project, sourceSetName: String, target: String) = - project.layout.buildDirectory.file("generated/ksp/$target/$sourceSetName").get().asFile + fun getKspOutputDir(project: Project, sourceSetName: String, target: String): Provider = + project.layout.buildDirectory.dir("generated/ksp/$target/$sourceSetName") @JvmStatic - fun getKspClassOutputDir(project: Project, sourceSetName: String, target: String) = - File(getKspOutputDir(project, sourceSetName, target), "classes") + fun getKspClassOutputDir(project: Project, sourceSetName: String, target: String): Provider = + getKspOutputDir(project, sourceSetName, target).map { it.dir("classes") } @JvmStatic - fun getKspJavaOutputDir(project: Project, sourceSetName: String, target: String) = - File(getKspOutputDir(project, sourceSetName, target), "java") + fun getKspJavaOutputDir(project: Project, sourceSetName: String, target: String): Provider = + getKspOutputDir(project, sourceSetName, target).map { it.dir("java") } @JvmStatic - fun getKspKotlinOutputDir(project: Project, sourceSetName: String, target: String) = - File(getKspOutputDir(project, sourceSetName, target), "kotlin") + fun getKspKotlinOutputDir(project: Project, sourceSetName: String, target: String): Provider = + getKspOutputDir(project, sourceSetName, target).map { it.dir("kotlin") } @JvmStatic - fun getKspResourceOutputDir(project: Project, sourceSetName: String, target: String) = - File(getKspOutputDir(project, sourceSetName, target), "resources") + fun getKspResourceOutputDir(project: Project, sourceSetName: String, target: String): Provider = + getKspOutputDir(project, sourceSetName, target).map { it.dir("resources") } @JvmStatic - fun getKspCachesDir(project: Project, sourceSetName: String, target: String) = + fun getKspCachesDir(project: Project, sourceSetName: String, target: String): Provider = project.layout.buildDirectory.dir("kspCaches/$target/$sourceSetName") @JvmStatic @@ -127,19 +127,24 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool ): Provider> { val options = project.objects.listProperty(SubpluginOption::class.java) options.add( - InternalSubpluginOption("classOutputDir", getKspClassOutputDir(project, sourceSetName, target).path) + getKspClassOutputDir(project, sourceSetName, target).map { + InternalSubpluginOption("classOutputDir", it.asFile.path) + } ) options.add( - InternalSubpluginOption("javaOutputDir", getKspJavaOutputDir(project, sourceSetName, target).path) + getKspJavaOutputDir(project, sourceSetName, target).map { + InternalSubpluginOption("javaOutputDir", it.asFile.path) + } ) options.add( - InternalSubpluginOption("kotlinOutputDir", getKspKotlinOutputDir(project, sourceSetName, target).path) + getKspKotlinOutputDir(project, sourceSetName, target).map { + InternalSubpluginOption("kotlinOutputDir", it.asFile.path) + } ) options.add( - InternalSubpluginOption( - "resourceOutputDir", - getKspResourceOutputDir(project, sourceSetName, target).path - ) + getKspResourceOutputDir(project, sourceSetName, target).map { + InternalSubpluginOption("resourceOutputDir", it.asFile.path) + } ) options.add( cachesDir.map { @@ -147,7 +152,9 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool } ) options.add( - InternalSubpluginOption("kspOutputDir", getKspOutputDir(project, sourceSetName, target).path) + getKspOutputDir(project, sourceSetName, target).map { + InternalSubpluginOption("kspOutputDir", it.asFile.path) + } ) options.add( SubpluginOption("incremental", isIncremental.toString()) @@ -345,25 +352,33 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool resourceOutputDir ) + val kotlinJavaOutDirPairProvider = kotlinOutputDir.zip(javaOutputDir) { kotlinOut, javaOut -> + kotlinOut.asFile to javaOut.asFile + } + @Suppress("DEPRECATION") if (kspExtension.allowSourcesFromOtherPlugins) { val kotlinCompileTask = kotlinCompileProvider.get() - fun setSource(source: FileCollection) { + fun setSource(source: Provider) { // kspTask.setSource(source) would create circular dependency. - // Therefore we need to manually extract input deps, filter them, and tell kspTask. - kspTask.source(project.provider { source.files }) - kspTask.dependsOn(project.provider { source.nonSelfDeps(kspTaskName) }) + // Therefore, we need to manually extract input deps, filter them, and tell kspTask. + kspTask.source(project.provider { source.map { it.files } }) + kspTask.dependsOn(project.provider { source.map { it.nonSelfDeps(kspTaskName) } }) } setSource( - kotlinCompileTask.sources.filter { - !kotlinOutputDir.isParentOf(it) && !javaOutputDir.isParentOf(it) + kotlinJavaOutDirPairProvider.map { (kotlinOut, javaOut) -> + kotlinCompileTask.sources.filter { + !kotlinOut.isParentOf(it) && !javaOut.isParentOf(it) + } } ) if (kotlinCompileTask is KotlinCompile) { setSource( - kotlinCompileTask.javaSources.filter { - !kotlinOutputDir.isParentOf(it) && !javaOutputDir.isParentOf(it) + kotlinJavaOutDirPairProvider.map { (kotlinOut, javaOut) -> + kotlinCompileTask.javaSources.filter { + !kotlinOut.isParentOf(it) && !javaOut.isParentOf(it) + } } ) } @@ -372,9 +387,11 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool kspExtension.excludedSources.buildDependencies.getDependencies(null).map { it.name } kotlinCompilation.allKotlinSourceSetsObservable.forAll { sourceSet -> kspTask.source( - sourceSet.kotlin.srcDirs.filter { - !kotlinOutputDir.isParentOf(it) && !javaOutputDir.isParentOf(it) && - it !in kspExtension.excludedSources + kotlinJavaOutDirPairProvider.map { (kotlinOut, javaOut) -> + sourceSet.kotlin.srcDirs.filter { + !kotlinOut.isParentOf(it) && !javaOut.isParentOf(it) && + it !in kspExtension.excludedSources + } } ) kspTask.dependsOn(sourceSet.kotlin.nonSelfDeps(kspTaskName).filter { it.name !in filteredTasks }) @@ -384,14 +401,14 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool if (kotlinCompilation is KotlinJvmAndroidCompilation) { // Workaround of a dependency resolution issue of AGP. val kaptGeneratedClassesDir = getKaptGeneratedClassesDir(project, sourceSetName) + kspTask.libraries.setFrom( project.files( Callable { kotlinCompileProvider.get().libraries.filter { // manually exclude KAPT generated class folder from class path snapshot. // TODO: remove in 1.9.0. - - !kspOutputDir.isParentOf(it) && + !kspOutputDir.get().asFile.isParentOf(it) && !kaptGeneratedClassesDir.isParentOf(it) && !(it.isDirectory && it.listFiles()?.isEmpty() == true) } @@ -474,14 +491,13 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool KotlinPlatformType.jvm, KotlinPlatformType.androidJvm -> { KotlinFactories.registerKotlinJvmCompileTask(project, kspTaskName, kotlinCompilation).also { it.configure { kspTask -> - val kotlinCompileTask = kotlinCompileProvider.get() as KotlinCompile blockOtherPlugins(kspTask as BaseKotlinCompile) configureAsKspTask(kspTask, isIncremental) configureAsAbstractKotlinCompileTool(kspTask as AbstractKotlinCompileTool<*>) configurePluginOptions(kspTask) configureLanguageVersion(kspTask) - kspTask.destination.value(kspOutputDir) + kspTask.destination.set(kspOutputDir) val classStructureFiles = getClassStructureFiles(project, kspTask.libraries) kspTask.incrementalChangesTransformers.add( @@ -587,7 +603,7 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool // https://docs.gradle.org/7.2/userguide/validation_problems.html#implementation_unknown kspTask.doFirst(object : Action { override fun execute(t: Task) { - kspOutputDir.deleteRecursively() + kspOutputDir.get().asFile.deleteRecursively() } }) }