From 657decce4ac386bdad9d5cfa78ac24ffa6eaea27 Mon Sep 17 00:00:00 2001 From: Will Molloy Date: Sun, 5 Jan 2025 01:01:21 +1300 Subject: [PATCH 1/3] Add `ktfmt` Have been finding inconsistent results with `ktlint`. I.e. it preserves custom formatting, which you do not want. It should have deterministic output. `ktfmt` was made to solve that: https://github.com/facebook/ktfmt?tab=readme-ov-file#faq I think they should work together? Need to use for a bit to make sure. Still want `ktlint` as it handles some bits better like space between methods. --- README.md | 8 ++-- build.gradle.kts | 40 +++++++------------ example-java/build.gradle.kts | 8 +--- .../kotlin/com/willmolloy/HelloWorldTest.kt | 4 +- settings.gradle.kts | 2 + 5 files changed, 25 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 12998a9..743d321 100644 --- a/README.md +++ b/README.md @@ -3,14 +3,16 @@ [![build](https://github.com/will-molloy/java-template/actions/workflows/build.yml/badge.svg?branch=main&event=push)](https://github.com/will-molloy/java-template/actions/workflows/build.yml) [![codecov](https://codecov.io/gh/will-molloy/java-template/branch/main/graph/badge.svg)](https://codecov.io/gh/will-molloy/java-template) -template repo for Java/Kotlin projects using Gradle +template repo for Java/Kotlin Gradle projects ## Features - JDK 21 ([Amazon Corretto](https://aws.amazon.com/corretto/)) -- [Gradle 8](https://github.com/gradle/gradle) with Kotlin DSL +- [Gradle 8](https://github.com/gradle/gradle) (Kotlin DSL) - [GitHub Actions](https://github.com/features/actions) CI/CD -- Automatic code formatting via [Spotless](https://github.com/diffplug/spotless) ([`google-java-format`](https://github.com/google/google-java-format) and [`ktlint`](https://github.com/pinterest/ktlint)) +- Automatic code formatting via [Spotless](https://github.com/diffplug/spotless) + - Java: [`google-java-format`](https://github.com/google/google-java-format) + - Kotlin: [`ktlint`](https://github.com/pinterest/ktlint) and [`ktfmt`](https://github.com/facebook/ktfmt) - Code style analysis via [Checkstyle](https://github.com/checkstyle/checkstyle) - Static analysis via [SpotBugs](https://spotbugs.github.io/) - Unit and integration test support via [JUnit 5](https://junit.org/junit5/) and [TestSets plugin](https://github.com/unbroken-dome/gradle-testsets-plugin) diff --git a/build.gradle.kts b/build.gradle.kts index 9117c35..269e429 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,6 +8,7 @@ import org.gradle.api.tasks.testing.logging.TestLogEvent import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension logger.quiet("Java version: ${JavaVersion.current()}") + logger.quiet("Gradle version: ${gradle.gradleVersion}") plugins { @@ -20,9 +21,7 @@ plugins { allprojects { group = "com.willmolloy" - repositories { - mavenCentral() - } + repositories { mavenCentral() } apply(plugin = "java") configure { @@ -31,31 +30,33 @@ allprojects { } apply(plugin = "kotlin") - configure { - jvmToolchain(21) - } + configure { jvmToolchain(21) } apply(plugin = "com.diffplug.spotless") configure { + // https://github.com/diffplug/spotless/tree/main/plugin-gradle#java java { removeUnusedImports() googleJavaFormat() trimTrailingWhitespace() endWithNewline() } + // https://github.com/diffplug/spotless/tree/main/plugin-gradle#kotlin kotlin { ktlint() + ktfmt().googleStyle() trimTrailingWhitespace() endWithNewline() } kotlinGradle { ktlint().editorConfigOverride(mapOf("ktlint_standard_no-empty-file" to "disabled")) + ktfmt().googleStyle() trimTrailingWhitespace() endWithNewline() } } - // TODO this doesn't work on Kotlin, look into Detekt? + // TODO Kotlin alternative? apply(plugin = "checkstyle") configure { toolVersion = "10.12.0" @@ -73,9 +74,7 @@ allprojects { ignoreFailures.set(false) excludeFilter.set(rootProject.file("./spotbugs-exclude.xml")) } - tasks.withType { - reports.create("html").required.set(true) - } + tasks.withType { reports.create("html").required.set(true) } tasks.withType { maxParallelForks = Runtime.getRuntime().availableProcessors() @@ -104,22 +103,12 @@ allprojects { } apply(plugin = "jacoco") - tasks.withType { - reports { - xml.required.set(true) - } - } + tasks.withType { reports { xml.required.set(true) } } val previewFeatures = emptyList() - tasks.withType { - options.compilerArgs = previewFeatures - } - tasks.withType { - jvmArgs = previewFeatures - } - tasks.withType { - jvmArgs = previewFeatures - } + tasks.withType { options.compilerArgs = previewFeatures } + tasks.withType { jvmArgs = previewFeatures } + tasks.withType { jvmArgs = previewFeatures } dependencies { implementation(rootProject.libs.log4j.core) @@ -137,7 +126,8 @@ allprojects { exclude(group = "org.assertj") exclude(group = "junit") resolutionStrategy { - force("com.google.guava:guava:${rootProject.libs.versions.guava.get()}") // exclude android version + // exclude android version + force("com.google.guava:guava:${rootProject.libs.versions.guava.get()}") } } } diff --git a/example-java/build.gradle.kts b/example-java/build.gradle.kts index 3ff8c1f..dae66ed 100644 --- a/example-java/build.gradle.kts +++ b/example-java/build.gradle.kts @@ -1,7 +1,3 @@ -plugins { - alias(libs.plugins.testsets) -} +plugins { alias(libs.plugins.testsets) } -testSets { - create("integrationTest") -} +testSets { create("integrationTest") } diff --git a/example-kotlin/src/test/kotlin/com/willmolloy/HelloWorldTest.kt b/example-kotlin/src/test/kotlin/com/willmolloy/HelloWorldTest.kt index 01488d0..460b55c 100644 --- a/example-kotlin/src/test/kotlin/com/willmolloy/HelloWorldTest.kt +++ b/example-kotlin/src/test/kotlin/com/willmolloy/HelloWorldTest.kt @@ -3,9 +3,7 @@ package com.willmolloy import com.google.common.truth.Truth.assertThat import org.junit.jupiter.api.Test -/** - * Unit tests for [HelloWorld]. - */ +/** Unit tests for [HelloWorld]. */ class HelloWorldTest { @Test fun `test hello`() { diff --git a/settings.gradle.kts b/settings.gradle.kts index 09ecaa5..2d7bdfe 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,3 +1,5 @@ rootProject.name = "java-template" + include("example-java") + include("example-kotlin") From 078f74ce4620ef771d18efef221765e55fc442e2 Mon Sep 17 00:00:00 2001 From: Will Molloy Date: Mon, 6 Jan 2025 22:55:30 +1300 Subject: [PATCH 2/3] Swap to `ktfmt` for kotlin code, but keep `ktlint` for gradle scripts --- README.md | 3 +- build.gradle.kts | 36 +++++++++++++------ .../main/kotlin/com/willmolloy/HelloWorld.kt | 1 + .../kotlin/com/willmolloy/HelloWorldTest.kt | 1 + settings.gradle.kts | 2 -- 5 files changed, 30 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 743d321..7a6cd56 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,8 @@ template repo for Java/Kotlin Gradle projects - [GitHub Actions](https://github.com/features/actions) CI/CD - Automatic code formatting via [Spotless](https://github.com/diffplug/spotless) - Java: [`google-java-format`](https://github.com/google/google-java-format) - - Kotlin: [`ktlint`](https://github.com/pinterest/ktlint) and [`ktfmt`](https://github.com/facebook/ktfmt) + - Kotlin: [`ktfmt`](https://github.com/facebook/ktfmt) + - Kotlin Gradle: [`ktlint`](https://github.com/pinterest/ktlint) - Code style analysis via [Checkstyle](https://github.com/checkstyle/checkstyle) - Static analysis via [SpotBugs](https://spotbugs.github.io/) - Unit and integration test support via [JUnit 5](https://junit.org/junit5/) and [TestSets plugin](https://github.com/unbroken-dome/gradle-testsets-plugin) diff --git a/build.gradle.kts b/build.gradle.kts index 269e429..bc87168 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,6 @@ import org.gradle.api.tasks.testing.logging.TestLogEvent import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension logger.quiet("Java version: ${JavaVersion.current()}") - logger.quiet("Gradle version: ${gradle.gradleVersion}") plugins { @@ -21,7 +20,9 @@ plugins { allprojects { group = "com.willmolloy" - repositories { mavenCentral() } + repositories { + mavenCentral() + } apply(plugin = "java") configure { @@ -30,7 +31,9 @@ allprojects { } apply(plugin = "kotlin") - configure { jvmToolchain(21) } + configure { + jvmToolchain(21) + } apply(plugin = "com.diffplug.spotless") configure { @@ -42,15 +45,16 @@ allprojects { endWithNewline() } // https://github.com/diffplug/spotless/tree/main/plugin-gradle#kotlin + // ktfmt seems better than ktlint (more deterministic/consistent output). + // Furthermore, using spotless more for formatting than linting. + // However, ktfmt has some weird output with Gradle scripts, so using ktlint for that. kotlin { - ktlint() ktfmt().googleStyle() trimTrailingWhitespace() endWithNewline() } kotlinGradle { ktlint().editorConfigOverride(mapOf("ktlint_standard_no-empty-file" to "disabled")) - ktfmt().googleStyle() trimTrailingWhitespace() endWithNewline() } @@ -74,7 +78,9 @@ allprojects { ignoreFailures.set(false) excludeFilter.set(rootProject.file("./spotbugs-exclude.xml")) } - tasks.withType { reports.create("html").required.set(true) } + tasks.withType { + reports.create("html").required.set(true) + } tasks.withType { maxParallelForks = Runtime.getRuntime().availableProcessors() @@ -103,12 +109,22 @@ allprojects { } apply(plugin = "jacoco") - tasks.withType { reports { xml.required.set(true) } } + tasks.withType { + reports { + xml.required.set(true) + } + } val previewFeatures = emptyList() - tasks.withType { options.compilerArgs = previewFeatures } - tasks.withType { jvmArgs = previewFeatures } - tasks.withType { jvmArgs = previewFeatures } + tasks.withType { + options.compilerArgs = previewFeatures + } + tasks.withType { + jvmArgs = previewFeatures + } + tasks.withType { + jvmArgs = previewFeatures + } dependencies { implementation(rootProject.libs.log4j.core) diff --git a/example-kotlin/src/main/kotlin/com/willmolloy/HelloWorld.kt b/example-kotlin/src/main/kotlin/com/willmolloy/HelloWorld.kt index a941572..5a74d96 100644 --- a/example-kotlin/src/main/kotlin/com/willmolloy/HelloWorld.kt +++ b/example-kotlin/src/main/kotlin/com/willmolloy/HelloWorld.kt @@ -6,6 +6,7 @@ package com.willmolloy * @author Will Molloy */ class HelloWorld { + fun hello(text: String): String { return "Hello $text!" } diff --git a/example-kotlin/src/test/kotlin/com/willmolloy/HelloWorldTest.kt b/example-kotlin/src/test/kotlin/com/willmolloy/HelloWorldTest.kt index 460b55c..a510605 100644 --- a/example-kotlin/src/test/kotlin/com/willmolloy/HelloWorldTest.kt +++ b/example-kotlin/src/test/kotlin/com/willmolloy/HelloWorldTest.kt @@ -5,6 +5,7 @@ import org.junit.jupiter.api.Test /** Unit tests for [HelloWorld]. */ class HelloWorldTest { + @Test fun `test hello`() { assertThat(HelloWorld().hello("world")).isEqualTo("Hello world!") diff --git a/settings.gradle.kts b/settings.gradle.kts index 2d7bdfe..09ecaa5 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,5 +1,3 @@ rootProject.name = "java-template" - include("example-java") - include("example-kotlin") From 18f20780e256382598fd7507e779c082c323feb2 Mon Sep 17 00:00:00 2001 From: Will Molloy Date: Mon, 13 Jan 2025 21:32:14 +1300 Subject: [PATCH 3/3] Remove comment --- build.gradle.kts | 3 --- 1 file changed, 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index bc87168..22c515f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -45,9 +45,6 @@ allprojects { endWithNewline() } // https://github.com/diffplug/spotless/tree/main/plugin-gradle#kotlin - // ktfmt seems better than ktlint (more deterministic/consistent output). - // Furthermore, using spotless more for formatting than linting. - // However, ktfmt has some weird output with Gradle scripts, so using ktlint for that. kotlin { ktfmt().googleStyle() trimTrailingWhitespace()