
I’m currently working on a pet project: a Kotlin assertion library designed to handle deep assertions over any object type. The goal is to write code that looks like this:
confirmThat { (1..3).toList() } deepMatches { listOf(1, 2, 3) }To make this work, the library needs to convert arbitrary code into a structured matcher tree. Under the hood, the goal is to transform that simple list check into something like this:
confirmThat { (1..3).toList() } deepMatches {
ListMatcher(
ValueMatcher(1),
ValueMatcher(2),
ValueMatcher(3)
)
}To pull this off, I weighed two sophisticated technical paths:
Option 1: Runtime Bytecode Manipulation
The first option is to modify the compiled bytecode while the application is running using tools like Byte Buddy.
- The Pro: It’s a standard way to handle introspection on the JVM without needing a custom compiler setup.
- The Con: It has very limited capabilities because Kotlin-specific details — like null-safety metadata — are often erased or transformed once the code is compiled. Many things are just impossible — e.g. you cannot convert primitives (
int) into objects (Int), which might make it impossible to replaceintwithIntMatcher.
Option 2: Kotlin Intermediate Representation (IR)
The more “hardcore” approach is hijacking the Kotlin compilation process itself. By using a Kotlin Compiler Plugin, I can intercept the IR (Intermediate Representation). This happens after the code is parsed but before it undergoes any “lowering” steps (converting high-level constructs into simpler ones) or gets turned into bytecode.
- The Pro: This allows me to see the code in its purest form. I can generate highly efficient, type-safe matchers that are baked directly into the program.
- The Con: It’s significantly more complex to implement since it requires working deep within the compiler’s internal mechanics.
My Take
I decided to go the “hardcore” route. I’ve been experimenting with Kotlin IR, and it works perfectly! It handles the primitive-to-object mapping and null-safety metadata with ease.
Stay tuned—I’ll be sharing more on how I actually implemented the IR transformer in my next post.
Leave a Reply