| # Compiler Plugins | |
| **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](https://kotlinlang.org/docs/ksp-overview.html) 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. | |
| ## Types of Extension Points | |
| There are two types of extension points: | |
| 1. **Frontend extension points** – Required for working with declarations that need to be visible during resolution. | |
| 2. **Backend extension points** – Required for working with declaration bodies and private declarations. | |
| ## Frontend Part | |
| 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: | |
| - Declare new publicly visible declarations. | |
| - Modify some properties of existing declarations. | |
| - Provide additional compiler warnings and errors relevant to your plugin. | |
| For new plugins, you should work with the [K2 Compiler Plugin API](../fir/fir-plugins.md). | |
| ## Backend Part | |
| 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: | |
| 1. Write the code that you want to generate manually. | |
| 2. Observe the IR generated by the compiler for that code. | |
| 3. Mimic the generated IR as closely as possible. | |
| 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](../../compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/JvmLoweringPhases.kt), and | |
| in similar places for other backends. Currently, for the JVM backend, the name of the first phase is `JvmUpgradeCallableReferences`. | |
| ## Examples | |
| There are several plugins in the Kotlin repository, located in the [plugins](../../plugins) directory. | |
| Also, there is a toy [sandbox plugin](../../plugins/plugin-sandbox) which tests all existing extension points, and can be used as example for simple cases. |