Roman Levinzon
10/24/2023, 6:17 PMlibrary
that has following code
interface Helper<T> { /* some methods */ }
inline fun<reified T> resolver() : Helper<T> {
throw NotImplementedException()
}
An then there is a kotlin compiler plugin that is applied to main
module
The idea is that every invocation of resolver
will be replaced with specific implementation of Helper
based on the type T
The implementation itself is generated using IrGenerationExtension
and placed as the companion object
So for example after compilation is done, based on this class
@MyAnnotation
data class Test(val data: String)
There is now a Test.Helper
instance which is a type of Helper<Test>
So, in theory, resolver
here would be replaced
fun main() {
val helper: Helper<Test> = resolver() // Test.Helper
}
This all works, but only for the invocation happening in my module where the plugin is applied. Which makes sense I guess
What I would like to achieve is following
I have multiple utility functions in my library, that take advantage of resolver
and I would like to make the same there
So for instance, if I have this utility function
inline fun<reified T> utility() : Helper<T> {
val helper = resolver()
// do something with helper
}
And then if I call this utility in my main module, it should not throw, since the resolver
is replaced
fun main() {
utility<Test>()
}
Is this possible? If not, is there some workaround I can use, i.e adjusting the library code to make it easier for compiler to pickup
Here is what I tried so far
• IrGenerationExtension
can’t go to that level that I want to
• Tried using ClassGenerationExtension
to modify the bytecode, but it seems it can’t go that deep as well
• Tried making resolver()
invocation as parameter of the utility functions, thinking it would be easier to replace it but it breaks inlining for some reason
Appreciate all the help 🙏