Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin: ProGuard erases properties attributes

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 classes 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...

like image 601
quezak Avatar asked Dec 23 '22 18:12

quezak


1 Answers

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...)

like image 142
quezak Avatar answered Dec 28 '22 06:12

quezak