Restore "AbstractKotlinCompileTool class now also implements PatternFilterable"
This reverts commit d5e5513dfd.
This commit is contained in:
+1
@@ -306,6 +306,7 @@ 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(),
|
||||
|
||||
+2
-2
@@ -33,6 +33,7 @@ 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
|
||||
@@ -576,8 +577,7 @@ class Kapt3GradleSubplugin @Inject internal constructor(private val registry: To
|
||||
kotlinCompilation.output.classesDirs.from(kaptTaskProvider.map { it.classesDir })
|
||||
|
||||
kotlinCompilation.compileKotlinTaskProvider.configure {
|
||||
it as SourceTask
|
||||
it.source(sourcesOutputDir, kotlinSourcesOutputDir)
|
||||
(it as AbstractKotlinCompileTool<*>).setSource(sourcesOutputDir, kotlinSourcesOutputDir)
|
||||
}
|
||||
|
||||
if (javaCompile != null) {
|
||||
|
||||
+40
-42
@@ -16,9 +16,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.internal
|
||||
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.Directory
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.file.*
|
||||
import org.gradle.api.model.ObjectFactory
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.provider.Provider
|
||||
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.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
|
||||
@@ -39,10 +36,12 @@ import javax.inject.Inject
|
||||
|
||||
@CacheableTask
|
||||
abstract class KaptGenerateStubsTask @Inject constructor(
|
||||
workerExecutor: WorkerExecutor
|
||||
): KotlinCompile(
|
||||
workerExecutor: WorkerExecutor,
|
||||
objectFactory: ObjectFactory
|
||||
) : KotlinCompile(
|
||||
KotlinJvmOptionsImpl(),
|
||||
workerExecutor
|
||||
workerExecutor,
|
||||
objectFactory
|
||||
) {
|
||||
|
||||
internal class Configurator(
|
||||
@@ -71,23 +70,10 @@ 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
|
||||
|
||||
@@ -118,28 +104,45 @@ abstract class KaptGenerateStubsTask @Inject constructor(
|
||||
@get:Incremental
|
||||
abstract val additionalSources: ConfigurableFileCollection
|
||||
|
||||
override fun setSource(vararg source: Any) {
|
||||
super.setSource(sourceRootsContainer.add(sources))
|
||||
}
|
||||
private fun File.isSourceRootAllowed(): Boolean =
|
||||
!destinationDirectory.get().asFile.isParentOf(this) &&
|
||||
!stubsDir.asFile.get().isParentOf(this) &&
|
||||
generatedSourcesDirs.none { it.isParentOf(this) }
|
||||
|
||||
override fun setSource(source: Any) {
|
||||
super.setSource(sourceRootsContainer.set(sources))
|
||||
}
|
||||
override fun skipCondition(): Boolean = sources.isEmpty && javaSources.isEmpty
|
||||
|
||||
// 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) }
|
||||
// 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() }
|
||||
}
|
||||
|
||||
@get:Internal
|
||||
internal abstract val compileKotlinArgumentsContributor: Property<CompilerArgumentsContributor<K2JVMCompilerArguments>>
|
||||
|
||||
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()
|
||||
@@ -148,9 +151,4 @@ 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<SourceRoots.ForJvm>
|
||||
|
||||
override fun getSourceRoots(): SourceRoots.ForJvm = jvmSourceRoots.get()
|
||||
}
|
||||
+6
-10
@@ -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,20 +31,16 @@ import javax.inject.Inject
|
||||
@CacheableTask
|
||||
abstract class KaptTask @Inject constructor(
|
||||
objectFactory: ObjectFactory
|
||||
) : ConventionTask(),
|
||||
) : DefaultTask(),
|
||||
TaskWithLocalState,
|
||||
UsesKotlinJavaToolchain {
|
||||
|
||||
open class Configurator<T: KaptTask>(protected val kotlinCompileTask: KotlinCompile) : TaskConfigurator<T> {
|
||||
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 } }
|
||||
@@ -52,7 +48,10 @@ 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(task.kotlinSourceRoots, task.stubsDir).asFileTree
|
||||
objectFactory.fileCollection().from(
|
||||
kotlinCompileTask.javaSources,
|
||||
task.stubsDir
|
||||
).asFileTree
|
||||
.matching { it.include("**/*.java") }
|
||||
.filter { f -> task.isRootAllowed(f) }
|
||||
).disallowChanges()
|
||||
@@ -153,9 +152,6 @@ abstract class KaptTask @Inject constructor(
|
||||
@get:Internal
|
||||
var useBuildCache: Boolean = false
|
||||
|
||||
@get:Internal
|
||||
abstract val kotlinSourceRoots: ListProperty<File>
|
||||
|
||||
/** Needed for the model builder. */
|
||||
@get:Internal
|
||||
abstract val sourceSetName: Property<String>
|
||||
|
||||
+2
-4
@@ -8,12 +8,10 @@ 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
|
||||
@@ -26,7 +24,6 @@ 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
|
||||
@@ -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.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.*
|
||||
@@ -187,7 +185,7 @@ class KotlinMultiplatformPlugin : Plugin<Project> {
|
||||
(sourceSet.languageSettings as? DefaultLanguageSettingsBuilder)?.run {
|
||||
compilerPluginOptionsTask = lazy {
|
||||
val associatedCompilation = primaryCompilationsBySourceSet[sourceSet] ?: metadataCompilation
|
||||
project.tasks.getByName(associatedCompilation.compileKotlinTaskName) as SourceTask
|
||||
project.tasks.getByName(associatedCompilation.compileKotlinTaskName) as AbstractKotlinCompileTool<*>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -8,7 +8,6 @@ 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
|
||||
@@ -16,6 +15,7 @@ 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<SourceTask?> = lazyOf(null)
|
||||
var compilerPluginOptionsTask: Lazy<AbstractKotlinCompileTool<*>?> = lazyOf(null)
|
||||
|
||||
val compilerPluginArguments: List<String>?
|
||||
get() {
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ class KotlinJsDcePlugin : Plugin<Project> {
|
||||
dceTask.configure {
|
||||
it.classpath.from(configuration)
|
||||
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 })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -101,9 +101,10 @@ open class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) :
|
||||
),
|
||||
listOf(compilation)
|
||||
) { task ->
|
||||
val entryFileProvider = binary.linkSyncTask.map {
|
||||
it.destinationDir
|
||||
.resolve(binary.linkTask.get().outputFileProperty.get().name)
|
||||
val entryFileProvider = binary.linkSyncTask.flatMap { syncTask ->
|
||||
binary.linkTask.map {
|
||||
syncTask.destinationDir.resolve(it.outputFileProperty.get().name)
|
||||
}
|
||||
}
|
||||
|
||||
webpackMajorVersion.choose(
|
||||
|
||||
+24
-15
@@ -7,6 +7,7 @@ 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.*
|
||||
@@ -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.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,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
|
||||
@get:Internal
|
||||
internal lateinit var compilation: KotlinCompilationData<*>
|
||||
@@ -81,10 +93,6 @@ 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
|
||||
@@ -93,23 +101,24 @@ abstract class KotlinJsIrLink @Inject constructor(
|
||||
@get:PathSensitive(PathSensitivity.RELATIVE)
|
||||
internal abstract val entryModule: DirectoryProperty
|
||||
|
||||
override val destinationDirectory: DirectoryProperty
|
||||
get() = objectFactory.directoryProperty().apply {
|
||||
@get:Internal
|
||||
override val destinationDirectory: DirectoryProperty = objectFactory.directoryProperty()
|
||||
|
||||
@get:OutputDirectory
|
||||
val normalizedDestinationDirectory: DirectoryProperty = objectFactory
|
||||
.directoryProperty()
|
||||
.apply {
|
||||
set(
|
||||
destinationDirectory.flatMap { dir ->
|
||||
if (kotlinOptions.outputFile == null) {
|
||||
objectFactory.property(dir)
|
||||
destinationDirectory.map { dir ->
|
||||
if (kotlinOptions.outputFile != null) {
|
||||
projectLayout.dir(outputFileProperty.map { it.parentFile }).get()
|
||||
} else {
|
||||
projectLayout.dir(outputFileProperty.map { it.parentFile })
|
||||
dir
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun skipCondition(): Boolean {
|
||||
return !entryModule.get().asFile.exists()
|
||||
}
|
||||
|
||||
@get:Internal
|
||||
val rootCacheDirectory by lazy {
|
||||
buildDir.resolve("klib/cache")
|
||||
|
||||
+5
-1
@@ -136,7 +136,11 @@ constructor(
|
||||
binary.linkSyncTaskName
|
||||
) { task ->
|
||||
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))
|
||||
|
||||
+22
-23
@@ -18,6 +18,7 @@ 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
|
||||
@@ -132,7 +133,10 @@ abstract class AbstractKotlinNativeCompile<
|
||||
T : KotlinCommonToolOptions,
|
||||
K : KotlinNativeCompilationData<*>,
|
||||
M : CommonToolArguments
|
||||
> : AbstractKotlinCompileTool<M>() {
|
||||
>
|
||||
@Inject constructor(
|
||||
private val objectFactory: ObjectFactory
|
||||
): AbstractKotlinCompileTool<M>(objectFactory) {
|
||||
@get:Internal
|
||||
abstract val compilation: K
|
||||
|
||||
@@ -149,9 +153,6 @@ 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
|
||||
@@ -162,7 +163,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 objects.fileCollection()
|
||||
else objectFactory.fileCollection()
|
||||
}
|
||||
|
||||
@get:Classpath
|
||||
@@ -172,7 +173,7 @@ abstract class AbstractKotlinNativeCompile<
|
||||
|
||||
@Deprecated("For native tasks use 'libraries' instead", ReplaceWith("libraries"))
|
||||
override val classpath: ConfigurableFileCollection
|
||||
get() = objects.fileCollection().from(libraries)
|
||||
get() = objectFactory.fileCollection().from(libraries)
|
||||
|
||||
@get:Input
|
||||
val target: String by project.provider { compilation.konanTarget.name }
|
||||
@@ -209,7 +210,7 @@ abstract class AbstractKotlinNativeCompile<
|
||||
|
||||
@get:Internal
|
||||
open val outputFile: Provider<File>
|
||||
get() = destinationDirectory.map {
|
||||
get() = destinationDirectory.flatMap {
|
||||
val prefix = outputKind.prefix(konanTarget)
|
||||
val suffix = outputKind.suffix(konanTarget)
|
||||
val filename = "$prefix${baseName}$suffix".let {
|
||||
@@ -222,7 +223,7 @@ abstract class AbstractKotlinNativeCompile<
|
||||
}
|
||||
}
|
||||
|
||||
it.file(filename).asFile
|
||||
objectFactory.property(it.file(filename).asFile)
|
||||
}
|
||||
|
||||
// endregion
|
||||
@@ -309,8 +310,9 @@ abstract class KotlinNativeCompile
|
||||
constructor(
|
||||
@Internal
|
||||
@Transient // can't be serialized for Gradle configuration cache
|
||||
final override val compilation: KotlinNativeCompilationData<*>
|
||||
) : AbstractKotlinNativeCompile<KotlinCommonOptions, KotlinNativeCompilationData<*>, StubK2NativeCompilerArguments>(),
|
||||
final override val compilation: KotlinNativeCompilationData<*>,
|
||||
objectFactory: ObjectFactory
|
||||
) : AbstractKotlinNativeCompile<KotlinCommonOptions, KotlinNativeCompilationData<*>, StubK2NativeCompilerArguments>(objectFactory),
|
||||
KotlinCompile<KotlinCommonOptions> {
|
||||
|
||||
@get:Input
|
||||
@@ -463,8 +465,9 @@ abstract class KotlinNativeLink
|
||||
@Inject
|
||||
constructor(
|
||||
@Internal
|
||||
val binary: NativeBinary
|
||||
) : AbstractKotlinNativeCompile<KotlinCommonToolOptions, KotlinNativeCompilation, StubK2NativeCompilerArguments>() {
|
||||
val binary: NativeBinary,
|
||||
objectFactory: ObjectFactory
|
||||
) : AbstractKotlinNativeCompile<KotlinCommonToolOptions, KotlinNativeCompilation, StubK2NativeCompilerArguments>(objectFactory) {
|
||||
@get:Internal
|
||||
final override val compilation: KotlinNativeCompilation
|
||||
get() = binary.compilation
|
||||
@@ -474,17 +477,13 @@ 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()
|
||||
}
|
||||
|
||||
@Internal // Taken into account by getSources().
|
||||
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 {
|
||||
override val destinationDirectory: DirectoryProperty = objectFactory.directoryProperty().apply {
|
||||
set(binary.outputDirectory)
|
||||
}
|
||||
|
||||
@@ -553,7 +552,7 @@ constructor(
|
||||
if (it is AbstractNativeLibrary) {
|
||||
project.configurations.getByName(it.exportConfigurationName)
|
||||
} else {
|
||||
objects.fileCollection()
|
||||
objectFactory.fileCollection()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -652,7 +651,7 @@ constructor(
|
||||
binaryOptions,
|
||||
isStaticFramework,
|
||||
exportLibraries.files.filterKlibsPassedToCompiler(),
|
||||
listOf(intermediateLibrary.get()),
|
||||
sources.asFileTree.files.toList(),
|
||||
externalDependenciesArgs + cacheArgs
|
||||
)
|
||||
|
||||
|
||||
+10
-10
@@ -18,6 +18,7 @@ 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
|
||||
@@ -46,8 +47,10 @@ import javax.inject.Inject
|
||||
@CacheableTask
|
||||
abstract class KotlinCompileCommon @Inject constructor(
|
||||
override val kotlinOptions: KotlinMultiplatformCommonOptions,
|
||||
workerExecutor: WorkerExecutor
|
||||
) : AbstractKotlinCompile<K2MetadataCompilerArguments>(), KotlinCommonCompile {
|
||||
workerExecutor: WorkerExecutor,
|
||||
objectFactory: ObjectFactory
|
||||
) : AbstractKotlinCompile<K2MetadataCompilerArguments>(objectFactory),
|
||||
KotlinCommonCompile {
|
||||
|
||||
class Configurator(compilation: KotlinCompilationData<*>) : AbstractKotlinCompile.Configurator<KotlinCompileCommon>(compilation) {
|
||||
override fun configure(task: KotlinCompileCommon) {
|
||||
@@ -85,7 +88,7 @@ abstract class KotlinCompileCommon @Inject constructor(
|
||||
}
|
||||
|
||||
override val compilerRunner: Provider<GradleCompilerRunner> =
|
||||
objects.propertyWithConvention(
|
||||
objectFactory.propertyWithConvention(
|
||||
gradleCompileTaskProvider.map {
|
||||
GradleCompilerRunnerWithWorkers(
|
||||
it,
|
||||
@@ -101,9 +104,6 @@ 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 = objects.fileCollection()
|
||||
internal val refinesMetadataPaths: ConfigurableFileCollection = objectFactory.fileCollection()
|
||||
|
||||
@get:Internal
|
||||
internal val expectActualLinker = objects.property(Boolean::class.java)
|
||||
internal val expectActualLinker = objectFactory.property(Boolean::class.java)
|
||||
|
||||
override fun callCompilerAsync(
|
||||
args: K2MetadataCompilerArguments,
|
||||
sourceRoots: SourceRoots,
|
||||
kotlinSources: Set<File>,
|
||||
inputChanges: InputChanges,
|
||||
taskOutputsBackup: TaskOutputsBackup?
|
||||
) {
|
||||
@@ -152,7 +152,7 @@ abstract class KotlinCompileCommon @Inject constructor(
|
||||
outputFiles = allOutputFiles()
|
||||
)
|
||||
compilerRunner.runMetadataCompilerAsync(
|
||||
sourceRoots.kotlinSourceFiles.files.toList(),
|
||||
kotlinSources.toList(),
|
||||
commonSourceSet.files.toList(),
|
||||
args,
|
||||
environment
|
||||
|
||||
+27
-13
@@ -16,11 +16,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.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.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.model.ObjectFactory
|
||||
import org.gradle.api.tasks.*
|
||||
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
|
||||
@@ -31,17 +32,21 @@ 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 : AbstractKotlinCompileTool<K2JSDceArguments>(), KotlinJsDce {
|
||||
abstract class KotlinJsDce @Inject constructor(
|
||||
objectFactory: ObjectFactory
|
||||
) : AbstractKotlinCompileTool<K2JSDceArguments>(objectFactory),
|
||||
KotlinJsDce {
|
||||
|
||||
init {
|
||||
cacheOnlyIfEnabledForKotlin()
|
||||
}
|
||||
|
||||
@get:Internal
|
||||
internal val objects = project.objects
|
||||
include("js".fileExtensionCasePermutations().map { "**/*.$it" })
|
||||
}
|
||||
|
||||
override fun createCompilerArgs(): K2JSDceArguments = K2JSDceArguments()
|
||||
|
||||
@@ -70,9 +75,18 @@ abstract class KotlinJsDce : AbstractKotlinCompileTool<K2JSDceArguments>(), Kotl
|
||||
@Input
|
||||
var jvmArgs = mutableListOf<String>()
|
||||
|
||||
private val buildDir by lazy {
|
||||
project.buildDir
|
||||
}
|
||||
// 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 isDevMode
|
||||
get() = dceOptions.devMode || "-dev-mode" in dceOptions.freeCompilerArgs
|
||||
@@ -95,7 +109,7 @@ abstract class KotlinJsDce : AbstractKotlinCompileTool<K2JSDceArguments>(), Kotl
|
||||
} else {
|
||||
classpath.asFileTree.files
|
||||
}
|
||||
// TODO: use PatternFilterable here!
|
||||
|
||||
val inputFiles = sources.asFileTree.files.plus(classpathFiles)
|
||||
.filter { !kotlinFilesOnly || isDceCandidate(it) }
|
||||
.map { it.path }
|
||||
@@ -120,7 +134,7 @@ abstract class KotlinJsDce : AbstractKotlinCompileTool<K2JSDceArguments>(), Kotl
|
||||
K2JSDce::class.java.name,
|
||||
defaultCompilerClasspath,
|
||||
log,
|
||||
buildDir,
|
||||
buildDir.get().asFile,
|
||||
jvmArgs
|
||||
)
|
||||
throwGradleExceptionIfError(exitCode, KotlinCompilerExecutionStrategy.OUT_OF_PROCESS)
|
||||
|
||||
-109
@@ -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)
|
||||
}
|
||||
}
|
||||
+160
-84
@@ -5,6 +5,7 @@
|
||||
|
||||
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
|
||||
@@ -19,10 +20,12 @@ 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
|
||||
@@ -57,13 +60,10 @@ 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.ChangedFiles
|
||||
import org.jetbrains.kotlin.incremental.ClasspathChanges
|
||||
import org.jetbrains.kotlin.incremental.*
|
||||
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,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_IR_BACKEND_MESSAGE = "Using Kotlin/JS IR backend"
|
||||
|
||||
abstract class AbstractKotlinCompileTool<T : CommonToolArguments>
|
||||
: DefaultTask(),
|
||||
//PatternFilterable,
|
||||
abstract class AbstractKotlinCompileTool<T : CommonToolArguments> @Inject constructor(
|
||||
objectFactory: ObjectFactory
|
||||
) : DefaultTask(),
|
||||
PatternFilterable,
|
||||
CompilerArgumentAwareWithInput<T>,
|
||||
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)
|
||||
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.
|
||||
* The given source object is evaluated as per [org.gradle.api.Project.files].
|
||||
*/
|
||||
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].
|
||||
*/
|
||||
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
|
||||
@@ -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 {
|
||||
|
||||
open class Configurator<T : AbstractKotlinCompile<*>>(protected val compilation: KotlinCompilationData<*>) : TaskConfigurator<T> {
|
||||
@@ -238,16 +310,13 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments> : AbstractKotl
|
||||
@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 = objects.directoryProperty()
|
||||
internal val taskBuildCacheableOutputDirectory: DirectoryProperty = objectFactory.directoryProperty()
|
||||
|
||||
// avoid creating directory in getter: this can lead to failure in parallel build
|
||||
@get:LocalState
|
||||
internal val taskBuildLocalStateDirectory: DirectoryProperty = objects.directoryProperty()
|
||||
internal val taskBuildLocalStateDirectory: DirectoryProperty = objectFactory.directoryProperty()
|
||||
|
||||
@get:Internal
|
||||
internal val buildHistoryFile
|
||||
@@ -277,20 +346,18 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments> : AbstractKotl
|
||||
internal fun reportingSettings() = buildMetricsReporterService.orNull?.parameters?.reportingSettings ?: ReportingSettings()
|
||||
|
||||
@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
|
||||
protected val multiModuleICSettings: MultiModuleICSettings
|
||||
get() = MultiModuleICSettings(buildHistoryFile.get().asFile, useModuleDetection.get())
|
||||
|
||||
@get:Classpath
|
||||
open val pluginClasspath: ConfigurableFileCollection = objects.fileCollection()
|
||||
open val pluginClasspath: ConfigurableFileCollection = objectFactory.fileCollection()
|
||||
|
||||
@get:Internal
|
||||
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]
|
||||
@@ -302,52 +369,52 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments> : AbstractKotl
|
||||
|
||||
// Input is needed to force rebuild even if source files are not changed
|
||||
@get:Input
|
||||
internal val coroutines: Property<Coroutines> = objects.property(Coroutines::class.java)
|
||||
internal val coroutines: Property<Coroutines> = objectFactory.property(Coroutines::class.java)
|
||||
|
||||
@get:Internal
|
||||
internal val javaOutputDir: DirectoryProperty = objects.directoryProperty()
|
||||
internal val javaOutputDir: DirectoryProperty = objectFactory.directoryProperty()
|
||||
|
||||
@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:IgnoreEmptyDirectories
|
||||
@get:Incremental
|
||||
@get:PathSensitive(PathSensitivity.RELATIVE)
|
||||
internal val commonSourceSet: ConfigurableFileCollection = objects.fileCollection()
|
||||
internal val commonSourceSet: ConfigurableFileCollection = objectFactory.fileCollection()
|
||||
|
||||
@get:Input
|
||||
internal val moduleName: Property<String> = objects.property(String::class.java)
|
||||
internal val moduleName: Property<String> = objectFactory.property(String::class.java)
|
||||
|
||||
@get:Internal
|
||||
val abiSnapshotFile
|
||||
get() = taskBuildCacheableOutputDirectory.file(IncrementalCompilerRunner.ABI_SNAPSHOT_FILE_NAME)
|
||||
|
||||
@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
|
||||
"$name/${IncrementalCompilerRunner.ABI_SNAPSHOT_FILE_NAME}"
|
||||
)
|
||||
|
||||
@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
|
||||
val friendPaths: ConfigurableFileCollection = objects.fileCollection()
|
||||
val friendPaths: ConfigurableFileCollection = objectFactory.fileCollection()
|
||||
|
||||
private val kotlinLogger by lazy { GradleKotlinLogger(logger) }
|
||||
|
||||
abstract override val kotlinDaemonJvmArguments: ListProperty<String>
|
||||
|
||||
@get:Internal
|
||||
protected val gradleCompileTaskProvider: Provider<GradleCompileTaskProvider> = objects
|
||||
protected val gradleCompileTaskProvider: Provider<GradleCompileTaskProvider> = objectFactory
|
||||
.property(
|
||||
objects.newInstance<GradleCompileTaskProvider>(project.gradle, this, project)
|
||||
objectFactory.newInstance<GradleCompileTaskProvider>(project.gradle, this, project)
|
||||
)
|
||||
|
||||
@get:Internal
|
||||
internal open val compilerRunner: Provider<GradleCompilerRunner> =
|
||||
objects.propertyWithConvention(
|
||||
objectFactory.propertyWithConvention(
|
||||
gradleCompileTaskProvider.map {
|
||||
GradleCompilerRunner(
|
||||
it,
|
||||
@@ -410,8 +477,7 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments> : AbstractKotl
|
||||
buildMetricsReporterService.orNull?.also { it.addTask(path, this.javaClass, buildMetrics) }
|
||||
}
|
||||
|
||||
protected open fun skipCondition(): Boolean =
|
||||
getSourceRoots().kotlinSourceFiles.isEmpty()
|
||||
protected open fun skipCondition(): Boolean = sources.isEmpty
|
||||
|
||||
private val projectDir = project.rootProject.projectDir
|
||||
|
||||
@@ -427,8 +493,7 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments> : AbstractKotl
|
||||
inputChanges: InputChanges,
|
||||
taskOutputsBackup: TaskOutputsBackup?
|
||||
) {
|
||||
val sourceRoots = getSourceRoots()
|
||||
val allKotlinSources = sourceRoots.kotlinSourceFiles
|
||||
val allKotlinSources = sources.asFileTree.files
|
||||
|
||||
logger.kotlinDebug { "All kotlin sources: ${allKotlinSources.pathsAsStringRelativeTo(projectDir)}" }
|
||||
|
||||
@@ -438,13 +503,12 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments> : AbstractKotl
|
||||
return
|
||||
}
|
||||
|
||||
sourceRoots.log(this.name, logger)
|
||||
val args = prepareCompilerArguments()
|
||||
taskBuildCacheableOutputDirectory.get().asFile.mkdirs()
|
||||
taskBuildLocalStateDirectory.get().asFile.mkdirs()
|
||||
callCompilerAsync(
|
||||
args,
|
||||
sourceRoots,
|
||||
allKotlinSources,
|
||||
inputChanges,
|
||||
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.
|
||||
* @see [GradleKotlinCompilerWork]
|
||||
*/
|
||||
internal abstract fun callCompilerAsync(
|
||||
args: T,
|
||||
sourceRoots: SourceRoots,
|
||||
kotlinSources: Set<File>,
|
||||
inputChanges: InputChanges,
|
||||
taskOutputsBackup: TaskOutputsBackup?
|
||||
)
|
||||
|
||||
@get:Input
|
||||
internal val multiPlatformEnabled: Property<Boolean> = objects.property(Boolean::class.java)
|
||||
internal val multiPlatformEnabled: Property<Boolean> = objectFactory.property(Boolean::class.java)
|
||||
|
||||
@get:Internal
|
||||
internal val abstractKotlinCompileArgumentsContributor by lazy {
|
||||
@@ -536,8 +597,9 @@ internal inline val <reified T : Task> T.thisTaskProvider: TaskProvider<out T>
|
||||
@CacheableTask
|
||||
abstract class KotlinCompile @Inject constructor(
|
||||
override val kotlinOptions: KotlinJvmOptions,
|
||||
workerExecutor: WorkerExecutor
|
||||
) : AbstractKotlinCompile<K2JVMCompilerArguments>(),
|
||||
workerExecutor: WorkerExecutor,
|
||||
private val objectFactory: ObjectFactory
|
||||
) : AbstractKotlinCompile<K2JVMCompilerArguments>(objectFactory),
|
||||
KotlinJvmCompile,
|
||||
UsesKotlinJavaToolchain {
|
||||
|
||||
@@ -635,16 +697,7 @@ abstract class KotlinCompile @Inject constructor(
|
||||
}
|
||||
|
||||
@get:Internal
|
||||
internal val parentKotlinOptionsImpl: Property<KotlinJvmOptions> = 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())
|
||||
}
|
||||
internal val parentKotlinOptionsImpl: Property<KotlinJvmOptions> = objectFactory.property(KotlinJvmOptions::class.java)
|
||||
|
||||
/** 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>
|
||||
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). */
|
||||
override val taskOutputsBackupExcludes: List<File>
|
||||
get() = classpathSnapshotProperties.classpathSnapshotDir.orNull?.asFile?.let { listOf(it) } ?: emptyList()
|
||||
|
||||
@get:Internal
|
||||
internal val defaultKotlinJavaToolchain: Provider<DefaultKotlinJavaToolchain> = objects
|
||||
internal val defaultKotlinJavaToolchain: Provider<DefaultKotlinJavaToolchain> = objectFactory
|
||||
.propertyWithNewInstance({ this })
|
||||
|
||||
final override val kotlinJavaToolchainProvider: Provider<KotlinJavaToolchain> = defaultKotlinJavaToolchain.cast()
|
||||
|
||||
@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()
|
||||
defaultKotlinJavaToolchain.flatMap { toolchain ->
|
||||
objects.property(gradleCompileTaskProvider.map {
|
||||
objectFactory.property(gradleCompileTaskProvider.map {
|
||||
GradleCompilerRunnerWithWorkers(
|
||||
it,
|
||||
toolchain.currentJvmJdkToolsJar.orNull,
|
||||
@@ -762,17 +821,13 @@ abstract class KotlinCompile @Inject constructor(
|
||||
KotlinJvmCompilerArgumentsContributor(KotlinJvmCompilerArgumentsProvider(this))
|
||||
}
|
||||
|
||||
override fun getSourceRoots(): SourceRoots.ForJvm = jvmSourceRoots
|
||||
|
||||
override fun callCompilerAsync(
|
||||
args: K2JVMCompilerArguments,
|
||||
sourceRoots: SourceRoots,
|
||||
kotlinSources: Set<File>,
|
||||
inputChanges: InputChanges,
|
||||
taskOutputsBackup: TaskOutputsBackup?
|
||||
) {
|
||||
sourceRoots as SourceRoots.ForJvm
|
||||
|
||||
validateKotlinAndJavaHasSameTargetCompatibility(args, sourceRoots)
|
||||
validateKotlinAndJavaHasSameTargetCompatibility(args, kotlinSources)
|
||||
|
||||
val messageCollector = GradlePrintingMessageCollector(logger, args.allWarningsAsErrors)
|
||||
val outputItemCollector = OutputItemsCollectorImpl()
|
||||
@@ -791,7 +846,7 @@ abstract class KotlinCompile @Inject constructor(
|
||||
)
|
||||
} else null
|
||||
|
||||
@Suppress("ConvertArgumentToSet")
|
||||
@Suppress("ConvertArgumentToSet", "DEPRECATION")
|
||||
val environment = GradleCompilerEnvironment(
|
||||
defaultCompilerClasspath, messageCollector, outputItemCollector,
|
||||
// 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,
|
||||
kotlinScriptExtensions = sourceFilesExtensions.get().toTypedArray()
|
||||
)
|
||||
logger.info("Kotlin source files: ${kotlinSources.joinToString()}")
|
||||
logger.info("Java source files: ${javaSources.files.joinToString()}")
|
||||
compilerRunner.runJvmCompilerAsync(
|
||||
sourceRoots.kotlinSourceFiles.files.toList(),
|
||||
kotlinSources.toList(),
|
||||
commonSourceSet.toList(),
|
||||
sourceRoots.javaSourceRoots,
|
||||
javaSources.files, // we need here only directories where Java sources are located
|
||||
javaPackagePrefix,
|
||||
args,
|
||||
environment,
|
||||
@@ -815,8 +872,12 @@ abstract class KotlinCompile @Inject constructor(
|
||||
)
|
||||
}
|
||||
|
||||
private fun validateKotlinAndJavaHasSameTargetCompatibility(args: K2JVMCompilerArguments, sourceRoots: SourceRoots.ForJvm) {
|
||||
val mixedSourcesArePresent = !associatedJavaCompileTaskSources.isEmpty && !sourceRoots.kotlinSourceFiles.isEmpty
|
||||
private fun validateKotlinAndJavaHasSameTargetCompatibility(
|
||||
args: K2JVMCompilerArguments,
|
||||
kotlinSources: Set<File>
|
||||
) {
|
||||
val mixedSourcesArePresent = !associatedJavaCompileTaskSources.isEmpty &&
|
||||
kotlinSources.isNotEmpty()
|
||||
if (mixedSourcesArePresent) {
|
||||
associatedJavaCompileTaskTargetCompatibility.orNull?.let { targetCompatibility ->
|
||||
val normalizedJavaTarget = when (targetCompatibility) {
|
||||
@@ -854,7 +915,7 @@ abstract class KotlinCompile @Inject constructor(
|
||||
if (it is AbstractCompile &&
|
||||
it !is JavaCompile &&
|
||||
it !is AbstractKotlinCompile<*> &&
|
||||
javaOutputDir.get().asFile.isParentOf(it.destinationDir)
|
||||
javaOutputDir.get().asFile.isParentOf(it.destinationDirectory.get().asFile)
|
||||
) {
|
||||
illegalTaskOrNull = illegalTaskOrNull ?: it
|
||||
}
|
||||
@@ -863,7 +924,7 @@ abstract class KotlinCompile @Inject constructor(
|
||||
val illegalTask = illegalTaskOrNull!!
|
||||
logger.info(
|
||||
"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"
|
||||
)
|
||||
}
|
||||
@@ -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) {
|
||||
sourceRootsContainer.set(source)
|
||||
javaSourceFiles.from(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) {
|
||||
sourceRootsContainer.add(*source)
|
||||
javaSourceFiles.from(*source)
|
||||
super.setSource(*source)
|
||||
}
|
||||
|
||||
@@ -913,7 +993,8 @@ abstract class Kotlin2JsCompile @Inject constructor(
|
||||
override val kotlinOptions: KotlinJsOptions,
|
||||
objectFactory: ObjectFactory,
|
||||
workerExecutor: WorkerExecutor
|
||||
) : AbstractKotlinCompile<K2JSCompilerArguments>(), KotlinJsCompile {
|
||||
) : AbstractKotlinCompile<K2JSCompilerArguments>(objectFactory),
|
||||
KotlinJsCompile {
|
||||
|
||||
init {
|
||||
incremental = true
|
||||
@@ -997,7 +1078,7 @@ abstract class Kotlin2JsCompile @Inject constructor(
|
||||
abstract val optionalOutputFile: RegularFileProperty
|
||||
|
||||
override val compilerRunner: Provider<GradleCompilerRunner> =
|
||||
objects.propertyWithConvention(
|
||||
objectFactory.propertyWithConvention(
|
||||
gradleCompileTaskProvider.map {
|
||||
GradleCompilerRunnerWithWorkers(
|
||||
it,
|
||||
@@ -1031,8 +1112,6 @@ 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
|
||||
@@ -1121,14 +1200,11 @@ abstract class Kotlin2JsCompile @Inject constructor(
|
||||
|
||||
override fun callCompilerAsync(
|
||||
args: K2JSCompilerArguments,
|
||||
sourceRoots: SourceRoots,
|
||||
kotlinSources: Set<File>,
|
||||
inputChanges: InputChanges,
|
||||
taskOutputsBackup: TaskOutputsBackup?
|
||||
) {
|
||||
sourceRoots as SourceRoots.KotlinOnly
|
||||
|
||||
logger.debug("Calling compiler")
|
||||
//destinationDir.mkdirs()
|
||||
|
||||
if (kotlinOptions.isIrBackendEnabled()) {
|
||||
logger.info(USING_JS_IR_BACKEND_MESSAGE)
|
||||
@@ -1174,7 +1250,7 @@ abstract class Kotlin2JsCompile @Inject constructor(
|
||||
)
|
||||
processArgs(args)
|
||||
compilerRunner.runJsCompilerAsync(
|
||||
sourceRoots.kotlinSourceFiles.files.toList(),
|
||||
kotlinSources.toList(),
|
||||
commonSourceSet.toList(),
|
||||
args,
|
||||
environment,
|
||||
|
||||
+26
@@ -18,6 +18,32 @@ internal fun File.isJavaFile() =
|
||||
internal fun File.isKotlinFile(sourceFilesExtensions: List<String>): 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<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 =
|
||||
relativeToOrNull(base)?.path ?: canonicalPath
|
||||
|
||||
|
||||
Reference in New Issue
Block a user