[Gradle] Optimize KaptGenerateStubs inputs filtering
^KT-53118 Fixed
This commit is contained in:
committed by
Space
parent
d6032be06e
commit
effa12e9a4
-2
@@ -482,8 +482,6 @@ class Kapt3GradleSubplugin @Inject internal constructor(private val registry: To
|
|||||||
taskConfig.configureTask {
|
taskConfig.configureTask {
|
||||||
it.stubsDir.set(getKaptStubsDir())
|
it.stubsDir.set(getKaptStubsDir())
|
||||||
it.destinationDirectory.set(getKaptIncrementalDataDir())
|
it.destinationDirectory.set(getKaptIncrementalDataDir())
|
||||||
val generatedSourcesDirs = listOf(sourcesOutputDir, kotlinSourcesOutputDir)
|
|
||||||
it.exclude { fileElement -> generatedSourcesDirs.any { dir -> dir.isParentOf(fileElement.file) } }
|
|
||||||
it.kaptClasspath.from(kaptClasspathConfigurations)
|
it.kaptClasspath.from(kaptClasspathConfigurations)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+52
-15
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.gradle.tasks.configuration
|
|||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.file.DirectoryProperty
|
import org.gradle.api.file.DirectoryProperty
|
||||||
|
import org.gradle.api.file.FileCollection
|
||||||
import org.gradle.api.provider.Provider
|
import org.gradle.api.provider.Provider
|
||||||
import org.gradle.api.specs.Spec
|
import org.gradle.api.specs.Spec
|
||||||
import org.gradle.api.tasks.TaskProvider
|
import org.gradle.api.tasks.TaskProvider
|
||||||
@@ -21,9 +22,12 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
|
|||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
import org.jetbrains.kotlin.gradle.tasks.CompilerPluginOptions
|
import org.jetbrains.kotlin.gradle.tasks.CompilerPluginOptions
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompilerArgumentsProvider
|
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompilerArgumentsProvider
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.isConfigurationCacheAvailable
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
|
||||||
import org.jetbrains.kotlin.gradle.utils.isParentOf
|
import org.jetbrains.kotlin.gradle.utils.isParentOf
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
internal class KaptGenerateStubsConfig : BaseKotlinCompileConfig<KaptGenerateStubsTask> {
|
internal class KaptGenerateStubsConfig : BaseKotlinCompileConfig<KaptGenerateStubsTask> {
|
||||||
|
|
||||||
@@ -48,13 +52,16 @@ internal class KaptGenerateStubsConfig : BaseKotlinCompileConfig<KaptGenerateStu
|
|||||||
)
|
)
|
||||||
val destinationDirectory = task.destinationDirectory
|
val destinationDirectory = task.destinationDirectory
|
||||||
val stubsDir = task.stubsDir
|
val stubsDir = task.stubsDir
|
||||||
|
val kaptFilterSpec = KaptFilterSpec(destinationDirectory, stubsDir, kaptJavaSourcesDir, kaptKotlinSourcesDir)
|
||||||
|
// FileTree filtering approach fails with configuration cache until Gradle 7.5 leading to failed UP-TO-DATE checks
|
||||||
|
val kaptFilter = if (shouldUseFileTreeKaptFilter) {
|
||||||
|
FileTreeKaptInputsFilter(kaptFilterSpec)
|
||||||
|
} else {
|
||||||
|
FileCollectionKaptInputsFilter(kaptFilterSpec)
|
||||||
|
}
|
||||||
task.source(
|
task.source(
|
||||||
kotlinCompileTask
|
kaptFilter.filtered(kotlinCompileTask.javaSources),
|
||||||
.javaSources
|
kaptFilter.filtered(kotlinCompileTask.sources),
|
||||||
.filter(KaptFilterSpec(destinationDirectory, stubsDir, kaptJavaSourcesDir)),
|
|
||||||
kotlinCompileTask
|
|
||||||
.sources
|
|
||||||
.filter(KaptFilterSpec(destinationDirectory, stubsDir, kaptKotlinSourcesDir))
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,24 +113,54 @@ internal class KaptGenerateStubsConfig : BaseKotlinCompileConfig<KaptGenerateStu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private abstract class CachingKaptInputsFilter {
|
||||||
|
private val filterCache = ConcurrentHashMap<File, Boolean>()
|
||||||
|
abstract fun filtered(fileCollection: FileCollection): FileCollection
|
||||||
|
|
||||||
|
protected fun isSatisfiedBy(file: File) = filterCache[file] ?: predicate(file).also { filterCache[file] = it }
|
||||||
|
|
||||||
|
abstract fun predicate(file: File): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
// Drop `isEmptyDirectory` check after min supported Gradle version will be bumped to 6.8
|
// Drop `isEmptyDirectory` check after min supported Gradle version will be bumped to 6.8
|
||||||
// It will be covered by '@IgnoreEmptyDirectories' input annotation
|
// It will be covered by '@IgnoreEmptyDirectories' input annotation
|
||||||
|
private class FileCollectionKaptInputsFilter(val spec: KaptFilterSpec) : CachingKaptInputsFilter() {
|
||||||
|
override fun filtered(fileCollection: FileCollection): FileCollection {
|
||||||
|
return fileCollection.filter(::isSatisfiedBy)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun predicate(file: File) = !file.isEmptyDirectory && spec.isSatisfiedBy(file)
|
||||||
|
|
||||||
|
private val File.isEmptyDirectory: Boolean
|
||||||
|
get() = with(toPath()) {
|
||||||
|
Files.isDirectory(this) && !Files.list(this).use { it.findFirst().isPresent }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val shouldUseFileTreeKaptFilter
|
||||||
|
get() = isGradleVersionAtLeast(7, 5) || !isConfigurationCacheAvailable(project.gradle) && isGradleVersionAtLeast(6, 8)
|
||||||
|
|
||||||
|
// Filtering through FileTree and PatternFilterable works faster, but adds empty directories which is the problem for Gradle 6.7
|
||||||
|
private class FileTreeKaptInputsFilter(val spec: KaptFilterSpec) : CachingKaptInputsFilter() {
|
||||||
|
override fun filtered(fileCollection: FileCollection): FileCollection {
|
||||||
|
return fileCollection.asFileTree.matching { it.include { elem -> isSatisfiedBy(elem.file) } }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun predicate(file: File) = spec.isSatisfiedBy(file)
|
||||||
|
}
|
||||||
|
|
||||||
private class KaptFilterSpec(
|
private class KaptFilterSpec(
|
||||||
private val destinationDirectory: DirectoryProperty,
|
private val destinationDirectory: DirectoryProperty,
|
||||||
private val stubsDir: DirectoryProperty,
|
private val stubsDir: DirectoryProperty,
|
||||||
private val additionalParentToCheck: File
|
private val kaptJavaSourcesDir: File,
|
||||||
|
private val kaptKotlinSourcesDir: File,
|
||||||
) : Spec<File> {
|
) : Spec<File> {
|
||||||
override fun isSatisfiedBy(element: File): Boolean {
|
override fun isSatisfiedBy(element: File) = element.isSourceRootAllowed()
|
||||||
return !element.isEmptyDirectory &&
|
|
||||||
element.isSourceRootAllowed()
|
|
||||||
}
|
|
||||||
|
|
||||||
private val File.isEmptyDirectory: Boolean
|
|
||||||
get() = with(toPath()) { Files.isDirectory(this) && !Files.list(this).use { it.findFirst().isPresent } }
|
|
||||||
|
|
||||||
private fun File.isSourceRootAllowed(): Boolean =
|
private fun File.isSourceRootAllowed(): Boolean =
|
||||||
!destinationDirectory.get().asFile.isParentOf(this) &&
|
!destinationDirectory.get().asFile.isParentOf(this) &&
|
||||||
!stubsDir.asFile.get().isParentOf(this) &&
|
!stubsDir.asFile.get().isParentOf(this) &&
|
||||||
!additionalParentToCheck.isParentOf(this)
|
!kaptJavaSourcesDir.isParentOf(this) &&
|
||||||
|
!kaptKotlinSourcesDir.isParentOf(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user