Restore "AbstractKotlinCompileTool class now also implements PatternFilterable"

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