---
title: "Suppressing annoying Kotlin compiler warnings"
source: "/writing/suppressing-annoying-kotlin-compiler-warnings/"
---

Article

# Suppressing annoying Kotlin compiler warnings

## Use a Kotlin compiler plugin to automatically rid yourself of those warnings you don't really care about

Sean Weiser

September 8, 2025

We recently found ourselves in a situation where some of the generated code in our networking library was referencing APIs we had just deprecated. This resulted in hundreds of similar lines in our logs at compile time:

This declaration overrides deprecated member but not marked as deprecated itself. Please add @Deprecated annotation or suppress. See https://youtrack.jetbrains.com/issue/KT-47902 for details
'createUser(User): Completable' is deprecated. Please use SuspendingUserOperations.createUser
This declaration overrides deprecated member but not marked as deprecated itself. Please add @Deprecated annotation or suppress. See https://youtrack.jetbrains.com/issue/KT-47902 for details
'getUser(String): Single<User>' is deprecated. Please use SuspendingUserOperations.getUser
This declaration overrides deprecated member but not marked as deprecated itself. Please add @Deprecated annotation or suppress. See https://youtrack.jetbrains.com/issue/KT-47902 for details
'getUsers(): Single<List<User>>' is deprecated. Please use SuspendingUserOperations.getUsers
This declaration overrides deprecated member but not marked as deprecated itself. Please add @Deprecated annotation or suppress. See https://youtrack.jetbrains.com/issue/KT-47902 for details
'updateUser(User): Completable' is deprecated. Please use SuspendingUserOperations.updateUser
...

Our logs became cluttered, causing us problems when trying to find important warnings or errors both locally and when running builds on our CI servers. There were a couple of solutions to this problem:

1.  In our generated code, add the `@Suppress` annotation where necessary. This is the solution we eventually went with, but it's not nearly as interesting as option 2. It just involves hardcoding `@Suppress("DEPRECATION")` immediately before any function definition we detect using the `Deprecated` annotation.
2.  Create a Kotlin compiler plugin to automatically suppress any warnings from these generated files. This is more work initially, but has the potential to be more powerful and flexible than programmatically adding suppressions to our generated code.

So, how can we accomplish option 2?

### Create a new project or module for the plugin

The first step is to create a spot for the plugin code. The code will not be referenced anywhere else, so it can be placed in a number of locations: either in an entirely separate project or a different module within your project. For the purposes of this example, I've created a new module within the project called `custom-compiler-plugin`.

The module's `build.gradle.kts` should look like:

plugins {
    kotlin("jvm")
    id("com.google.devtools.ksp")
}

dependencies {
    implementation(libs.kotlin.compiler.embeddable)
    implementation("com.google.auto.service:auto-service-annotations:1.1.1")

    ksp("dev.zacsweers.autoservice:auto-service-ksp:1.2.0")
}

You'll also need to reference it in the project's `settings.gradle.kts`:

...
include(":custom-compiler-plugin")
...

### Create a suppressor extension

From there, the most important step is actually specifying what logs are going to be suppressed.

In `custom-compiler-plugin/src/main/java/com/example/compilerplugin/ExampleWarningsSuppressor.kt` add the following:

package com.example.compilerplugin

import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.resolve.diagnostics.DiagnosticSuppressor

class ExampleWarningsSuppressor : DiagnosticSuppressor {
    override fun isSuppressed(diagnostic: Diagnostic): Boolean {
        return diagnostic.psiFile.name.contains("_Generated")
    }
}

and modify it to your needs. In the above example, we're suppressing all warnings from any file with a name that contains the substring `_Generated` (e.g. `UserOperations_Generated.kt`). This logic can be as simple or as complex as you want. You could just return `true` and suppress all warnings. Or you can make use of the `[PsiFile](https://github.com/JetBrains/intellij-community/blob/master/platform/core-api/src/com/intellij/psi/PsiFile.java)` and `[PsiElement](https://github.com/JetBrains/intellij-community/blob/master/platform/core-api/src/com/intellij/psi/PsiElement.java)` properties contained in the passed in `[Diagnostic](https://github.com/JetBrains/kotlin/blob/master/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Diagnostic.kt)` object and make suppressions more fine-grained.

### Register the suppressor extension

The next step is to hook into the build system and register your newly created suppressor extension.

In `custom-compiler-plugin/src/main/java/com/example/compilerplugin/ExampleWarningsRegistrar.kt` add:

package com.example.compilerplugin

import com.google.auto.service.AutoService
import org.jetbrains.kotlin.com.intellij.mock.MockProject
import org.jetbrains.kotlin.com.intellij.openapi.extensions.Extensions
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.resolve.diagnostics.DiagnosticSuppressor

@OptIn(ExperimentalCompilerApi::class)
@AutoService(ComponentRegistrar::class)
class ExampleWarningsRegistrar : ComponentRegistrar {
    override fun registerProjectComponents(
        project: MockProject,
        configuration: CompilerConfiguration
    ) {
        Extensions
            .getRootArea()
            .getExtensionPoint(DiagnosticSuppressor.EP_NAME)
            .registerExtension(ExampleWarningsSuppressor())
    }
}

The only difference should be the name of the registrar and the object you pass into `registerExtension()`. If you want to expand the functionality of this registrar beyond just a diagnostic suppressor, there are other extension point names that can be used instead, but that goes beyond the scope of this article.

Note that this class is using the `@AutoService` annotation. Typically you'd need to create a resource file called `META-INF/services/org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar` that points to your registrar class, but that is automatically handled for you when this particular annotation is applied.

### Compile to a JAR and reference it in the application or library module

Whether you've added a new module to your project or created an entirely new project for the plugin, the final step will be to generate a JAR. From the command line, run:

./gradlew custom-compiler-plugin:assemble

Then copy the generated JAR from the `build/libs` directory to somewhere in your project. For this example I've moved it to a `libs` folder under the root directory.

In your application or library module's `build.gradle.kts` add the following:

...
android {
    ...
    kotlinOptions {
        freeCompilerArgs = listOf(
            ...
            "-Xplugin=$rootDir/libs/custom-compiler-plugin.jar"
        )
    }
}
...

Be sure to update the file name and path based on where you ended up placing the JAR.

Note that using a local JAR requires manually updating the `freeCompilerArgs` as described above. However, if you're able to publish your binary, either locally or to a remote repository like Maven, there are alternatives to modifying the compiler argument list yourself. I'll explore these in a future article, but a couple of well known libraries are able to handle this in their own way:

-   The Jetpack Compose compiler plugin defines its [Gradle plugin](https://github.com/JetBrains/kotlin/blob/master/libraries/tools/kotlin-compose-compiler/build.gradle.kts?utm_source=chatgpt.com#L14) as a `[KotlinCompilerPluginSupportPlugin](https://kotlinlang.org/api/kotlin-gradle-plugin/kotlin-gradle-plugin-api/org.jetbrains.kotlin.gradle.plugin/-kotlin-compiler-plugin-support-plugin/)` . By doing so, the published JAR will automatically be included as a plugin in the compiler argument list.
-   Hilt does the same thing, but in a round-about way. Hilt uses KSP to run its annotation processors. Internally, KSP defines a [Gradle plugin](https://github.com/google/ksp/blob/8c02de73198e184a645344b63fdd307db9afed8a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt#L82) that also subclasses `KotlinCompilerPluginSupportPlugin`, which handles the compiler arguments just like Compose.

### Compile your project

The final step is to compile your project and verify those warnings have been eliminated. If you need to make adjustments you'll mostly likely need to update the `isSuppressed` function in the suppressor class. Each time you make changes you'll also need to recompile the plugin JAR and copy it back into your project.

Once you confirm that everything is working, sit back and enjoy your clean, easy to read logs.

Sean works at [Livefront](https://livefront.com) , where he tries not to ignore too many warnings (at least the important ones).

-   Sean Weiser

    Principal Software Engineer

    [More from Sean](/team/sean-weiser/)

    Sean Weiser

### Tags

[Digital Engineering](/insights/all/?topic=digital-engineering) [Mobile Apps](/insights/all/?topic=mobile-apps)

### Share

-   Copied

## View these next.

[See all](/insights/all/?type=writing)

-   [

    Article

    How To Sabotage Your Project Using Inconsistency

    Collin Flynn

    ](/writing/how-to-sabotage-your-project-using-inconsistency/)
-   [

    Article

    Unit Testing race conditions by creating chaos (Swift)

    Sean Berry

    ](/writing/unit-testing-race-conditions-by-creating-chaos-swift/)
-   [

    Article

    UIApplicationDelegate call sequence reference

    Sean Berry

    ](/writing/uiapplicationdelegate-call-sequence-reference/)
