|
| 1 | +# Kotlinter Gradle 4.x and Earlier |
| 2 | + |
| 3 | +For current version see [README.md](README.md). |
| 4 | + |
| 5 | +Painless Gradle plugin for linting and formatting Kotlin source files using the awesome [ktlint](https://ktlint.github.io) engine. |
| 6 | + |
| 7 | +It aims to be easy to set up with _zero_ required configuration and behaves as you'd expect out of the box. |
| 8 | + |
| 9 | +It's also fast because it integrates the ktlint _engine_ directly with Gradle's incremental build and uses the Worker API to parallelize work. |
| 10 | + |
| 11 | +### Installation |
| 12 | + |
| 13 | +Available on the Gradle Plugins Portal: https://plugins.gradle.org/plugin/org.jmailen.kotlinter |
| 14 | + |
| 15 | +#### Single module |
| 16 | + |
| 17 | +<details open> |
| 18 | +<summary>Kotlin</summary> |
| 19 | + |
| 20 | +```kotlin |
| 21 | +plugins { |
| 22 | + id("org.jmailen.kotlinter") version "4.5.0" |
| 23 | +} |
| 24 | +``` |
| 25 | + |
| 26 | +</details> |
| 27 | + |
| 28 | +<details> |
| 29 | +<summary>Groovy</summary> |
| 30 | + |
| 31 | +```groovy |
| 32 | +plugins { |
| 33 | + id "org.jmailen.kotlinter" version "4.5.0" |
| 34 | +} |
| 35 | +``` |
| 36 | + |
| 37 | +</details> |
| 38 | + |
| 39 | +#### Multi-module and Android |
| 40 | + |
| 41 | +<details open> |
| 42 | +<summary>Kotlin</summary> |
| 43 | +Root `build.gradle.kts` |
| 44 | + |
| 45 | +```kotlin |
| 46 | +plugins { |
| 47 | + id("org.jmailen.kotlinter") version "4.5.0" apply false |
| 48 | +} |
| 49 | +``` |
| 50 | + |
| 51 | +Each module `build.gradle.kts` with Kotlin source |
| 52 | + |
| 53 | +```kotlin |
| 54 | +plugins { |
| 55 | + id("org.jmailen.kotlinter") |
| 56 | +} |
| 57 | +``` |
| 58 | + |
| 59 | +</details> |
| 60 | + |
| 61 | +<details> |
| 62 | +<summary>Groovy</summary> |
| 63 | +Root `build.gradle` |
| 64 | + |
| 65 | +```groovy |
| 66 | +plugins { |
| 67 | + id 'org.jmailen.kotlinter' version "4.5.0" apply false |
| 68 | +} |
| 69 | +``` |
| 70 | + |
| 71 | +Each module `build.gradle` with Kotlin source |
| 72 | + |
| 73 | +```groovy |
| 74 | +plugins { |
| 75 | + id 'org.jmailen.kotlinter' |
| 76 | +} |
| 77 | +``` |
| 78 | + |
| 79 | +</details> |
| 80 | + |
| 81 | +### Compatibility |
| 82 | + |
| 83 | +| kotlinter version | min kotlin version | max kotlin version | min gradle version | |
| 84 | +|-------------------|--------------------|--------------------|--------------------| |
| 85 | +| 4.5.0+ | 2.0.0 | 2.0.21 | 8.4 | |
| 86 | +| 4.2.0+ | 1.9.20 | 1.9.25 | 8.4 | |
| 87 | +| 4.0.0+ | 1.9.0 | 1.9.25 | 7.6 | |
| 88 | +| 3.14.0+ | 1.8.0 | 1.8.22 | 7.6 | |
| 89 | +| 3.11.0+ | 1.7.0 | 1.7.22 | 7.0 | |
| 90 | +| 3.10.0+ | 1.6.20 | 1.6.21 | 7.0 | |
| 91 | +| 3.7.0+ | 1.5.31 | 1.6.10 | 7.0 | |
| 92 | +| 3.5.0+ | 1.5.0 | 1.5.30 | 6.8 | |
| 93 | +| 3.0.0+ | 1.4.0 | 1.4.30 | 6.8 | |
| 94 | +| 2.0.0+ | 1.3.0 | 1.3.30 | - | |
| 95 | + |
| 96 | +### Features |
| 97 | + |
| 98 | +- Supports Kotlin Gradle plugins: |
| 99 | + - [JVM](https://plugins.gradle.org/plugin/org.jetbrains.kotlin.jvm) |
| 100 | + - [Multiplatform](https://plugins.gradle.org/plugin/org.jetbrains.kotlin.multiplatform) |
| 101 | + - [Android](https://plugins.gradle.org/plugin/org.jetbrains.kotlin.android) |
| 102 | +- Supports `.kt` and `.kts` files |
| 103 | +- Standalone `LintTask` and `FormatTask` types for defining custom tasks |
| 104 | +- Incremental build support and fast parallelization with Gradle Worker API |
| 105 | +- Configures from `.editorconfig` when available |
| 106 | +- Configurable reporters |
| 107 | + |
| 108 | +### Tasks |
| 109 | + |
| 110 | +When your project uses one of the supported Kotlin Gradle plugins, Kotlinter adds these tasks: |
| 111 | + |
| 112 | +`formatKotlin`: format Kotlin source code according to `ktlint` rules or warn when auto-format not possible. |
| 113 | + |
| 114 | +`lintKotlin`: report Kotlin lint errors and by default fail the build. |
| 115 | + |
| 116 | +Also `check` becomes dependent on `lintKotlin`. |
| 117 | + |
| 118 | +Granular tasks are added for each source set in the project: `formatKotlin`*`SourceSet`* and `lintKotlin`*`SourceSet`*. |
| 119 | + |
| 120 | +### Git Hooks |
| 121 | + |
| 122 | +Kotlinter can install a hook to run pre-push (`installKotlinterPrePushHook`). The hook runs `lintKotlin` and, if there are errors, `formatKotlin` and exits non-zero leaving changed files to be committed. |
| 123 | + |
| 124 | +You *must* apply the kotlinter plugin to your root project to make this task available. If using `git worktree` you must install the hook from the parent git directory. |
| 125 | + |
| 126 | +To install the hook automatically when someone runs the build, add this to your root project `build.gradle.kts`: |
| 127 | + |
| 128 | +<details open> |
| 129 | +<summary>Kotlin</summary> |
| 130 | + |
| 131 | +```kotlin |
| 132 | +tasks.check { |
| 133 | + dependsOn("installKotlinterPrePushHook") |
| 134 | +} |
| 135 | +``` |
| 136 | + |
| 137 | +</details> |
| 138 | + |
| 139 | +<details> |
| 140 | +<summary>Groovy</summary> |
| 141 | + |
| 142 | +```groovy |
| 143 | +tasks.named('check') { |
| 144 | + dependsOn 'installKotlinterPrePushHook' |
| 145 | +} |
| 146 | +``` |
| 147 | + |
| 148 | +</details> |
| 149 | + |
| 150 | + |
| 151 | +### Configuration |
| 152 | +Options are configured in the `kotlinter` extension. Defaults shown (you may omit the configuration block entirely if you want these defaults). |
| 153 | + |
| 154 | +<details open> |
| 155 | +<summary>Kotlin</summary> |
| 156 | + |
| 157 | +```kotlin |
| 158 | +kotlinter { |
| 159 | + failBuildWhenCannotAutoFormat = false |
| 160 | + ignoreFailures = false |
| 161 | + reporters = arrayOf("checkstyle", "plain") |
| 162 | +} |
| 163 | +``` |
| 164 | + |
| 165 | +</details> |
| 166 | + |
| 167 | +<details> |
| 168 | +<summary>Groovy</summary> |
| 169 | + |
| 170 | +```groovy |
| 171 | +kotlinter { |
| 172 | + failBuildWhenCannotAutoFormat = false |
| 173 | + ignoreFailures = false |
| 174 | + reporters = ['checkstyle', 'plain'] |
| 175 | +} |
| 176 | +``` |
| 177 | + |
| 178 | +</details> |
| 179 | + |
| 180 | +Setting `failBuildWhenCannotAutoFormat` to `true` will configure the `formatKotlin` task to fail the build when auto-format is not able to fix a lint error. This is overrided by setting `ignoreFailures` to `true`. |
| 181 | + |
| 182 | +Options for `reporters`: `checkstyle`, `html`, `json`, `plain`, `sarif` |
| 183 | + |
| 184 | +Reporters behave as described at: https://github.com/pinterest/ktlint |
| 185 | + |
| 186 | +### Editorconfig |
| 187 | + |
| 188 | +Kotlinter will configure itself using an `.editorconfig` file if one is present. |
| 189 | + |
| 190 | +This configuration includes code style and linting rules. |
| 191 | + |
| 192 | +See [KtLint configuration](https://pinterest.github.io/ktlint/latest/rules/configuration-ktlint/) for details. |
| 193 | + |
| 194 | +### Customizing Tasks |
| 195 | + |
| 196 | +The `formatKotlin`*`SourceSet`* and `lintKotlin`*`SourceSet`* tasks inherit from [SourceTask](https://docs.gradle.org/current/dsl/org.gradle.api.tasks.SourceTask.html) |
| 197 | +so you can customize includes, excludes, and source. |
| 198 | + |
| 199 | +<details open> |
| 200 | +<summary>Kotlin</summary> |
| 201 | + |
| 202 | +```kotlin |
| 203 | +tasks.withType<LintTask> { |
| 204 | + this.source = this.source.minus(fileTree("src/generated")).asFileTree |
| 205 | +} |
| 206 | + |
| 207 | +tasks.withType<FormatTask> { |
| 208 | + this.source = this.source.minus(fileTree("src/generated")).asFileTree |
| 209 | +} |
| 210 | +``` |
| 211 | + |
| 212 | +</details> |
| 213 | + |
| 214 | +<details> |
| 215 | +<summary>Groovy</summary> |
| 216 | + |
| 217 | +```groovy |
| 218 | +tasks.named("lintKotlinMain") { |
| 219 | + source = source - fileTree("$buildDir/generated") |
| 220 | +} |
| 221 | +``` |
| 222 | + |
| 223 | +</details> |
| 224 | + |
| 225 | +Note that exclude paths are relative to the package root. |
| 226 | + |
| 227 | +### Custom Tasks |
| 228 | + |
| 229 | +If you aren't using autoconfiguration from a supported plugin or otherwise need to handle additional source code, you can create custom tasks: |
| 230 | + |
| 231 | +<details open> |
| 232 | +<summary>Kotlin</summary> |
| 233 | + |
| 234 | +```kotlin |
| 235 | +import org.jmailen.gradle.kotlinter.tasks.LintTask |
| 236 | +import org.jmailen.gradle.kotlinter.tasks.FormatTask |
| 237 | + |
| 238 | +tasks.register<LintTask>("ktLint") { |
| 239 | + group = "verification" |
| 240 | + source(files("src")) |
| 241 | + reports.set( |
| 242 | + mapOf( |
| 243 | + "plain" to file("build/lint-report.txt"), |
| 244 | + "json" to file("build/lint-report.json") |
| 245 | + ) |
| 246 | + ) |
| 247 | +} |
| 248 | + |
| 249 | +tasks.register<FormatTask>("ktFormat") { |
| 250 | + group = "formatting" |
| 251 | + source(files("src")) |
| 252 | + report.set(file("build/format-report.txt")) |
| 253 | +} |
| 254 | +``` |
| 255 | + |
| 256 | +</details> |
| 257 | + |
| 258 | +<details> |
| 259 | +<summary>Groovy</summary> |
| 260 | + |
| 261 | +```groovy |
| 262 | +import org.jmailen.gradle.kotlinter.tasks.LintTask |
| 263 | +import org.jmailen.gradle.kotlinter.tasks.FormatTask |
| 264 | +
|
| 265 | +tasks.register('ktLint', LintTask) { |
| 266 | + group 'verification' |
| 267 | + source files('src') |
| 268 | + reports = [ |
| 269 | + 'plain': file('build/lint-report.txt'), |
| 270 | + 'json' : file('build/lint-report.json') |
| 271 | + ] |
| 272 | +} |
| 273 | +
|
| 274 | +
|
| 275 | +tasks.register('ktFormat', FormatTask) { |
| 276 | + group 'formatting' |
| 277 | + source files('src/test') |
| 278 | + report = file('build/format-report.txt') |
| 279 | +} |
| 280 | +``` |
| 281 | + |
| 282 | +</details> |
| 283 | + |
| 284 | +### Custom ktlint version |
| 285 | + |
| 286 | +If you need to use a different version of `ktlint` you can override the dependency. |
| 287 | + |
| 288 | +<details open> |
| 289 | +<summary>Kotlin or Groovy</summary> |
| 290 | + |
| 291 | +```kotlin |
| 292 | +buildscript { |
| 293 | + configurations.classpath { |
| 294 | + resolutionStrategy { |
| 295 | + force( |
| 296 | + "com.pinterest.ktlint:ktlint-rule-engine:1.2.1", |
| 297 | + "com.pinterest.ktlint:ktlint-rule-engine-core:1.2.1", |
| 298 | + "com.pinterest.ktlint:ktlint-cli-reporter-core:1.2.1", |
| 299 | + "com.pinterest.ktlint:ktlint-cli-reporter-checkstyle:1.2.1", |
| 300 | + "com.pinterest.ktlint:ktlint-cli-reporter-json:1.2.1", |
| 301 | + "com.pinterest.ktlint:ktlint-cli-reporter-html:1.2.1", |
| 302 | + "com.pinterest.ktlint:ktlint-cli-reporter-plain:1.2.1", |
| 303 | + "com.pinterest.ktlint:ktlint-cli-reporter-sarif:1.2.1", |
| 304 | + "com.pinterest.ktlint:ktlint-ruleset-standard:1.2.1" |
| 305 | + ) |
| 306 | + } |
| 307 | + } |
| 308 | +} |
| 309 | + |
| 310 | +``` |
| 311 | + |
| 312 | +</details> |
| 313 | + |
| 314 | +Alternatively, if you have a custom build convention plugin that utilizes kotlinter, you can enforce a newer KtLint version through a `platform` directive: |
| 315 | + |
| 316 | +<details open> |
| 317 | +<summary>Kotlin or Groovy</summary> |
| 318 | + |
| 319 | +```kotlin |
| 320 | +dependencies { |
| 321 | + implementation(platform("com.pinterest.ktlint:ktlint-bom:1.4.0")) |
| 322 | + implementation("org.jmailen.gradle:kotlinter-gradle:4.5.0") |
| 323 | +} |
| 324 | + |
| 325 | +``` |
| 326 | + |
| 327 | +### Custom Rules |
| 328 | + |
| 329 | +You can add custom ktlint RuleSets using the `buildscript` classpath: |
| 330 | + |
| 331 | +<details open> |
| 332 | +<summary>Kotlin</summary> |
| 333 | + |
| 334 | +```kotlin |
| 335 | +buildscript { |
| 336 | + dependencies { |
| 337 | + classpath(files("libs/my-custom-ktlint-rules.jar")) |
| 338 | + classpath("org.other.ktlint:custom-rules:1.0") |
| 339 | + } |
| 340 | +} |
| 341 | +``` |
| 342 | + |
| 343 | +</details> |
| 344 | + |
| 345 | +<details> |
| 346 | +<summary>Groovy</summary> |
| 347 | + |
| 348 | +```groovy |
| 349 | +buildscript { |
| 350 | + dependencies { |
| 351 | + classpath files('libs/my-custom-ktlint-rules.jar') |
| 352 | + classpath 'org.other.ktlint:custom-rules:1.0' |
| 353 | + } |
| 354 | +} |
| 355 | +``` |
| 356 | + |
| 357 | +</details> |
0 commit comments