Home

Awesome

Ktlint Gradle

Provides a convenient wrapper plugin over the ktlint project.

<!-- Note: if changing the line below, the `sed` command in the perform-release.yaml needs to be updated too -->

Latest plugin version: 12.1.1

Join the chat at https://kotlinlang.slack.com Build and Check ktlint Gradle Plugin Portal OpenSSF Scorecard

This plugin creates convenient tasks in your Gradle project that run ktlint checks or do code auto format.

The plugin can be applied to any project, but only activates if that project has the kotlin plugin applied. The assumption being that you would not want to lint code you weren't compiling.

Table of content

Supported Kotlin plugins

This plugin supports the following kotlin plugins:

If you know any new Kotlin plugin that is not in this list - please, open a new issue.

How to use

Minimal supported versions

This plugin was written using the new API available for the Gradle script Kotlin builds. This API is available in new versions of Gradle.

Minimal supported Gradle version: 7.4

Minimal supported Kotlin version: 1.4

Minimal supported ktlint version: 0.47.1

Minimal supported Android Gradle plugin version: 4.1.0

Ktlint plugin

Simple setup

Build script snippet for new plugin mechanism introduced in Gradle 2.1:

<details> <summary>Groovy</summary>
plugins {
  id "org.jlleitschuh.gradle.ktlint" version "<current_version>"
}

repositories {
  // Required to download KtLint
  mavenCentral()
}
</details> <details open> <summary>Kotlin</summary>
plugins {
  id("org.jlleitschuh.gradle.ktlint") version "<current_version>"
}

repositories {
  // Required to download KtLint
  mavenCentral()
}
</details>

Using Version Catalog

To configure the plugin using a version catalog, first, add the following entries to your libs.versions.toml file:

[versions]
ktlint = "<current_version>"

[plugins]
ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" }

Next, apply it to your project:

<details> <summary>Groovy</summary>
plugins {
  alias(libs.plugins.ktlint)
}

repositories {
  // Required to download KtLint
  mavenCentral()
}
</details> <details open> <summary>Kotlin</summary>
plugins {
  alias(libs.plugins.ktlint)
}

repositories {
  // Required to download KtLint
  mavenCentral()
}
</details>

Using legacy apply method

Build script snippet for use in all Gradle versions:

<details> <summary>Groovy</summary>
buildscript {
  repositories {
    maven {
      url "https://plugins.gradle.org/m2/"
    }
  }
  dependencies {
    classpath "org.jlleitschuh.gradle:ktlint-gradle:<current_version>"
  }
}

repositories {
  // Required to download KtLint
  mavenCentral()
}

apply plugin: "org.jlleitschuh.gradle.ktlint"
</details> <details> <summary>Kotlin</summary>
buildscript {
  repositories {
    maven("https://plugins.gradle.org/m2/")
  }
  dependencies {
    classpath("org.jlleitschuh.gradle:ktlint-gradle:<current_version>")
  }
}

repositories {
  // Required to download KtLint
  mavenCentral()
}

apply(plugin = "org.jlleitschuh.gradle.ktlint")
</details>

Applying to subprojects

Optionally apply plugin to all project modules:

<details> <summary>Groovy</summary>
subprojects {
    apply plugin: "org.jlleitschuh.gradle.ktlint" // Version should be inherited from parent

    repositories {
        // Required to download KtLint
        mavenCentral()
    }

    // Optionally configure plugin
    ktlint {
        debug = true
    }
}
</details> <details open> <summary>Kotlin</summary>
subprojects {
    apply(plugin = "org.jlleitschuh.gradle.ktlint") // Version should be inherited from parent

    repositories {
        // Required to download KtLint
        mavenCentral()
    }

    // Optionally configure plugin
    configure<org.jlleitschuh.gradle.ktlint.KtlintExtension> {
        debug.set(true)
    }
}
</details>

Baseline support

Plugin supports KtLint baseline with following limitations:

Run task ktlintGenerateBaseline to generate a new baseline.

Testing KtLint snapshots

To test KtLint snapshots add following configuration into project build script (latest KtLint snapshot version name you could find here):

<details> <summary>Groovy</summary>
repositories {
    maven {
      url 'https://oss.sonatype.org/content/repositories/snapshots'
    }
}

ktlint {
  version = "0.41.0-SNAPSHOT"
}
</details> <details open> <summary>Kotlin</summary>
repositories {
    maven("https://oss.sonatype.org/content/repositories/snapshots")
}

ktlint {
    version.set("0.41.0-SNAPSHOT")
}
</details>

IntelliJ Idea Only Plugin

Note: This plugin is automatically applied by the main ktlint plugin.

This plugin just adds special tasks that can generate IntelliJ IDEA codestyle rules using ktlint.

Idea plugin simple setup

Build script snippet for new plugin mechanism introduced in Gradle 2.1:

plugins {
  id("org.jlleitschuh.gradle.ktlint-idea") version "<current_version>"
}

Idea plugin setup using legacy apply method

For all Gradle versions:

Use the same buildscript logic as above, but with this instead of the above suggested apply line. If you also want the GIT pre-commit gradle tasks, keep both apply variations.

apply plugin: "org.jlleitschuh.gradle.ktlint-idea"

Configuration

The following configuration block is optional.

If you don't configure this the defaults defined in the KtlintExtension object will be used.

The version of ktlint used by default may change between patch versions of this plugin. If you don't want to inherit these changes then make sure you lock your version here. Consult the ktlint release notes for more information about the differences between ktlint versions.

<details> <summary>Groovy</summary>
import org.jlleitschuh.gradle.ktlint.reporter.ReporterType

ktlint {
    version = "0.22.0"
    debug = true
    verbose = true
    android = false
    outputToConsole = true
    outputColorName = "RED"
    ignoreFailures = true
    enableExperimentalRules = true
    additionalEditorconfigFile = file("/some/additional/.editorconfig")  // not supported with ktlint 0.47+
    additionalEditorconfig = [ // not supported until ktlint 0.49
        "max_line_length": "20"
    ]
    disabledRules = ["final-newline"] // not supported with ktlint 0.48+
    baseline = file("my-project-ktlint-baseline.xml")
    reporters {
        reporter "plain"
        reporter "checkstyle"
        reporter "sarif"

        customReporters {
            "csv" {
                fileExtension = "csv"
                dependency = project(":project-reporters:csv-reporter")
            }
            "yaml" {
                fileExtension = "yml"
                dependency = "com.example:ktlint-yaml-reporter:1.0.0"
            }
        }
    }
    kotlinScriptAdditionalPaths {
        include fileTree("scripts/")
    }
    filter {
        exclude("**/generated/**")
        include("**/kotlin/**")
    }
}

dependencies {
    ktlintRuleset "com.github.username:rulseset:main-SNAPSHOT"
    ktlintRuleset files("/path/to/custom/rulseset.jar")
    ktlintRuleset project(":chore:project-ruleset")
}
</details>

or in kotlin script:

<details open> <summary>Kotlin</summary>
import org.jlleitschuh.gradle.ktlint.reporter.ReporterType

configure<org.jlleitschuh.gradle.ktlint.KtlintExtension> {
    version.set("0.22.0")
    debug.set(true)
    verbose.set(true)
    android.set(false)
    outputToConsole.set(true)
    outputColorName.set("RED")
    ignoreFailures.set(true)
    enableExperimentalRules.set(true)
    additionalEditorconfigFile.set(file("/some/additional/.editorconfig")) // not supported with ktlint 0.47+
    additionalEditorconfig.set( // not supported until ktlint 0.49
        mapOf(
            "max_line_length" to "20"
        )
    )
    disabledRules.set(setOf("final-newline")) // not supported with ktlint 0.48+
    baseline.set(file("my-project-ktlint-baseline.xml"))
    reporters {
        reporter(ReporterType.PLAIN)
        reporter(ReporterType.CHECKSTYLE)

        customReporters {
            register("csv") {
                fileExtension = "csv"
                dependency = project(":project-reporters:csv-reporter")
            }
            register("yaml") {
                fileExtension = "yml"
                dependency = "com.example:ktlint-yaml-reporter:1.0.0"
            }
        }
    }
    kotlinScriptAdditionalPaths {
        include(fileTree("scripts/"))
    }
    filter {
        exclude("**/generated/**")
        include("**/kotlin/**")
    }
}

dependencies {
    ktlintRuleset("com.github.username:rulseset:main-SNAPSHOT")
    ktlintRuleset(files("/path/to/custom/rulseset.jar"))
    ktlintRuleset(project(":chore:project-ruleset"))
}
</details>

Setting reports output directory

It is possible also to define different from default output directory for generated reports (by default it is "build/reports/ktlint"):

<details> <summary>Groovy</summary>
tasks.withType(org.jlleitschuh.gradle.ktlint.tasks.GenerateReportsTask) {
    reportsOutputDirectory = project.layout.buildDirectory.dir("other/location/$name")
}
</details> <details open> <summary>Kotlin script</summary>
tasks.withType<org.jlleitschuh.gradle.ktlint.tasks.GenerateReportsTask> {
    reportsOutputDirectory.set(
        project.layout.buildDirectory.dir("other/location/$name")
    )
}
</details>

Custom reporters

Note: If Ktlint custom reporter creates report output file internally, for example:

class CsvReporter(
    private val out: PrintStream
) : Reporter {
    override fun onLintError(file: String, err: LintError, corrected: Boolean) {
        val line = "$file;${err.line};${err.col};${err.ruleId};${err.detail};$corrected"
        out.println(line)
        File("some_other_file.txt").write(line) // <-- Here!!!
    }
}

"some_other_file.txt" won't be captured as task output. This may lead to the problem, that task will always be not "UP_TO_DATE" and caching will not work.

Changing workers memory usage

By default, KtLint Gradle workers will use at most 256mb of heap size. For some projects it may be not enough, but it is possible to change:

<details> <summary>Groovy</summary>
tasks.withType(org.jlleitschuh.gradle.ktlint.tasks.BaseKtLintCheckTask).configureEach {
    it.workerMaxHeapSize.set("512m")
}
</details> <details open> <summary>Kotlin script</summary>
tasks.withType<org.jlleitschuh.gradle.ktlint.tasks.BaseKtLintCheckTask> {
    workerMaxHeapSize.set("512m")
}
</details>

Samples

This repository provides the following examples of how to set up this plugin:

Tasks Added

Main tasks

This plugin adds following tasks to every project:

Then for each SourceSet plugin adds following tasks:

Additional helper tasks

Following additional tasks are added:

All these additional tasks are always added only to the root project.

FAQ

Yes. Just use gradle --continue option:

$ ./gradlew --continue ktlintCheck

No. These approaches are not equivalent to how they work. The problem that the plugin may not find some of the kotlin plugins if both approaches are used in the project configuration. Especially it is related to the Android plugin.

Yes, check tasks support it. On the first run, the task will check all files in the source set, on subsequent runs it will check only added/modified files.

Format tasks do not check files incrementally.

Gradle based filtering are only working for files located inside project (subproject) folder, see https://github.com/gradle/gradle/issues/3417 To filter files outside project dir, use:

exclude { element -> element.file.path.contains("generated/") }

Ensure you are not pinning Kotlin version for "ktlint*" configurations added by plugin.

KtLint relies on Kotlin compiler to parse source files. Each version of KtLint are build using specific Kotlin version.

To exclude "ktlint*" Gradle configurations from Kotlin version pinning - use following approach:

configurations.all {
    if (!name.startsWith("ktlint")) {
        resolutionStrategy {
            eachDependency {
                // Force Kotlin to our version
                if (requested.group == "org.jetbrains.kotlin") {
                    useVersion("1.3.72")
                }
            }
        }
    }
}

Developers

Importing

Import the settings.gradle.kts file into your IDE.

To enable the Android sample either define the ANDROID_HOME environmental variable or add a local.properties file to the project root folder with the following content:

sdk.dir=<android-sdk-location>

Building

Building the plugin: ./plugin/gradlew build

On how to run the current plugin snapshot check on sample projects: ./gradlew ktlintCheck

Running tests from IDEA IDE

To run tests in IDEA IDE, firstly you need to run following gradle task (or after any dependency change):

$ ./plugin/gradlew -p ./plugin pluginUnderTestMetadata

Optionally you can add this step test run configuration.

Links

Ktlint Gradle Plugin on the Gradle Plugin Registry