Niels Doucet
09/30/2025, 1:50 PMMapProperty is confusing, or I'm doing something wrong.
There seems to be a difference in behavior between using putAll vs individual put invocations when setting lazy Provider instances as values for these keys.
Details in thread ๐งตNiels Doucet
09/30/2025, 1:50 PMMapProperty using putAll, it seems I can't provide entry values with Providers. e.g.
myExtension.mapProp.putAll(mapOf(
"key1" to providers.provider { "myLazyStringValue" },
"key2" to providers.provider { "myOtherLazyStringValue" },
))
When reading from this map, I get back an instance of org.gradle.api.internal.provider.TransformBackedProvider instead of the expected `String`:
assertInstanceOf<String>(myExtension.mapProp.get()["key1"])
results in
Unexpected type, expected: <java.lang.String> but was: <org.gradle.api.internal.provider.TransformBackedProvider>
Expected :class java.lang.String
Actual :class org.gradle.api.internal.provider.TransformBackedProvider
Yet individual put statements do work. e.g.
myExtension.mapProp.run {
put("key1", providers.provider { "myLazyStringValue" }
put("key2", providers.provider { "myOtherLazyStringValue" }
}
When reading from this map, I get back the expected String and the assertion passes.
Are my expectations for putAll wrong? If so could this be made explicit in the documentation/javadoc?Mikhail Lopatkin
09/30/2025, 1:58 PMMapProperty a MapProperty<String, Object>? Otherwise the putAll shouldn't compile.Martin
09/30/2025, 1:58 PMProperty<Map> were allowed. Most of the time, I don't need per-collector laziness and the mental model would be a lot simpler.Niels Doucet
09/30/2025, 1:59 PM@get:Input val mapProp: MapProperty<String, Any>Niels Doucet
09/30/2025, 2:00 PMStringMikhail Lopatkin
09/30/2025, 2:21 PMString), and for lazy values (accepting providers of value types, like Provider<String>). There are also "batch" versions, accepting either collection of values (Iterable<String>) or lazy collection of values (Provider<Iterable<String>>). There is no version that accepts a collection of lazy values, because these can be trivially expressed with the lazy value inserter, like: mapOfProviders.forEach(mapProperty::put) (and generic erasure gets in the way if we want to provide an overload).
The type signatures of the inserter methods already make the contract quite obvious, IMO. Unfortunately, with Any you don't have the type restriction to help.Niels Doucet
09/30/2025, 2:47 PMput(K key, Provider<V> providerOfValue) would "play nice" with putAll.
But given that I looked through the javadoc multiple times while implementing this and I still ended up doing it wrong, indicates to me that it's not very intuitive.
Perhaps an @apiNote in the javadoc for putAll that warns about V == Any/Object and the pitfall of adding value-providers in that case?
I do understand it's a corner-case and the api is mostly clear (thank you for providing the extra context), but it still leads to a confusing situation.Adam
09/30/2025, 4:16 PM