All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.gradle.utils.providerApiUtils.kt Maven / Gradle / Ivy

There is a newer version: 2.1.0-RC
Show newest version
/*
 * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
 * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
 */

package org.jetbrains.kotlin.gradle.utils

import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.Directory
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.*
import java.io.File
import kotlin.reflect.KProperty

// Workaround for https://github.com/gradle/gradle/issues/12388
// which should be fixed via https://github.com/gradle/gradle/issues/24767
internal fun  Provider.mapOrNull(
    providerFactory: ProviderFactory,
    block: (IN) -> OUT?
): Provider = flatMap { providerFactory.provider { (block(it)) } }

internal operator fun  Provider.getValue(thisRef: Any?, property: KProperty<*>) = get()

internal operator fun  Property.setValue(thisRef: Any?, property: KProperty<*>, value: T) {
    set(value)
}

internal fun  Project.newProperty(initialize: (() -> T)? = null): Property =
    @Suppress("UNCHECKED_CAST")
    (project.objects.property(Any::class.java) as Property).apply {
        if (initialize != null)
            set(provider(initialize))
    }

internal inline fun  ObjectFactory.property() = property(T::class.java)

internal inline fun  ObjectFactory.listProperty() = listProperty(T::class.java)

internal inline fun  ObjectFactory.setProperty() = setProperty(T::class.java)

internal inline fun  ObjectFactory.property(initialValue: T) = property().value(initialValue)

internal inline fun  ObjectFactory.property(initialValue: Provider) = property().value(initialValue)

internal inline fun  ObjectFactory.setPropertyWithValue(
    initialValue: Provider>
) = setProperty().value(initialValue)

internal inline fun  ObjectFactory.setPropertyWithValue(
    initialValue: Iterable
) = setProperty().value(initialValue)

internal inline fun  ObjectFactory.setPropertyWithLazyValue(
    noinline lazyValue: () -> Iterable
) = setPropertyWithValue(providerWithLazyConvention(lazyValue))

internal inline fun  ObjectFactory.propertyWithConvention(
    conventionValue: Provider
) = property().convention(conventionValue)

internal inline fun  ObjectFactory.propertyWithConvention(
    conventionValue: T
) = property().convention(conventionValue)

internal inline fun  ObjectFactory.listPropertyWithConvention(
    conventionValue: Iterable
) = listProperty().convention(conventionValue)

internal inline fun  ObjectFactory.providerWithLazyConvention(
    noinline lazyConventionValue: () -> T
) = property(lazyConventionValue).map { it.invoke() }

internal inline fun  ObjectFactory.newInstance() = newInstance(T::class.java)

internal inline fun  ObjectFactory.newInstance(vararg parameters: Any) =
    newInstance(T::class.java, *parameters)

internal inline fun  ObjectFactory.propertyWithNewInstance(
    vararg parameters: Any
) = propertyWithConvention(newInstance(T::class.java, *parameters))

internal fun > T.chainedFinalizeValueOnRead(): T =
    apply {
        finalizeValueOnRead()
    }

internal fun > T.chainedFinalizeValueOnRead(): T =
    apply {
        finalizeValueOnRead()
    }

internal fun > T.chainedFinalizeValue(): T =
    apply {
        finalizeValue()
    }

internal fun > T.chainedDisallowChanges(): T =
    apply {
        disallowChanges()
    }

internal fun > T.chainedDisallowChanges(): T =
    apply {
        disallowChanges()
    }


// Before 5.0 fileProperty is created via ProjectLayout
// https://docs.gradle.org/current/javadoc/org/gradle/api/model/ObjectFactory.html#fileProperty--
internal fun Project.newFileProperty(initialize: (() -> File)? = null): RegularFileProperty {
    val regularFileProperty = project.objects.fileProperty()

    return regularFileProperty.apply {
        if (initialize != null) {
            set(project.layout.file(project.provider(initialize)))
        }
    }
}

internal fun ObjectFactory.fileProperty(initialValue: File): RegularFileProperty = fileProperty()
    .apply { set(initialValue) }

internal fun ObjectFactory.directoryProperty(initialValue: File): DirectoryProperty = directoryProperty()
    .apply { set(initialValue) }

internal fun Project.filesProvider(
    vararg buildDependencies: Any,
    provider: () -> Any?
): ConfigurableFileCollection {
    return project.files(provider).builtBy(*buildDependencies)
}

internal fun  T.outputFilesProvider(provider: T.() -> Any): ConfigurableFileCollection {
    return project.filesProvider(this) { provider() }
}

internal inline fun  Project.listProperty(noinline itemsProvider: () -> Iterable): ListProperty =
    objects.listProperty(T::class.java).apply { set(provider(itemsProvider)) }

internal inline fun  Project.setProperty(noinline itemsProvider: () -> Iterable): SetProperty =
    objects.setProperty(T::class.java).apply { set(provider(itemsProvider)) }

/**
 * Changing Provider will be evaluated every time it accessed.
 *
 * And its producing [code] will be serilalised to Configuration Cache as is
 * So that it still will be evaluated during Task Execution phase.
 * It is very convenient for Configuration Cache compatibility.
 *
 * It is recommended to use Task Output's and map/flatMap them to other Task Inputs but in cases when TaskOutput's is not available
 * as Gradle's Properties or Providers then this [changing] provider can be used.
 *
 * name `changing` and overall concept is borrowed from Gradle internal API [org.gradle.api.internal.provider.Providers.changing]
 *
 * @see org.gradle.api.internal.provider.ChangingProvider
 */
internal fun  ProviderFactory.changing(code: () -> T): Provider {
    @Suppress("UNCHECKED_CAST")
    val adhocValueSourceClass = AdhocValueSource::class.java as Class>
    return of(adhocValueSourceClass) { valueSourceSpec ->
        valueSourceSpec.parameters {
            it.producingLambda.set(code)
        }
    }
}

private abstract class AdhocValueSource : ValueSource {

    // this interface can't be parameterized with T since it breaks internal Gradle logic
    // This is why producingLambda is '() -> Any?' but not '() -> T'
    interface Parameters : ValueSourceParameters {
        val producingLambda: Property<() -> Any?>
    }

    override fun obtain(): T {
        @Suppress("UNCHECKED_CAST")
        return parameters.producingLambda.get().invoke() as T
    }
}

internal fun Provider.dir(path: String): Provider = map { it.dir(path) }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy