Jakub Chrzanowski
08/28/2025, 9:18 AMconfigurations[configurationName].dependencies.addLater(
myProvider.map { myValue ->
println("myValue=$myValue")
return ...
}
)
And yes, this gets printed 20-30 times when the project is being configured.
Is that expected, and I shouldn't interfere with that, or is using a cached provider a good choice here?Vampire
08/28/2025, 9:38 AMmap on a provider (unless finalizeValue() or finalizeValueOnRead() is used at an appropriate place) is called each time the provider is queried.
So if this gets printed 20-30 times, the provider is queried 20-30 times.
If what you do is stable and fast, you should probably not care too much.
"cached provider" are unfortunately not existing yet. "cached provider" or maybe better "memoized provider" are requested by me in https://github.com/gradle/gradle/issues/25550 together with a way to "fake" them right now for example for expensive calculations.Jakub Chrzanowski
08/28/2025, 9:40 AMinternal inline fun <reified T : Any> cachedProvider(
objects: ObjectFactory,
providers: ProviderFactory,
crossinline value: () -> T,
) = objects
.property<T>()
.value(providers.provider { value() })
.apply {
disallowChanges()
finalizeValueOnRead()
}
but I am reviewing all the code now and started wondering if regular providers (and zips) shouldn't be used instead.Vampire
08/28/2025, 9:41 AMJakub Chrzanowski
08/28/2025, 9:41 AMJakub Chrzanowski
08/28/2025, 9:42 AMVampire
09/04/2025, 11:01 AMList,Map, and Set, and there is now also cachedZip 🙂Jakub Chrzanowski
10/16/2025, 8:56 AM@OptIn(ExperimentalTypeInference::class)
@OverloadResolutionByLambdaReturnType
inline fun <reified T : Any> Project.cachedProvider(
crossinline block: () -> T?
): Provider<out T> =
providers.cachedProvider(objects, block)
why out T?
This causes troubles i.e. when
directoryProperty.set(project.cachedProvider {
File("...")
})
due to
[ARGUMENT_TYPE_MISMATCH] Argument type mismatch: actual type is 'Provider<CapturedType(out File)>', but 'Provider<File!>!' was expected.Jakub Chrzanowski
10/16/2025, 8:57 AM.map { it } 🙃Vampire
10/16/2025, 9:10 AMdirectoryProperty is a DirectoryProperty, then set does only accept File, Directory, or Provider<out Directory>.Vampire
10/16/2025, 9:13 AMdirectoryProperty is a Property<File>, then it also works, because the set parameter is Provider<? extends T> in Java-speak, so Provider<out File> in Kotlin-speak.Jakub Chrzanowski
10/16/2025, 9:20 AMJakub Chrzanowski
10/16/2025, 9:20 AMe: file:///Users/hsz/Projects/JetBrains/intellij-platform-gradle-plugin/src/main/kotlin/org/jetbrains/intellij/platform/gradle/utils/cache.kt:76:46 Type argument is not within its bounds: should be subtype of 'Any'Jakub Chrzanowski
10/16/2025, 9:20 AMout T in
@OptIn(ExperimentalTypeInference::class)
@OverloadResolutionByLambdaReturnType
inline fun <T, reified S : Any> Provider<out T>.cachedMap(
project: Project,
crossinline transformer: (T) -> S?
): Provider<out S> =
cachedMap(project.objects, transformer)Jakub Chrzanowski
10/16/2025, 9:22 AMJakub Chrzanowski
10/16/2025, 9:23 AMT: Any and U: Any helps, but is that expected?Vampire
10/16/2025, 9:24 AMVampire
10/16/2025, 9:25 AMVampire
10/16/2025, 9:27 AMVampire
10/16/2025, 9:27 AMVampire
10/16/2025, 9:29 AM: Any to a all T declarationsJakub Chrzanowski
10/16/2025, 9:29 AMUJakub Chrzanowski
10/16/2025, 9:29 AMRVampire
10/16/2025, 9:29 AMJakub Chrzanowski
10/16/2025, 9:29 AMVampire
10/16/2025, 9:32 AMR? I guessVampire
10/16/2025, 9:48 AMJakub Chrzanowski
10/16/2025, 9:50 AMVampire
10/16/2025, 9:56 AMVampire
10/16/2025, 9:58 AMJakub Chrzanowski
10/16/2025, 9:59 AM