Hello, Is it possible to use KSP to replicate wha...
# ksp
Hello, Is it possible to use KSP to replicate what is done by derive in Rust? With editor support. For instance, with
data class
, compiler will generate some standard code. With
it will perform some transformation as well. Same with
. That’s for keywords, but there are also
for Jetpack Compose and
for Kotlinx.serialization. The last one is really cool. It will generate all of what is needed for de/serialization, and methods such as
are showing errors right away in the IDE if Person is not annotated with
. This does not use KSP (I think), but a compiler plugin. Would KSP be able to reproduce the same experience before execution?
Copy code
import com.me.WithMyFeature
import com.me.useFeature

class Dog

class Person

val dog = Dog()
val person = Person()

dog.useFeature() // No issue

person.useFeature() // Issue
I saw this kind of solution, but that would only work at runtime :/
Copy code
fun Any.useFeature() {
  throw NotImplementedError("missing implementation")
Derive is a proc macro, KSP has some of the same power but not all. For instance it can read the most of the langs AST but nothing expression level. Similarly it can generate new code but can’t edit existing code. For your example yes you could just generate an extension function for the annotated type.
Also note unlike proc macros which work on token streams, ksp works but emitting kotlin source files which are included in the compilation
One way to achieve compile-time error reporting for generated functions is to ~ab~use extension function precedence and
. In your base library you have something like:
Copy code
package myfeature

  message = "Missing implementation",
  level = RequiredOptIn.Level.ERROR
internal annotation class UseFeaturePlaceholder

fun Any.useFeature() = error("Missing implementation")
If you call
you’ll get a compile error with “Missing implementation”. And no one can “opt-in” to the feature because the annotation to do so is internal. Then in your KSP generator you generate the same method signature with a more specific type:
Copy code
package myfeature

// Generated by KSP
fun String.useFeature() = "Real string from feature"
fun Int.useFeature() = 5
Because these have a more specific type but are in the same package they will transparently override the less specific placeholder signature. So now
will compile, as will
, but
will report a missing implementation. The other benefit is that you get a level of auto-completion even if you haven’t run KSP for the first time yet. Depending on the generic signature of
it’s usually good enough to get you where you need to go