From d5e5513dfd42d78fea287adde1c6385277720848 Mon Sep 17 00:00:00 2001 From: Yahor Berdnikau Date: Wed, 23 Mar 2022 19:03:17 +0100 Subject: [PATCH] Revert "AbstractKotlinCompileTool class now also implements PatternFilterable" This reverts commit 0025bf9ed3461a24b99819083c01b263e413fdc3. --- .../gradle/KaptIncrementalWithIsolatingApt.kt | 1 - .../kapt/Kapt3KotlinGradleSubplugin.kt | 4 +- .../internal/kapt/KaptGenerateStubsTask.kt | 82 +++--- .../kotlin/gradle/internal/kapt/KaptTask.kt | 16 +- .../plugin/mpp/KotlinMultiplatformPlugin.kt | 6 +- .../sources/DefaultLanguageSettingsBuilder.kt | 4 +- .../gradle/targets/js/KotlinJsDcePlugin.kt | 2 +- .../gradle/targets/js/ir/KotlinBrowserJsIr.kt | 7 +- .../gradle/targets/js/ir/KotlinJsIrLink.kt | 39 ++- .../gradle/targets/js/ir/KotlinJsIrTarget.kt | 6 +- .../targets/native/tasks/KotlinNativeTasks.kt | 45 ++-- .../gradle/tasks/KotlinCompileCommon.kt | 20 +- .../kotlin/gradle/tasks/KotlinJsDce.kt | 40 +-- .../kotlin/gradle/tasks/SourceRoots.kt | 109 ++++++++ .../jetbrains/kotlin/gradle/tasks/Tasks.kt | 244 ++++++------------ .../kotlin/gradle/utils/fileUtils.kt | 26 -- 16 files changed, 319 insertions(+), 332 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/SourceRoots.kt diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KaptIncrementalWithIsolatingApt.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KaptIncrementalWithIsolatingApt.kt index 0ded560cf85..fe111b75cb8 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KaptIncrementalWithIsolatingApt.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KaptIncrementalWithIsolatingApt.kt @@ -306,7 +306,6 @@ class KaptIncrementalWithIsolatingApt : KaptIncrementalIT() { build(":mylibrary:assembleDebug") { assertEquals( listOf( - "baseLibrary/build/tmp/kapt3/stubs/debug/error/NonExistentClass.java", "mylibrary/src/main/java/com/example/lib/ExampleParcel.java", "baseLibrary/src/main/java/com/example/lib2/basemodule/BaseClassParcel.java", ).map { projectPath.resolve(it).toRealPath().toString() }.toSet(), diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt index 1b86fb8f013..b5cc857e1dc 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt @@ -33,7 +33,6 @@ import org.jetbrains.kotlin.gradle.model.builder.KaptModelBuilder import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation -import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompileTool import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.gradle.tasks.locateTask import org.jetbrains.kotlin.gradle.tasks.registerTask @@ -577,7 +576,8 @@ class Kapt3GradleSubplugin @Inject internal constructor(private val registry: To kotlinCompilation.output.classesDirs.from(kaptTaskProvider.map { it.classesDir }) kotlinCompilation.compileKotlinTaskProvider.configure { - (it as AbstractKotlinCompileTool<*>).setSource(sourcesOutputDir, kotlinSourcesOutputDir) + it as SourceTask + it.source(sourcesOutputDir, kotlinSourcesOutputDir) } if (javaCompile != null) { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptGenerateStubsTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptGenerateStubsTask.kt index fc79e07fd25..abbe5bbda39 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptGenerateStubsTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptGenerateStubsTask.kt @@ -16,8 +16,9 @@ package org.jetbrains.kotlin.gradle.internal -import org.gradle.api.file.* -import org.gradle.api.model.ObjectFactory +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.Directory +import org.gradle.api.file.DirectoryProperty import org.gradle.api.provider.Property import org.gradle.api.provider.Provider import org.gradle.api.tasks.* @@ -28,6 +29,8 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptionsImpl import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData import org.jetbrains.kotlin.gradle.tasks.* +import org.jetbrains.kotlin.gradle.tasks.FilteringSourceRootsContainer +import org.jetbrains.kotlin.gradle.tasks.SourceRoots import org.jetbrains.kotlin.gradle.utils.isParentOf import org.jetbrains.kotlin.incremental.classpathAsList import org.jetbrains.kotlin.incremental.destinationAsFile @@ -36,12 +39,10 @@ import javax.inject.Inject @CacheableTask abstract class KaptGenerateStubsTask @Inject constructor( - workerExecutor: WorkerExecutor, - objectFactory: ObjectFactory -) : KotlinCompile( + workerExecutor: WorkerExecutor +): KotlinCompile( KotlinJvmOptionsImpl(), - workerExecutor, - objectFactory + workerExecutor ) { internal class Configurator( @@ -70,10 +71,23 @@ abstract class KaptGenerateStubsTask @Inject constructor( kotlinCompileTask.compilerArgumentsContributor } ) + task.jvmSourceRoots.set( + providerFactory.provider { + kotlinCompileTask.getSourceRoots().let { compileTaskSourceRoots -> + SourceRoots.ForJvm( + compileTaskSourceRoots.kotlinSourceFiles.filter { task.isSourceRootAllowed(it) }, + compileTaskSourceRoots.javaSourceRoots.filter { task.isSourceRootAllowed(it) } + ) + } + } + ) task.verbose.set(KaptTask.queryKaptVerboseProperty(task.project)) } } + @field:Transient + override val sourceRootsContainer = FilteringSourceRootsContainer(objects, { isSourceRootAllowed(it) }) + @get:OutputDirectory abstract val stubsDir: DirectoryProperty @@ -104,45 +118,28 @@ abstract class KaptGenerateStubsTask @Inject constructor( @get:Incremental abstract val additionalSources: ConfigurableFileCollection - private fun File.isSourceRootAllowed(): Boolean = - !destinationDirectory.get().asFile.isParentOf(this) && - !stubsDir.asFile.get().isParentOf(this) && - generatedSourcesDirs.none { it.isParentOf(this) } + override fun setSource(vararg source: Any) { + super.setSource(sourceRootsContainer.add(sources)) + } - override fun skipCondition(): Boolean = sources.isEmpty && javaSources.isEmpty + override fun setSource(source: Any) { + super.setSource(sourceRootsContainer.set(sources)) + } - // Task need to run even if there is no Kotlin sources, but only Java - @get:Incremental - @get:InputFiles - @get:IgnoreEmptyDirectories - @get:PathSensitive(PathSensitivity.RELATIVE) - override val sources: FileCollection = super.sources - .asFileTree - .matching { patternFilterable -> - patternFilterable.include { it.isDirectory || it.file.isSourceRootAllowed() } - } - - override val javaSources: FileCollection = super.javaSources - .asFileTree - .matching { patternFilterable -> - patternFilterable.include { it.isDirectory || it.file.isSourceRootAllowed() } - } + // TODO: prevent querying destinationDirectory on configuration time + private fun isSourceRootAllowed(source: File): Boolean = + !destinationDirectory.get().asFile.isParentOf(source) && + !stubsDir.asFile.get().isParentOf(source) && + generatedSourcesDirs.none { it.isParentOf(source) } @get:Internal internal abstract val compileKotlinArgumentsContributor: Property> - override fun setupCompilerArgs( - args: K2JVMCompilerArguments, - defaultsOnly: Boolean, - ignoreClasspathResolutionErrors: Boolean - ) { - compileKotlinArgumentsContributor.get().contributeArguments( - args, - compilerArgumentsConfigurationFlags( - defaultsOnly, - ignoreClasspathResolutionErrors - ) - ) + override fun setupCompilerArgs(args: K2JVMCompilerArguments, defaultsOnly: Boolean, ignoreClasspathResolutionErrors: Boolean) { + compileKotlinArgumentsContributor.get().contributeArguments(args, compilerArgumentsConfigurationFlags( + defaultsOnly, + ignoreClasspathResolutionErrors + )) val pluginOptionsWithKapt = pluginOptions.withWrappedKaptOptions(withApClasspath = kaptClasspath) args.pluginOptions = (pluginOptionsWithKapt.arguments + args.pluginOptions!!).toTypedArray() @@ -151,4 +148,9 @@ abstract class KaptGenerateStubsTask @Inject constructor( args.classpathAsList = this.classpath.filter { it.exists() }.toList() args.destinationAsFile = this.destinationDirectory.get().asFile } + + @get:Internal + internal abstract val jvmSourceRoots: Property + + override fun getSourceRoots(): SourceRoots.ForJvm = jvmSourceRoots.get() } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptTask.kt index 77afeff7217..83335ec2935 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptTask.kt @@ -1,10 +1,10 @@ package org.jetbrains.kotlin.gradle.internal -import org.gradle.api.DefaultTask import org.gradle.api.Project import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.FileCollection +import org.gradle.api.internal.ConventionTask import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.ListProperty import org.gradle.api.provider.Property @@ -31,16 +31,20 @@ import javax.inject.Inject @CacheableTask abstract class KaptTask @Inject constructor( objectFactory: ObjectFactory -) : DefaultTask(), +) : ConventionTask(), TaskWithLocalState, UsesKotlinJavaToolchain { open class Configurator(protected val kotlinCompileTask: KotlinCompile) : TaskConfigurator { override fun configure(task: T) { val objectFactory = task.project.objects + val providerFactory = task.project.providers task.compilerClasspath.from({ kotlinCompileTask.defaultCompilerClasspath }) task.classpath.from(kotlinCompileTask.classpath) + task.kotlinSourceRoots.value( + providerFactory.provider { kotlinCompileTask.sourceRootsContainer.sourceRoots } + ).disallowChanges() task.compiledSources.from( kotlinCompileTask.destinationDirectory, Callable { kotlinCompileTask.javaOutputDir.takeIf { it.isPresent } } @@ -48,10 +52,7 @@ abstract class KaptTask @Inject constructor( task.sourceSetName.value(kotlinCompileTask.sourceSetName).disallowChanges() task.localStateDirectories.from(Callable { task.incAptCache.orNull }).disallowChanges() task.source.from( - objectFactory.fileCollection().from( - kotlinCompileTask.javaSources, - task.stubsDir - ).asFileTree + objectFactory.fileCollection().from(task.kotlinSourceRoots, task.stubsDir).asFileTree .matching { it.include("**/*.java") } .filter { f -> task.isRootAllowed(f) } ).disallowChanges() @@ -152,6 +153,9 @@ abstract class KaptTask @Inject constructor( @get:Internal var useBuildCache: Boolean = false + @get:Internal + abstract val kotlinSourceRoots: ListProperty + /** Needed for the model builder. */ @get:Internal abstract val sourceSetName: Property diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt index cf3e3e05b22..75f5bacb284 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt @@ -8,10 +8,12 @@ package org.jetbrains.kotlin.gradle.plugin.mpp import groovy.lang.Closure import org.gradle.api.Plugin import org.gradle.api.Project +import org.gradle.api.attributes.Attribute import org.gradle.api.attributes.AttributeContainer import org.gradle.api.file.DuplicatesStrategy import org.gradle.api.internal.plugins.DslObject import org.gradle.api.plugins.JavaBasePlugin +import org.gradle.api.tasks.SourceTask import org.gradle.api.tasks.TaskProvider import org.gradle.jvm.tasks.Jar import org.gradle.util.ConfigureUtil @@ -24,6 +26,7 @@ import org.jetbrains.kotlin.gradle.internal.customizeKotlinDependencies import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMultiplatformPlugin.Companion.sourceSetFreeCompilerArgsPropertyName import org.jetbrains.kotlin.gradle.plugin.mpp.internal.handleHierarchicalStructureFlagsMigration +import org.jetbrains.kotlin.gradle.plugin.mpp.isMain import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.* import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.hasKpmModel import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.registerDefaultVariantFactories @@ -38,7 +41,6 @@ import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService import org.jetbrains.kotlin.gradle.scripting.internal.ScriptingGradleSubplugin import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTargetPreset import org.jetbrains.kotlin.gradle.targets.native.tasks.artifact.registerKotlinArtifactsExtension -import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompileTool import org.jetbrains.kotlin.gradle.tasks.locateTask import org.jetbrains.kotlin.gradle.tasks.registerTask import org.jetbrains.kotlin.gradle.utils.* @@ -185,7 +187,7 @@ class KotlinMultiplatformPlugin : Plugin { (sourceSet.languageSettings as? DefaultLanguageSettingsBuilder)?.run { compilerPluginOptionsTask = lazy { val associatedCompilation = primaryCompilationsBySourceSet[sourceSet] ?: metadataCompilation - project.tasks.getByName(associatedCompilation.compileKotlinTaskName) as AbstractKotlinCompileTool<*> + project.tasks.getByName(associatedCompilation.compileKotlinTaskName) as SourceTask } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/DefaultLanguageSettingsBuilder.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/DefaultLanguageSettingsBuilder.kt index 8114880d02f..c56eac798e9 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/DefaultLanguageSettingsBuilder.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/DefaultLanguageSettingsBuilder.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.plugin.sources import org.gradle.api.InvalidUserDataException import org.gradle.api.file.FileCollection import org.gradle.api.provider.Provider +import org.gradle.api.tasks.SourceTask import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersion @@ -15,7 +16,6 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions import org.jetbrains.kotlin.gradle.plugin.LanguageSettingsBuilder import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile -import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompileTool import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinNativeCompile import org.jetbrains.kotlin.project.model.LanguageSettings import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics @@ -70,7 +70,7 @@ internal class DefaultLanguageSettingsBuilder : LanguageSettingsBuilder { /* A Kotlin task that is responsible for code analysis of the owner of this language settings builder. */ @Transient // not needed during Gradle Instant Execution - var compilerPluginOptionsTask: Lazy?> = lazyOf(null) + var compilerPluginOptionsTask: Lazy = lazyOf(null) val compilerPluginArguments: List? get() { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsDcePlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsDcePlugin.kt index 39e54039b15..01a3dce42a5 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsDcePlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsDcePlugin.kt @@ -78,7 +78,7 @@ class KotlinJsDcePlugin : Plugin { dceTask.configure { it.classpath.from(configuration) it.destinationDirectory.set(it.dceOptions.outputDirectory?.let { File(it) } ?: outputDir) - it.setSource(kotlinTask.map { task -> (task as Kotlin2JsCompile).outputFileProperty }) + it.setSource((kotlinTask.get() as Kotlin2JsCompile).outputFileProperty) } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinBrowserJsIr.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinBrowserJsIr.kt index 0c42283875c..86ab7a022f0 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinBrowserJsIr.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinBrowserJsIr.kt @@ -101,10 +101,9 @@ open class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) : ), listOf(compilation) ) { task -> - val entryFileProvider = binary.linkSyncTask.flatMap { syncTask -> - binary.linkTask.map { - syncTask.destinationDir.resolve(it.outputFileProperty.get().name) - } + val entryFileProvider = binary.linkSyncTask.map { + it.destinationDir + .resolve(binary.linkTask.get().outputFileProperty.get().name) } webpackMajorVersion.choose( diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrLink.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrLink.kt index 24c0e0bfe0a..d078b824f23 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrLink.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrLink.kt @@ -7,7 +7,6 @@ package org.jetbrains.kotlin.gradle.targets.js.ir import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.DirectoryProperty -import org.gradle.api.file.FileCollection import org.gradle.api.file.ProjectLayout import org.gradle.api.model.ObjectFactory import org.gradle.api.tasks.* @@ -26,6 +25,7 @@ import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBinaryMode.DEVELOPMENT import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBinaryMode.PRODUCTION import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile import org.jetbrains.kotlin.gradle.utils.getValue +import org.jetbrains.kotlin.gradle.utils.property import org.jetbrains.kotlin.gradle.utils.toHexString import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics import org.jetbrains.kotlin.statistics.metrics.StringMetrics @@ -57,18 +57,6 @@ abstract class KotlinJsIrLink @Inject constructor( } } - init { - // Not check sources, only klib module - disallowSourceChanges() - } - - @get:Internal - override val sources: FileCollection = super.sources - - override fun skipCondition(): Boolean { - return !entryModule.get().asFile.exists() - } - @Transient @get:Internal internal lateinit var compilation: KotlinCompilationData<*> @@ -93,6 +81,10 @@ abstract class KotlinJsIrLink @Inject constructor( @Input lateinit var mode: KotlinJsBinaryMode + // Not check sources, only klib module + @get:Internal + abstract override val sources: ConfigurableFileCollection + private val buildDir = project.buildDir @get:SkipWhenEmpty @@ -101,24 +93,23 @@ abstract class KotlinJsIrLink @Inject constructor( @get:PathSensitive(PathSensitivity.RELATIVE) internal abstract val entryModule: DirectoryProperty - @get:Internal - override val destinationDirectory: DirectoryProperty = objectFactory.directoryProperty() - - @get:OutputDirectory - val normalizedDestinationDirectory: DirectoryProperty = objectFactory - .directoryProperty() - .apply { + override val destinationDirectory: DirectoryProperty + get() = objectFactory.directoryProperty().apply { set( - destinationDirectory.map { dir -> - if (kotlinOptions.outputFile != null) { - projectLayout.dir(outputFileProperty.map { it.parentFile }).get() + destinationDirectory.flatMap { dir -> + if (kotlinOptions.outputFile == null) { + objectFactory.property(dir) } else { - dir + projectLayout.dir(outputFileProperty.map { it.parentFile }) } } ) } + override fun skipCondition(): Boolean { + return !entryModule.get().asFile.exists() + } + @get:Internal val rootCacheDirectory by lazy { buildDir.resolve("klib/cache") diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrTarget.kt index 1a81e460833..183095f792f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrTarget.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrTarget.kt @@ -136,11 +136,7 @@ constructor( binary.linkSyncTaskName ) { task -> task.from( - project.layout.file( - binary.linkTask.flatMap { linkTask -> - linkTask.normalizedDestinationDirectory.map { it.asFile } - } - ) + project.layout.file(binary.linkTask.flatMap { it.destinationDirectory.map { it.asFile } }) ) task.from(project.tasks.named(compilation.processResourcesTaskName)) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeTasks.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeTasks.kt index c5d865d9599..329e66dd37a 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeTasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeTasks.kt @@ -18,7 +18,6 @@ import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.FileCollection import org.gradle.api.file.FileTree -import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.Provider import org.gradle.api.tasks.* import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments @@ -133,10 +132,7 @@ abstract class AbstractKotlinNativeCompile< T : KotlinCommonToolOptions, K : KotlinNativeCompilationData<*>, M : CommonToolArguments - > -@Inject constructor( - private val objectFactory: ObjectFactory -): AbstractKotlinCompileTool(objectFactory) { + > : AbstractKotlinCompileTool() { @get:Internal abstract val compilation: K @@ -153,6 +149,9 @@ abstract class AbstractKotlinNativeCompile< @get:Internal abstract val baseName: String + @get:Internal + protected val objects = project.objects + @get:Internal protected val konanTarget by project.provider { compilation.konanTarget @@ -163,7 +162,7 @@ abstract class AbstractKotlinNativeCompile< // Avoid resolving these dependencies during task graph construction when we can't build the target: if (konanTarget.enabledOnCurrentHost) compilation.compileDependencyFiles.filterOutPublishableInteropLibs(project) - else objectFactory.fileCollection() + else objects.fileCollection() } @get:Classpath @@ -173,7 +172,7 @@ abstract class AbstractKotlinNativeCompile< @Deprecated("For native tasks use 'libraries' instead", ReplaceWith("libraries")) override val classpath: ConfigurableFileCollection - get() = objectFactory.fileCollection().from(libraries) + get() = objects.fileCollection().from(libraries) @get:Input val target: String by project.provider { compilation.konanTarget.name } @@ -210,7 +209,7 @@ abstract class AbstractKotlinNativeCompile< @get:Internal open val outputFile: Provider - get() = destinationDirectory.flatMap { + get() = destinationDirectory.map { val prefix = outputKind.prefix(konanTarget) val suffix = outputKind.suffix(konanTarget) val filename = "$prefix${baseName}$suffix".let { @@ -223,7 +222,7 @@ abstract class AbstractKotlinNativeCompile< } } - objectFactory.property(it.file(filename).asFile) + it.file(filename).asFile } // endregion @@ -310,9 +309,8 @@ abstract class KotlinNativeCompile constructor( @Internal @Transient // can't be serialized for Gradle configuration cache - final override val compilation: KotlinNativeCompilationData<*>, - objectFactory: ObjectFactory -) : AbstractKotlinNativeCompile, StubK2NativeCompilerArguments>(objectFactory), + final override val compilation: KotlinNativeCompilationData<*> +) : AbstractKotlinNativeCompile, StubK2NativeCompilerArguments>(), KotlinCompile { @get:Input @@ -465,9 +463,8 @@ abstract class KotlinNativeLink @Inject constructor( @Internal - val binary: NativeBinary, - objectFactory: ObjectFactory -) : AbstractKotlinNativeCompile(objectFactory) { + val binary: NativeBinary +) : AbstractKotlinNativeCompile() { @get:Internal final override val compilation: KotlinNativeCompilation get() = binary.compilation @@ -477,13 +474,17 @@ constructor( // Frameworks actively uses symlinks. // Gradle build cache transforms symlinks into regular files https://guides.gradle.org/using-build-cache/#symbolic_links outputs.cacheIf { outputKind != FRAMEWORK } - - this.setSource(compilation.compileKotlinTask.outputFile) - includes.clear() // we need to include non '.kt' or '.kts' files - disallowSourceChanges() } - override val destinationDirectory: DirectoryProperty = objectFactory.directoryProperty().apply { + @Internal // Taken into account by getSources(). + val intermediateLibrary: Provider = project.provider { compilation.compileKotlinTask.outputFile.get() } + + override val sources: ConfigurableFileCollection = objects + .fileCollection() + .from(intermediateLibrary) + .apply { disallowChanges() } + + override val destinationDirectory: DirectoryProperty = objects.directoryProperty().apply { set(binary.outputDirectory) } @@ -552,7 +553,7 @@ constructor( if (it is AbstractNativeLibrary) { project.configurations.getByName(it.exportConfigurationName) } else { - objectFactory.fileCollection() + objects.fileCollection() } } } @@ -651,7 +652,7 @@ constructor( binaryOptions, isStaticFramework, exportLibraries.files.filterKlibsPassedToCompiler(), - sources.asFileTree.files.toList(), + listOf(intermediateLibrary.get()), externalDependenciesArgs + cacheArgs ) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinCompileCommon.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinCompileCommon.kt index 8b7fe7c3feb..07afea53b22 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinCompileCommon.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinCompileCommon.kt @@ -18,7 +18,6 @@ package org.jetbrains.kotlin.gradle.tasks import org.gradle.api.Project import org.gradle.api.file.ConfigurableFileCollection -import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.Provider import org.gradle.api.tasks.* import org.gradle.work.InputChanges @@ -47,10 +46,8 @@ import javax.inject.Inject @CacheableTask abstract class KotlinCompileCommon @Inject constructor( override val kotlinOptions: KotlinMultiplatformCommonOptions, - workerExecutor: WorkerExecutor, - objectFactory: ObjectFactory -) : AbstractKotlinCompile(objectFactory), - KotlinCommonCompile { + workerExecutor: WorkerExecutor +) : AbstractKotlinCompile(), KotlinCommonCompile { class Configurator(compilation: KotlinCompilationData<*>) : AbstractKotlinCompile.Configurator(compilation) { override fun configure(task: KotlinCompileCommon) { @@ -88,7 +85,7 @@ abstract class KotlinCompileCommon @Inject constructor( } override val compilerRunner: Provider = - objectFactory.propertyWithConvention( + objects.propertyWithConvention( gradleCompileTaskProvider.map { GradleCompilerRunnerWithWorkers( it, @@ -104,6 +101,9 @@ abstract class KotlinCompileCommon @Inject constructor( override fun createCompilerArgs(): K2MetadataCompilerArguments = K2MetadataCompilerArguments() + override fun getSourceRoots(): SourceRoots = + SourceRoots.KotlinOnly.create(sources, sourceFilesExtensions.get()) + override fun setupCompilerArgs(args: K2MetadataCompilerArguments, defaultsOnly: Boolean, ignoreClasspathResolutionErrors: Boolean) { args.apply { fillDefaultValues() } super.setupCompilerArgs(args, defaultsOnly = defaultsOnly, ignoreClasspathResolutionErrors = ignoreClasspathResolutionErrors) @@ -132,14 +132,14 @@ abstract class KotlinCompileCommon @Inject constructor( @get:PathSensitive(PathSensitivity.RELATIVE) @get:IgnoreEmptyDirectories @get:InputFiles - internal val refinesMetadataPaths: ConfigurableFileCollection = objectFactory.fileCollection() + internal val refinesMetadataPaths: ConfigurableFileCollection = objects.fileCollection() @get:Internal - internal val expectActualLinker = objectFactory.property(Boolean::class.java) + internal val expectActualLinker = objects.property(Boolean::class.java) override fun callCompilerAsync( args: K2MetadataCompilerArguments, - kotlinSources: Set, + sourceRoots: SourceRoots, inputChanges: InputChanges, taskOutputsBackup: TaskOutputsBackup? ) { @@ -152,7 +152,7 @@ abstract class KotlinCompileCommon @Inject constructor( outputFiles = allOutputFiles() ) compilerRunner.runMetadataCompilerAsync( - kotlinSources.toList(), + sourceRoots.kotlinSourceFiles.files.toList(), commonSourceSet.files.toList(), args, environment diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinJsDce.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinJsDce.kt index 009e7618c72..60fe655b2a4 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinJsDce.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinJsDce.kt @@ -16,12 +16,11 @@ package org.jetbrains.kotlin.gradle.tasks -import org.gradle.api.file.ConfigurableFileCollection -import org.gradle.api.file.FileCollection -import org.gradle.api.model.ObjectFactory -import org.gradle.api.tasks.* +import org.gradle.api.tasks.CacheableTask +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.TaskAction import org.gradle.work.ChangeType -import org.gradle.work.Incremental import org.gradle.work.InputChanges import org.jetbrains.kotlin.cli.common.arguments.DevModeOverwritingStrategies import org.jetbrains.kotlin.cli.common.arguments.K2JSDceArguments @@ -32,22 +31,18 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinJsDceOptions import org.jetbrains.kotlin.gradle.dsl.KotlinJsDceOptionsImpl import org.jetbrains.kotlin.gradle.logging.GradleKotlinLogger import org.jetbrains.kotlin.gradle.utils.canonicalPathWithoutExtension -import org.jetbrains.kotlin.gradle.utils.fileExtensionCasePermutations import java.io.File -import javax.inject.Inject @CacheableTask -abstract class KotlinJsDce @Inject constructor( - objectFactory: ObjectFactory -) : AbstractKotlinCompileTool(objectFactory), - KotlinJsDce { +abstract class KotlinJsDce : AbstractKotlinCompileTool(), KotlinJsDce { init { cacheOnlyIfEnabledForKotlin() - - include("js".fileExtensionCasePermutations().map { "**/*.$it" }) } + @get:Internal + internal val objects = project.objects + override fun createCompilerArgs(): K2JSDceArguments = K2JSDceArguments() override fun setupCompilerArgs(args: K2JSDceArguments, defaultsOnly: Boolean, ignoreClasspathResolutionErrors: Boolean) { @@ -75,18 +70,9 @@ abstract class KotlinJsDce @Inject constructor( @Input var jvmArgs = mutableListOf() - // Source could be empty, while classpath not - @get:Incremental - @get:InputFiles - @get:IgnoreEmptyDirectories - @get:PathSensitive(PathSensitivity.RELATIVE) - override val sources: FileCollection = super.sources - - @get:Incremental - @get:InputFiles - abstract override val classpath: ConfigurableFileCollection - - private val buildDir = project.layout.buildDirectory + private val buildDir by lazy { + project.buildDir + } private val isDevMode get() = dceOptions.devMode || "-dev-mode" in dceOptions.freeCompilerArgs @@ -109,7 +95,7 @@ abstract class KotlinJsDce @Inject constructor( } else { classpath.asFileTree.files } - + // TODO: use PatternFilterable here! val inputFiles = sources.asFileTree.files.plus(classpathFiles) .filter { !kotlinFilesOnly || isDceCandidate(it) } .map { it.path } @@ -134,7 +120,7 @@ abstract class KotlinJsDce @Inject constructor( K2JSDce::class.java.name, defaultCompilerClasspath, log, - buildDir.get().asFile, + buildDir, jvmArgs ) throwGradleExceptionIfError(exitCode, KotlinCompilerExecutionStrategy.OUT_OF_PROCESS) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/SourceRoots.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/SourceRoots.kt new file mode 100644 index 00000000000..1c7d7076c02 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/SourceRoots.kt @@ -0,0 +1,109 @@ +package org.jetbrains.kotlin.gradle.tasks + +import org.gradle.api.file.FileCollection +import org.gradle.api.file.FileTree +import org.gradle.api.file.SourceDirectorySet +import org.gradle.api.logging.Logger +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Provider +import org.jetbrains.kotlin.gradle.logging.kotlinDebug +import org.jetbrains.kotlin.gradle.utils.isJavaFile +import org.jetbrains.kotlin.gradle.utils.isKotlinFile +import org.jetbrains.kotlin.gradle.utils.isParentOf +import java.io.File +import java.util.concurrent.Callable + +internal sealed class SourceRoots(val kotlinSourceFiles: FileCollection) { + private companion object { + fun dumpPaths(files: Iterable): String = + "[${files.map { it.canonicalPath }.sorted().joinToString(prefix = "\n\t", separator = ",\n\t")}]" + } + + open fun log(taskName: String, logger: Logger) { + logger.kotlinDebug { "$taskName source roots: ${dumpPaths(kotlinSourceFiles.files)}" } + } + + class ForJvm constructor( + kotlinSourceFiles: FileCollection, + val javaSourceRoots: FileCollection + ) : SourceRoots(kotlinSourceFiles) { + + companion object { + fun create( + taskSource: FileCollection, + sourceRoots: FilteringSourceRootsContainer, + sourceFilesExtensions: List + ): ForJvm { + return ForJvm( + taskSource.filter { it.isKotlinFile(sourceFilesExtensions) }, + sourceRoots.sourceRoots.filterJavaRoots( + taskSource.filter { it.isJavaFile() } + ) + ) + } + + private fun FileCollection.filterJavaRoots( + sourceDirs: FileCollection + ): FileCollection = filter { sourceRoot -> + sourceDirs.asSequence().map { it.parentFile }.any { sourceRoot.isParentOf(it) } + } + } + + override fun log(taskName: String, logger: Logger) { + super.log(taskName, logger) + logger.kotlinDebug { "$taskName java source roots: ${dumpPaths(javaSourceRoots.files)}" } + } + } + + class KotlinOnly(kotlinSourceFiles: FileCollection) : SourceRoots(kotlinSourceFiles) { + companion object { + fun create( + taskSource: FileCollection, + sourceFilesExtensions: List + ) = KotlinOnly( + taskSource.filter { it.isKotlinFile(sourceFilesExtensions) } + ) + } + } +} + +internal class FilteringSourceRootsContainer( + private val objectFactory: ObjectFactory, + val filter: (File) -> Boolean = { true } +) { + private val sourceContainers: MutableList = mutableListOf() + + private fun getFilteredSourceRootsFrom(any: Any) = objectFactory.fileCollection().from(Callable { + val resultItems = mutableListOf() + fun getRootsFrom(item: Any?) { + when (item) { + is SourceDirectorySet -> resultItems.add(item.sourceDirectories) + is Callable<*> -> getRootsFrom(item.call()) + is Provider<*> -> if (item.isPresent) getRootsFrom(item.get()) + is FileCollection -> resultItems.add(item) + is Iterable<*> -> item.forEach { getRootsFrom(it) } + is Array<*> -> item.forEach { getRootsFrom(it) } + is Any /* not null */ -> resultItems.add(item) + } + } + getRootsFrom(any) + resultItems + }).filter(filter) + + val sourceRoots: FileCollection + get() = getFilteredSourceRootsFrom(sourceContainers) + + fun clear() { + sourceContainers.clear() + } + + fun set(source: Any): FileCollection { + clear() + return add(source) + } + + fun add(vararg sources: Any): FileCollection { + sourceContainers.addAll(sources.toList()) + return getFilteredSourceRootsFrom(sources) + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt index 1064f5e8ff3..f9d73cbc00b 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.gradle.tasks -import groovy.lang.Closure import org.gradle.api.DefaultTask import org.gradle.api.GradleException import org.gradle.api.Project @@ -20,12 +19,10 @@ import org.gradle.api.provider.Property import org.gradle.api.provider.Provider import org.gradle.api.services.BuildService import org.gradle.api.services.BuildServiceParameters -import org.gradle.api.specs.Spec import org.gradle.api.tasks.* import org.gradle.api.tasks.compile.AbstractCompile import org.gradle.api.tasks.compile.JavaCompile import org.gradle.api.tasks.util.PatternFilterable -import org.gradle.api.tasks.util.PatternSet import org.gradle.work.ChangeType import org.gradle.work.Incremental import org.gradle.work.InputChanges @@ -60,10 +57,13 @@ import org.jetbrains.kotlin.gradle.report.BuildReportMode import org.jetbrains.kotlin.gradle.report.ReportingSettings import org.jetbrains.kotlin.gradle.targets.js.ir.isProduceUnzippedKlib import org.jetbrains.kotlin.gradle.utils.* -import org.jetbrains.kotlin.incremental.* +import org.jetbrains.kotlin.incremental.ChangedFiles +import org.jetbrains.kotlin.incremental.ClasspathChanges import org.jetbrains.kotlin.incremental.ClasspathChanges.ClasspathSnapshotDisabled import org.jetbrains.kotlin.incremental.ClasspathChanges.ClasspathSnapshotEnabled.* import org.jetbrains.kotlin.incremental.ClasspathChanges.ClasspathSnapshotEnabled.IncrementalRun.* +import org.jetbrains.kotlin.incremental.ClasspathSnapshotFiles +import org.jetbrains.kotlin.incremental.IncrementalCompilerRunner import org.jetbrains.kotlin.library.impl.isKotlinLibrary import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics import org.jetbrains.kotlin.utils.JsLibraryUtils @@ -77,44 +77,24 @@ const val USING_JVM_INCREMENTAL_COMPILATION_MESSAGE = "Using Kotlin/JVM incremen const val USING_JS_INCREMENTAL_COMPILATION_MESSAGE = "Using Kotlin/JS incremental compilation" const val USING_JS_IR_BACKEND_MESSAGE = "Using Kotlin/JS IR backend" -abstract class AbstractKotlinCompileTool @Inject constructor( - objectFactory: ObjectFactory -) : DefaultTask(), - PatternFilterable, +abstract class AbstractKotlinCompileTool + : DefaultTask(), + //PatternFilterable, CompilerArgumentAwareWithInput, TaskWithLocalState { - private val patternFilterable = PatternSet() - - init { - patternFilterable.include( - DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS.flatMap { ext -> ext.fileExtensionCasePermutations().map { "**/*.$it" } } - ) - } - - private val sourceFiles = objectFactory.fileCollection() - @get:InputFiles @get:SkipWhenEmpty @get:IgnoreEmptyDirectories @get:PathSensitive(PathSensitivity.RELATIVE) - open val sources: FileCollection = objectFactory.fileCollection() - .from( - { sourceFiles.asFileTree.matching(patternFilterable) } - ) - - @Deprecated("Use PatternFilterable methods to configure sources") - @get:Input - val sourceFilesExtensions: ListProperty = objectFactory - .listProperty(String::class.java) - .convention(DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS) + abstract val sources: ConfigurableFileCollection /** * Sets the source for this task. * The given source object is evaluated as per [org.gradle.api.Project.files]. */ open fun setSource(source: Any) { - sourceFiles.from(source) + sources.from(source) } /** @@ -122,57 +102,7 @@ abstract class AbstractKotlinCompileTool @Inject constr * The given source object is evaluated as per [org.gradle.api.Project.files]. */ open fun setSource(vararg source: Any) { - sourceFiles.from(source) - } - - fun disallowSourceChanges() { - sourceFiles.disallowChanges() - } - - @Internal - final override fun getIncludes(): MutableSet = patternFilterable.includes - - @Internal - final override fun getExcludes(): MutableSet = patternFilterable.excludes - - final override fun setIncludes(includes: Iterable): PatternFilterable = also { - patternFilterable.setIncludes(includes) - } - - final override fun setExcludes(excludes: Iterable): PatternFilterable = also { - patternFilterable.setExcludes(excludes) - } - - final override fun include(vararg includes: String?): PatternFilterable = also { - patternFilterable.include(*includes) - } - - final override fun include(includes: Iterable): PatternFilterable = also { - patternFilterable.include(includes) - } - - final override fun include(includeSpec: Spec): PatternFilterable = also { - patternFilterable.include(includeSpec) - } - - final override fun include(includeSpec: Closure<*>): PatternFilterable = also { - patternFilterable.include(includeSpec) - } - - final override fun exclude(vararg excludes: String?): PatternFilterable = also { - patternFilterable.exclude(*excludes) - } - - final override fun exclude(excludes: Iterable): PatternFilterable = also { - patternFilterable.exclude(excludes) - } - - final override fun exclude(excludeSpec: Spec): PatternFilterable = also { - patternFilterable.exclude(excludeSpec) - } - - final override fun exclude(excludeSpec: Closure<*>): PatternFilterable = also { - patternFilterable.exclude(excludeSpec) + sources.from(source) } @get:Classpath @@ -257,9 +187,7 @@ abstract class GradleCompileTaskProvider @Inject constructor( ) } -abstract class AbstractKotlinCompile @Inject constructor( - objectFactory: ObjectFactory -) : AbstractKotlinCompileTool(objectFactory), +abstract class AbstractKotlinCompile : AbstractKotlinCompileTool(), CompileUsingKotlinDaemonWithNormalization { open class Configurator>(protected val compilation: KotlinCompilationData<*>) : TaskConfigurator { @@ -310,13 +238,16 @@ abstract class AbstractKotlinCompile @Inject constr @get:Inject internal abstract val fileSystemOperations: FileSystemOperations + @get:Internal + protected val objects: ObjectFactory = project.objects + // avoid creating directory in getter: this can lead to failure in parallel build @get:OutputDirectory - internal val taskBuildCacheableOutputDirectory: DirectoryProperty = objectFactory.directoryProperty() + internal val taskBuildCacheableOutputDirectory: DirectoryProperty = objects.directoryProperty() // avoid creating directory in getter: this can lead to failure in parallel build @get:LocalState - internal val taskBuildLocalStateDirectory: DirectoryProperty = objectFactory.directoryProperty() + internal val taskBuildLocalStateDirectory: DirectoryProperty = objects.directoryProperty() @get:Internal internal val buildHistoryFile @@ -346,18 +277,20 @@ abstract class AbstractKotlinCompile @Inject constr internal fun reportingSettings() = buildMetricsReporterService.orNull?.parameters?.reportingSettings ?: ReportingSettings() @get:Input - internal val useModuleDetection: Property = objectFactory.property(Boolean::class.java).value(false) + internal val useModuleDetection: Property = objects.property(Boolean::class.java).value(false) @get:Internal protected val multiModuleICSettings: MultiModuleICSettings get() = MultiModuleICSettings(buildHistoryFile.get().asFile, useModuleDetection.get()) @get:Classpath - open val pluginClasspath: ConfigurableFileCollection = objectFactory.fileCollection() + open val pluginClasspath: ConfigurableFileCollection = objects.fileCollection() @get:Internal internal val pluginOptions = CompilerPluginOptions() + @get:Input + val sourceFilesExtensions: ListProperty = objects.listProperty(String::class.java).value(DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS) /** * Plugin Data provided by [KpmCompilerPlugin] @@ -369,52 +302,52 @@ abstract class AbstractKotlinCompile @Inject constr // Input is needed to force rebuild even if source files are not changed @get:Input - internal val coroutines: Property = objectFactory.property(Coroutines::class.java) + internal val coroutines: Property = objects.property(Coroutines::class.java) @get:Internal - internal val javaOutputDir: DirectoryProperty = objectFactory.directoryProperty() + internal val javaOutputDir: DirectoryProperty = objects.directoryProperty() @get:Internal - internal val sourceSetName: Property = objectFactory.property(String::class.java) + internal val sourceSetName: Property = objects.property(String::class.java) @get:InputFiles @get:IgnoreEmptyDirectories @get:Incremental @get:PathSensitive(PathSensitivity.RELATIVE) - internal val commonSourceSet: ConfigurableFileCollection = objectFactory.fileCollection() + internal val commonSourceSet: ConfigurableFileCollection = objects.fileCollection() @get:Input - internal val moduleName: Property = objectFactory.property(String::class.java) + internal val moduleName: Property = objects.property(String::class.java) @get:Internal val abiSnapshotFile get() = taskBuildCacheableOutputDirectory.file(IncrementalCompilerRunner.ABI_SNAPSHOT_FILE_NAME) @get:Input - val abiSnapshotRelativePath: Property = objectFactory.property(String::class.java).value( + val abiSnapshotRelativePath: Property = objects.property(String::class.java).value( //TODO update to support any jar changes "$name/${IncrementalCompilerRunner.ABI_SNAPSHOT_FILE_NAME}" ) @get:Internal - internal val friendSourceSets = objectFactory.listProperty(String::class.java) + internal val friendSourceSets = objects.listProperty(String::class.java) @get:Internal // takes part in the compiler arguments - val friendPaths: ConfigurableFileCollection = objectFactory.fileCollection() + val friendPaths: ConfigurableFileCollection = objects.fileCollection() private val kotlinLogger by lazy { GradleKotlinLogger(logger) } abstract override val kotlinDaemonJvmArguments: ListProperty @get:Internal - protected val gradleCompileTaskProvider: Provider = objectFactory + protected val gradleCompileTaskProvider: Provider = objects .property( - objectFactory.newInstance(project.gradle, this, project) + objects.newInstance(project.gradle, this, project) ) @get:Internal internal open val compilerRunner: Provider = - objectFactory.propertyWithConvention( + objects.propertyWithConvention( gradleCompileTaskProvider.map { GradleCompilerRunner( it, @@ -477,7 +410,8 @@ abstract class AbstractKotlinCompile @Inject constr buildMetricsReporterService.orNull?.also { it.addTask(path, this.javaClass, buildMetrics) } } - protected open fun skipCondition(): Boolean = sources.isEmpty + protected open fun skipCondition(): Boolean = + getSourceRoots().kotlinSourceFiles.isEmpty() private val projectDir = project.rootProject.projectDir @@ -493,7 +427,8 @@ abstract class AbstractKotlinCompile @Inject constr inputChanges: InputChanges, taskOutputsBackup: TaskOutputsBackup? ) { - val allKotlinSources = sources.asFileTree.files + val sourceRoots = getSourceRoots() + val allKotlinSources = sourceRoots.kotlinSourceFiles logger.kotlinDebug { "All kotlin sources: ${allKotlinSources.pathsAsStringRelativeTo(projectDir)}" } @@ -503,12 +438,13 @@ abstract class AbstractKotlinCompile @Inject constr return } + sourceRoots.log(this.name, logger) val args = prepareCompilerArguments() taskBuildCacheableOutputDirectory.get().asFile.mkdirs() taskBuildLocalStateDirectory.get().asFile.mkdirs() callCompilerAsync( args, - allKotlinSources, + sourceRoots, inputChanges, taskOutputsBackup ) @@ -536,19 +472,22 @@ abstract class AbstractKotlinCompile @Inject constr } } + @Internal + internal abstract fun getSourceRoots(): SourceRoots + /** * Compiler might be executed asynchronously. Do not do anything requiring end of compilation after this function is called. * @see [GradleKotlinCompilerWork] */ internal abstract fun callCompilerAsync( args: T, - kotlinSources: Set, + sourceRoots: SourceRoots, inputChanges: InputChanges, taskOutputsBackup: TaskOutputsBackup? ) @get:Input - internal val multiPlatformEnabled: Property = objectFactory.property(Boolean::class.java) + internal val multiPlatformEnabled: Property = objects.property(Boolean::class.java) @get:Internal internal val abstractKotlinCompileArgumentsContributor by lazy { @@ -597,9 +536,8 @@ internal inline val T.thisTaskProvider: TaskProvider @CacheableTask abstract class KotlinCompile @Inject constructor( override val kotlinOptions: KotlinJvmOptions, - workerExecutor: WorkerExecutor, - private val objectFactory: ObjectFactory -) : AbstractKotlinCompile(objectFactory), + workerExecutor: WorkerExecutor +) : AbstractKotlinCompile(), KotlinJvmCompile, UsesKotlinJavaToolchain { @@ -697,7 +635,16 @@ abstract class KotlinCompile @Inject constructor( } @get:Internal - internal val parentKotlinOptionsImpl: Property = objectFactory.property(KotlinJvmOptions::class.java) + internal val parentKotlinOptionsImpl: Property = objects.property(KotlinJvmOptions::class.java) + + @get:Internal + @field:Transient + internal open val sourceRootsContainer = FilteringSourceRootsContainer(objects) + + private val jvmSourceRoots by project.provider { + // serialize in the task state for configuration caching; avoid building anew in task execution, as it may access the project model + SourceRoots.ForJvm.create(sources, sourceRootsContainer, sourceFilesExtensions.get()) + } /** A package prefix that is used for locating Java sources in a directory structure with non-full-depth packages. * @@ -744,29 +691,23 @@ abstract class KotlinCompile @Inject constructor( } override val incrementalProps: List - get() = listOf( - sources, - javaSources, - commonSourceSet, - classpathSnapshotProperties.classpath, - classpathSnapshotProperties.classpathSnapshot - ) + get() = listOf(sources, commonSourceSet, classpathSnapshotProperties.classpath, classpathSnapshotProperties.classpathSnapshot) // Exclude classpathSnapshotDir from TaskOutputsBackup (see TaskOutputsBackup's kdoc for more info). */ override val taskOutputsBackupExcludes: List get() = classpathSnapshotProperties.classpathSnapshotDir.orNull?.asFile?.let { listOf(it) } ?: emptyList() @get:Internal - internal val defaultKotlinJavaToolchain: Provider = objectFactory + internal val defaultKotlinJavaToolchain: Provider = objects .propertyWithNewInstance({ this }) final override val kotlinJavaToolchainProvider: Provider = defaultKotlinJavaToolchain.cast() @get:Internal - override val compilerRunner: Provider = objectFactory.propertyWithConvention( + override val compilerRunner: Provider = objects.propertyWithConvention( // From Gradle 6.6 better to replace flatMap with provider.zip() defaultKotlinJavaToolchain.flatMap { toolchain -> - objectFactory.property(gradleCompileTaskProvider.map { + objects.property(gradleCompileTaskProvider.map { GradleCompilerRunnerWithWorkers( it, toolchain.currentJvmJdkToolsJar.orNull, @@ -821,13 +762,17 @@ abstract class KotlinCompile @Inject constructor( KotlinJvmCompilerArgumentsContributor(KotlinJvmCompilerArgumentsProvider(this)) } + override fun getSourceRoots(): SourceRoots.ForJvm = jvmSourceRoots + override fun callCompilerAsync( args: K2JVMCompilerArguments, - kotlinSources: Set, + sourceRoots: SourceRoots, inputChanges: InputChanges, taskOutputsBackup: TaskOutputsBackup? ) { - validateKotlinAndJavaHasSameTargetCompatibility(args, kotlinSources) + sourceRoots as SourceRoots.ForJvm + + validateKotlinAndJavaHasSameTargetCompatibility(args, sourceRoots) val messageCollector = GradlePrintingMessageCollector(logger, args.allWarningsAsErrors) val outputItemCollector = OutputItemsCollectorImpl() @@ -846,7 +791,7 @@ abstract class KotlinCompile @Inject constructor( ) } else null - @Suppress("ConvertArgumentToSet", "DEPRECATION") + @Suppress("ConvertArgumentToSet") val environment = GradleCompilerEnvironment( defaultCompilerClasspath, messageCollector, outputItemCollector, // In the incremental compiler, outputFiles will be cleaned on rebuild. However, because classpathSnapshotDir is not included in @@ -858,12 +803,10 @@ abstract class KotlinCompile @Inject constructor( incrementalCompilationEnvironment = icEnv, kotlinScriptExtensions = sourceFilesExtensions.get().toTypedArray() ) - logger.info("Kotlin source files: ${kotlinSources.joinToString()}") - logger.info("Java source files: ${javaSources.files.joinToString()}") compilerRunner.runJvmCompilerAsync( - kotlinSources.toList(), + sourceRoots.kotlinSourceFiles.files.toList(), commonSourceSet.toList(), - javaSources.files, // we need here only directories where Java sources are located + sourceRoots.javaSourceRoots, javaPackagePrefix, args, environment, @@ -872,12 +815,8 @@ abstract class KotlinCompile @Inject constructor( ) } - private fun validateKotlinAndJavaHasSameTargetCompatibility( - args: K2JVMCompilerArguments, - kotlinSources: Set - ) { - val mixedSourcesArePresent = !associatedJavaCompileTaskSources.isEmpty && - kotlinSources.isNotEmpty() + private fun validateKotlinAndJavaHasSameTargetCompatibility(args: K2JVMCompilerArguments, sourceRoots: SourceRoots.ForJvm) { + val mixedSourcesArePresent = !associatedJavaCompileTaskSources.isEmpty && !sourceRoots.kotlinSourceFiles.isEmpty if (mixedSourcesArePresent) { associatedJavaCompileTaskTargetCompatibility.orNull?.let { targetCompatibility -> val normalizedJavaTarget = when (targetCompatibility) { @@ -915,7 +854,7 @@ abstract class KotlinCompile @Inject constructor( if (it is AbstractCompile && it !is JavaCompile && it !is AbstractKotlinCompile<*> && - javaOutputDir.get().asFile.isParentOf(it.destinationDirectory.get().asFile) + javaOutputDir.get().asFile.isParentOf(it.destinationDir) ) { illegalTaskOrNull = illegalTaskOrNull ?: it } @@ -924,7 +863,7 @@ abstract class KotlinCompile @Inject constructor( val illegalTask = illegalTaskOrNull!! logger.info( "Kotlin inter-project IC is disabled: " + - "unknown task '$illegalTask' destination dir ${illegalTask.destinationDirectory.get().asFile} " + + "unknown task '$illegalTask' destination dir ${illegalTask.destinationDir} " + "intersects with java destination dir $javaOutputDir" ) } @@ -932,34 +871,15 @@ abstract class KotlinCompile @Inject constructor( } } - private val javaSourceFiles = objectFactory.fileCollection() - - private fun javaFilesPatternFilter(patternFilterable: PatternFilterable) { - patternFilterable.include( - "java".fileExtensionCasePermutations().map { "**/*.$it" } - ) - } - - @get:Incremental - @get:InputFiles - @get:IgnoreEmptyDirectories - @get:PathSensitive(PathSensitivity.RELATIVE) - open val javaSources: FileCollection = objectFactory.fileCollection() - .from( - javaSourceFiles - .asFileTree - .matching(::javaFilesPatternFilter) - ) - - // override setSource to track Java sources as well + // override setSource to track source directory sets and files (for generated android folders) override fun setSource(source: Any) { - javaSourceFiles.from(source) + sourceRootsContainer.set(source) super.setSource(source) } - // override source to track Java sources as well + // override source to track source directory sets and files (for generated android folders) override fun setSource(vararg source: Any) { - javaSourceFiles.from(*source) + sourceRootsContainer.add(*source) super.setSource(*source) } @@ -993,8 +913,7 @@ abstract class Kotlin2JsCompile @Inject constructor( override val kotlinOptions: KotlinJsOptions, objectFactory: ObjectFactory, workerExecutor: WorkerExecutor -) : AbstractKotlinCompile(objectFactory), - KotlinJsCompile { +) : AbstractKotlinCompile(), KotlinJsCompile { init { incremental = true @@ -1078,7 +997,7 @@ abstract class Kotlin2JsCompile @Inject constructor( abstract val optionalOutputFile: RegularFileProperty override val compilerRunner: Provider = - objectFactory.propertyWithConvention( + objects.propertyWithConvention( gradleCompileTaskProvider.map { GradleCompilerRunnerWithWorkers( it, @@ -1112,6 +1031,8 @@ abstract class Kotlin2JsCompile @Inject constructor( (kotlinOptions as KotlinJsOptionsImpl).updateArguments(args) } + override fun getSourceRoots() = SourceRoots.KotlinOnly.create(sources, sourceFilesExtensions.get()) + @get:InputFiles @get:IgnoreEmptyDirectories @get:Incremental @@ -1200,11 +1121,14 @@ abstract class Kotlin2JsCompile @Inject constructor( override fun callCompilerAsync( args: K2JSCompilerArguments, - kotlinSources: Set, + sourceRoots: SourceRoots, inputChanges: InputChanges, taskOutputsBackup: TaskOutputsBackup? ) { + sourceRoots as SourceRoots.KotlinOnly + logger.debug("Calling compiler") + //destinationDir.mkdirs() if (kotlinOptions.isIrBackendEnabled()) { logger.info(USING_JS_IR_BACKEND_MESSAGE) @@ -1250,7 +1174,7 @@ abstract class Kotlin2JsCompile @Inject constructor( ) processArgs(args) compilerRunner.runJsCompilerAsync( - kotlinSources.toList(), + sourceRoots.kotlinSourceFiles.files.toList(), commonSourceSet.toList(), args, environment, diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/utils/fileUtils.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/utils/fileUtils.kt index 5b043d2a0c4..1fc7eb20448 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/utils/fileUtils.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/utils/fileUtils.kt @@ -18,32 +18,6 @@ internal fun File.isJavaFile() = internal fun File.isKotlinFile(sourceFilesExtensions: List): Boolean = !isJavaFile() && sourceFilesExtensions.any { it.equals(extension, ignoreCase = true) } -/** - * Create all possible case-sensitive permutations for given [String]. - * - * Useful to create for [org.gradle.api.tasks.util.PatternFilterable] Ant-style patterns. - */ -@OptIn(ExperimentalStdlibApi::class) -internal fun String.fileExtensionCasePermutations(): List { - val lowercaseInput = lowercase() - val length = lowercaseInput.length - // number of permutations is 2^n - val max = 1 shl length - val result = mutableListOf() - var combination: CharArray - for (i in 0 until max) { - combination = lowercaseInput.toCharArray() - for (j in 0 until length) { - // If j-th bit is set, we convert it to upper case - if (((i shr j) and 1) == 1) { - combination[j] = combination[j].uppercaseChar() - } - } - result.add(String(combination)) - } - return result -} - internal fun File.relativeOrCanonical(base: File): String = relativeToOrNull(base)?.path ?: canonicalPath