TL;DR: with proguard enabled, when using reflection, my properties look private, non-nullable and without annotations, despite proguard config that should keep all these attributes.
I have some simple data class
es with public properties to serve as data models in my Android app. Later, when doing generic [de]serialization of said classes, I filter the property list like this:
val properties = instance::class.memberProperties
.filter { it.visibility == KVisibility.PUBLIC } // && some other conditions, unrelated here
.filterIsInstance<KMutableProperty<*>>()
It works normally on my debug builds (I mean it selects the properties I want it to). But, when doing a release build, where proguard is active, the result is empty. To check why, I logged all the relevant stuff about the properties of one class -- turns out their visibility
field reads PRIVATE
(and all other attributes remain the same as on a debug build).
I already have a line in proguard config to keep all the models:
-keepclassmembers class * extends com.models.package.name.BaseModel { *; }
I tried this one before, with same result:
-keep class com.models.package.name.** { *; }
Why/how does proguard affect property visibility? Should I modify the config somehow? Or am I missing something else here?
UPDATE: It seems like visibility is not the only thing. prop.returnType.isMarkedNullable
also doesn't work, it returns false
for properties declared nullable. And annotations also seem to get lost, even though I asked proguard to keep them. Is there any way to work around this? It pretty much renders 2 weeks of my work useless...
Thanks to the suggestion from @yole in question comments, I've been able to make this work. Even though my classes were configured to be kept by ProGuard, it stripped the kotlin.Metadata
annotations from them. These annotatons are where Kotlin stores all the attributes I was missing. The solution is to prevent ProGuard from deleting them, adding to configuration:
-keep class kotlin.Metadata { *; }
(on a side note: it's weird that it's not included in the default config, at least if you're using the kotlin.reflect.full
package. Or at least it should be mentioned clearly somewhere in the docs...)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With