:wave: I want to write a small compiler plugin tha...
# k2-adopters
p
👋 I want to write a small compiler plugin that adds information about call site when calling a target logging API. E.g. writing:
Copy code
fun somewhere() {
  log("foo")
}
would compile down to:
Copy code
fun somewhere() {
  log("somewhere()", "foo")
}
or
Copy code
fun somewhere() {
  log("Somewhere.kt", "foo")
}
From what I can tell, it looks like I need to write "backend" plugin, as this is modifying bytecode? Correct me if wrong plz. I found this recent example: https://github.com/thalesdev/first-kotlin-compiler-plugin to get started with a kotlin compiler plugin. So now I'm trying to figure out how to learn the details of the compiler related data structures, what I need to read, the transformations to do.. would love pointers there, recent examples, etc. I'm not even sure this is the right channel to ask this question in, plz redirect me as needed
m
Strongly recommended:

https://www.youtube.com/watch?v=9P7qUGi5_gc

And #C7L3JB43G will probably be more helpful
If you want to modify the bytecode, another option is to use a Java agent and something like ASM, it might be easier. But of course not multiplatform.
k
You should look at this plugin as inspiration https://github.com/JakeWharton/cite
m
But
cite
is probably even closer to the use case here
j
I haven’t updated it in a while but the refactor compiler plugin branch from my logger repo is what you want: • https://github.com/JavierSegoviaCordoba/mokoki/tree/refactor-compiler-plugin
You shouldn’t need to do anything on FIR, but just IR
👍 1
You should use the official template tho, if you need any help about how to work on it, DM me :P
p
Interesting!
"the official template" => where's that?
p
what's Mokoti doing btw? can't find any docs
j
Do you mean in IR?
Basically, there is a function which accepts a bunch of parameters, those parameters are picked in compilation time:
Copy code
@Mokoki
@PublishedApi
internal fun internalLog(
    priority: Priority? = null,
    tag: String? = null,
    kType: KType,
    fileLink: String,
    fileName: String,
    classExhaustiveKind: String,
    className: String,
    functionName: String,
    lineNumber: Int,
    message: () -> String,
) {
    ...
}
So, if I remember correctly, I was replacing the original
log
call with that internal call, passing all the necessary parameters so they can be shown in the terminal
I am not sure if cite provides everything you want, if so, probably you don't need to create a compiler plugin but just use cite 😛
p
no actually it's more like what you do
cite is good inspiration, your plugin too
I want to revisit this little library to get the filename of the callsite correctly: https://github.com/square/logcat
the only additional / interesting challenge is the use of an inlined log function to avoid allocations when logging is disabled
j
Probably you can use cite for that then
p
I can't use Cite directly, no: I don't want consumers of the library to have to type
__FILE__
but I likely can rebuild what Cite did
j
haven't checked, so not sure if de consumers needs to call
__FILE__
directly, what would happens if it is used in a default argument? Original function, or call site? 🤔
p
I did try that first haha, and that resolves to the file where the log function is defined 🙂
👀 1
this is the main part: find calls to the log function, if the first arg is null, swap it with the file name
tbh no idea why an argument with a default param value ends up as passing null
but hey that seems to work, good enough for a quick prototype to make sure it'd work