CallSiteIrTransformer
Rewrites every call to a log4k logging entry point so the emitted event carries a compile-time io.github.smyrgeorge.log4k.SourceLocation — the call's file, line, and enclosing function. Because the values are baked in as constants, accurate source locations cost no runtime stack-walking, and work uniformly on every Kotlin target (including Native, JS, and Wasm, where walking the stack is expensive or impossible).
Intercepted entry points, and how each is rewritten:
Logger.log(level, span, tags, message, arguments, throwable)— retargeted to the overload with the trailingcallSiteparameter, all other arguments copied verbatim.Logger.at(level) { … }and theatTrace/…/atErrorshorthands — retargeted toat(level, callSite, f); the builder lambda stays in inline position, so its laziness (and any non-local returns inside it) are preserved.The level-named
trace/debug/info/warn/error(…)forwarders — the classic extensions (log4k-classic), the context-aware overloads (log4k-context,context(TracingContext)/context(Span)), and thelog.classic.…escape hatch (Log4kClassic) — remapped directly ontoLogger.log(…, callSite). They are all trivial forwarders, so the plugin re-derives the mapping from the callee's signature instead of hardcoding each shape: the level comes from the function name, every value parameter is classified by its type (Span/Tags/Stringmessage /() -> Stringlazy message /Throwable/ vararg arguments), aLog4kClassicreceiver is unwrapped through itsloggerproperty, and a context parameter contributes the span (aSpandirectly; aTracingContextviacurrentOrNull()). Argument expressions are evaluated into temporaries in their original order, so side-effect ordering is unchanged. A lazy{ … }message lambda is invoked behind anisEnabled(level)guard — mirroring the level gate the original inline extension compiled to — so a disabled logger still costs neither the message building nor the lambda allocation.
A call is left untouched (keeping a null call site, never breaking compilation) when:
A classic lazy-message lambda contains a non-local jump — a
return,break, orcontinuetargeting an enclosing function or loop (it cannot be moved behind the guard);The callee's shape is not recognized (e.g., a future log4k adds a parameter this plugin predates);
The call has no source offsets (synthetic code).