(simplified from the real life usage but) I have c...
# compiler
e
(simplified from the real life usage but) I have code structured like this and I'd like not to have to manually keep
entries
up to date nor write out the
values
overrides when they're basically all the same shape.
for
entries
, we ended up using
Copy code
val entries: List<Switch<*>> = Switch::class.sealedSubclasses.map { it.objectInstance as Switch<*> }
(well actually we're nesting the classes and using
Copy code
val entries: List<Switch<*>> = Switch::class.java.declaredClasses.mapNotNull {
    if (Switch::class.java.isAssignableFrom(it)) {
        it.getDeclaredField("INSTANCE").apply { isAccessible = true }.get(null) as Switch<*>
    } else null
}
to avoid kotlin.reflect at runtime, but it's basically the same idea)
I wrote a compiler plugin for this case https://kotlinlang.slack.com/archives/C7L3JB43G/p1771344614011309?thread_ts=1771212496.882179&amp;cid=C7L3JB43G which works but it hasn't really been worth the effort keeping it up to date
so I've recently been looking into writing a compiler plugin to automatically generate the
values
overrides, but ran into issues
1. does this need to be a FIR plugin? I was expecting no, since it's fine if
Ternary.values
resolves to
Switch::values.invoke(Ternary)
2. without the presence of the
overload val
in the subclasses, I still see
IrProperty("values")
and
IrFunction("<get-values>")
when processing the subclasses. however, even if I add bodies to them or replace them entirely in an
IrElementTransformerVoid
, my changes don't seem to show up in the compiled classes. is there something magically eliding them?
p
For 2, probably, this overrides have fakeOverride flag, and you need to remove it. Compiler don't expect something to be both fake override and have body, so probably body would be just ignored in most cases.
➕ 1
For 1, wouldn't you get abstract method not implemented without it? Probably you can add a default implementation, to make it open, and than add overrides on IR level, but looks quite fragile.
➕ 1
Another option I could recommend is having an extension instead.
Copy code
inline <reified T> val Switch<T>.values = enumEntries<T>()
But then you wouldn't be able to call on unknown type, so maybe it's not that useful.
y