1

Is there a simple method I can use to list all of the properties in a class that don't implement a custom getter?


For example:
class Person(val name: String, val age: Int) {

    val signature: String get() = "$name - $age"
    
    val uuid = UUID.randomUUID()
}

Using the code above, I would like to find the following:

[ Person::name, Person::age, Person::uuid ].

JΛYDΞV
  • 8,532
  • 3
  • 51
  • 77
Andrzej Zabost
  • 1,387
  • 11
  • 26
  • By looking into the generated bytecode I think there is nothing really there to distinguish a generated and custom getter. Fortunately, Kotlin compiler attaches metadata to the generated bytecode and it is quite probable such information is there. Metadata is binary, so I didn't check it by myself, but you can read it with: [kotlinx-metadata](https://github.com/JetBrains/kotlin/blob/master/libraries/kotlinx-metadata/jvm/ReadMe.md) lib. In the source code I see flags like: `IS_SYNTHESIZED`, `IS_DECLARATION` for functions, `HAS_GETTER` for props, etc., so maybe one of them will be helpful. – broot May 28 '21 at 14:56
  • Why do you want to do this?  I can't help wondering if there's a better approach without using reflection.  (Reflection is an advanced tool, but it's slow, fragile, insecure, ugly, and prevents many compile-time checks.  It's needed for specialised situations such as frameworks, plug-ins, and annotation processors, but IME it's very rarely appropriate in general application code, and so is a bit of a code smell. Some of the patterns common in scripting and other dynamic languages don't translate well to static languages such as Java and Kotlin, where there are usually better designs.) – gidds May 28 '21 at 16:37
  • @gidds It's quite difficult to explain exactly why I need this. I have a very narrow use case for it in unit tests. I wrote some [custom equality checking utility](https://github.com/bright/kequality) that is very helpful in some situations to avoid a lot of boilerplate code when comparing large classes with a lot of properties. I would like to filter out the properties with custom getters. – Andrzej Zabost Jun 05 '21 at 19:14

2 Answers2

0

Following code will return a list of all class properties with a backing fields and exclude all artificial properties.

Person::class.memberProperties.filter { it.javaField != null }
qoomon
  • 4,549
  • 1
  • 21
  • 27
-1

Properties that only have a getter do not have a JVM backing field, therefore; you can take all the properties, and exclude the ones that do not have a field.

// All properties
Person::class.declaredMemberProperties.forEach {
    println(it.name)
}
println()

// All fields
Person::class.java.declaredFields.forEach {
    println(it.name)
}
println()

It should be noted that the signature is missing from the second set.


JΛYDΞV
  • 8,532
  • 3
  • 51
  • 77
Nikola Mihajlović
  • 2,286
  • 2
  • 19
  • 23