WARNING: The Compiler Plugin API is very unstable and low-level.
Please consider other options whenever possible. Many use cases for compiler plugins can be addressed by tools like KSP or external linters.
The compiler provides several extension points that can modify its behavior.
Currently, no stable API for compiler plugins is available. This means there is no guarantee that a compiler plugin built against one version of the compiler will work with another version.
You need to either build the compiler plugin within your project or publish versions built specifically for all the compiler versions you need as dependencies.
There are two types of extension points:
This part is specific to the version of the frontend being used.
If you need to work with language versions below 1.9, you must use the K1 Compiler Plugin API.
The frontend part of Compiler Plugin API allows you to:
For new plugins, you should work with the K2 Compiler Plugin API.
The backend part enables you to generate bodies of declarations created in frontend part and modify bodies of preexisting declarations.
This is achieved by changing the compiler's intermediate representation (IR), which is generated by compiler.
The primary entry point for this is the org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension::generate
method.
Unfortunately, there is no comprehensive documentation on what specific IR represents or how it corresponds to Kotlin code.
The best way to understand which IR needs to be generated for your use case is as follows:
Here are some useful utilities for working with IR:
The IrElement.dump()
extension function allows you to inspect IR by logging it or checking it in a debugger within your generate
method.
You can dump IR to text files by passing the following options to the compiler:
-Xphases-to-dump-before=<phase-name>
-Xdump-directory=<path>
You can check the name of the first backend compiler phase to dump IR for the JVM backend here, and in similar places for other backends. Currently, for the JVM backend, the name of the first phase is ExternalPackageParentPatcherLowering
.
There are several plugins in the Kotlin repository, located in the plugins directory.
Also, there is a toy sandbox plugin which tests all existing extension points, and can be used as example for simple cases.