From 48d7e8ce2bfca100743f96319d11b7e6b5e6fd74 Mon Sep 17 00:00:00 2001 From: Julian Roggendorf Date: Mon, 25 Nov 2024 16:31:04 +0100 Subject: [PATCH 1/9] Create tasks to check and format top-level script files of a project (#337) --- .../com/ncorti/ktfmt/gradle/KtfmtPlugin.kt | 4 ++ .../ncorti/ktfmt/gradle/KtfmtPluginUtils.kt | 43 +++++++++++++++++++ .../ncorti/ktfmt/gradle/KtfmtPluginTest.kt | 25 ++++++++--- 3 files changed, 66 insertions(+), 6 deletions(-) diff --git a/plugin-build/plugin/src/main/java/com/ncorti/ktfmt/gradle/KtfmtPlugin.kt b/plugin-build/plugin/src/main/java/com/ncorti/ktfmt/gradle/KtfmtPlugin.kt index 9526f9e..9df7a03 100644 --- a/plugin-build/plugin/src/main/java/com/ncorti/ktfmt/gradle/KtfmtPlugin.kt +++ b/plugin-build/plugin/src/main/java/com/ncorti/ktfmt/gradle/KtfmtPlugin.kt @@ -4,6 +4,7 @@ import com.ncorti.ktfmt.gradle.KtfmtAndroidUtils.applyKtfmtToAndroidProject import com.ncorti.ktfmt.gradle.KtfmtPluginUtils.EXTENSION_NAME import com.ncorti.ktfmt.gradle.KtfmtPluginUtils.TASK_NAME_CHECK import com.ncorti.ktfmt.gradle.KtfmtPluginUtils.TASK_NAME_FORMAT +import com.ncorti.ktfmt.gradle.KtfmtPluginUtils.createScriptTasks import com.ncorti.ktfmt.gradle.KtfmtPluginUtils.createTasksForSourceSet import com.ncorti.ktfmt.gradle.tasks.KtfmtBaseTask import com.ncorti.ktfmt.gradle.util.i @@ -62,6 +63,7 @@ abstract class KtfmtPlugin : Plugin { if (project.plugins.hasPlugin("org.jetbrains.kotlin.multiplatform")) { project.logger.i("Skipping Android task creation, as KMP is applied") } else { + createScriptTasks(project, project.projectDir, topLevelFormat, topLevelCheck) applyKtfmtToAndroidProject(project, topLevelFormat, topLevelCheck, ktfmtExtension) } } @@ -73,6 +75,7 @@ abstract class KtfmtPlugin : Plugin { private fun applyKtfmt(project: Project, ktfmtExtension: KtfmtExtension) { val extension = project.extensions.getByType(KotlinProjectExtension::class.java) + createScriptTasks(project, project.projectDir, topLevelFormat, topLevelCheck) extension.sourceSets.all { createTasksForSourceSet( project, @@ -87,6 +90,7 @@ abstract class KtfmtPlugin : Plugin { private fun applyKtfmtToMultiplatformProject(project: Project, ktfmtExtension: KtfmtExtension) { val extension = project.extensions.getByType(KotlinMultiplatformExtension::class.java) + createScriptTasks(project, project.projectDir, topLevelFormat, topLevelCheck) extension.sourceSets.all { val name = "kmp ${it.name}" if (it.name.startsWith("android")) { diff --git a/plugin-build/plugin/src/main/java/com/ncorti/ktfmt/gradle/KtfmtPluginUtils.kt b/plugin-build/plugin/src/main/java/com/ncorti/ktfmt/gradle/KtfmtPluginUtils.kt index 4c8649c..6a4d20d 100644 --- a/plugin-build/plugin/src/main/java/com/ncorti/ktfmt/gradle/KtfmtPluginUtils.kt +++ b/plugin-build/plugin/src/main/java/com/ncorti/ktfmt/gradle/KtfmtPluginUtils.kt @@ -63,6 +63,49 @@ internal object KtfmtPluginUtils { } } + internal fun createScriptTasks( + project: Project, + projectDir: File, + topLevelFormat: TaskProvider, + topLevelCheck: TaskProvider, + ) { + val checkTaskName = "${TASK_NAME_CHECK}Script" + val formatTaskName = "${TASK_NAME_FORMAT}Script" + + val scriptFiles = + project + .fileTree(projectDir) + .filter { it.extension == "kts" } + .filter { it.parentFile == projectDir } + + val scriptCheckTask = + project.tasks.register(checkTaskName, KtfmtCheckTask::class.java) { + it.description = + "Run Ktfmt formatter validation for script files on project '${project.name}'" + it.setSource(scriptFiles) + it.setIncludes(KtfmtPlugin.defaultIncludes) + } + val scriptFormatTask = + project.tasks.register(formatTaskName, KtfmtFormatTask::class.java) { + it.description = "Run Ktfmt formatter for script files on project '${project.name}'" + it.setSource(scriptFiles) + it.setIncludes(KtfmtPlugin.defaultIncludes) + } + + project.tasks.withType(KotlinCompile::class.java).all { + it.mustRunAfter(scriptCheckTask, scriptFormatTask) + } + + topLevelFormat.configure { task -> task.dependsOn(scriptFormatTask) } + topLevelCheck.configure { task -> task.dependsOn(scriptCheckTask) } + + project.plugins.withType(LifecycleBasePlugin::class.java) { + project.tasks.named(LifecycleBasePlugin.CHECK_TASK_NAME).configure { task -> + task.dependsOn(scriptCheckTask) + } + } + } + private fun createCheckTask( project: Project, name: String, diff --git a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/KtfmtPluginTest.kt b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/KtfmtPluginTest.kt index bfe227e..4920656 100644 --- a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/KtfmtPluginTest.kt +++ b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/KtfmtPluginTest.kt @@ -32,10 +32,13 @@ class KtfmtPluginTest { assertThat(project["ktfmtCheckTest"]).isInstanceOf(KtfmtCheckTask::class.java) assertThat(project["ktfmtFormatTest"]).isInstanceOf(KtfmtFormatTask::class.java) + assertThat(project["ktfmtCheckScript"]).isInstanceOf(KtfmtCheckTask::class.java) + assertThat(project["ktfmtFormatScript"]).isInstanceOf(KtfmtFormatTask::class.java) + assertThat(project["ktfmtCheck"].dependencies) - .containsExactly("ktfmtCheckMain", "ktfmtCheckTest") + .containsExactly("ktfmtCheckMain", "ktfmtCheckTest", "ktfmtCheckScript") assertThat(project["ktfmtFormat"].dependencies) - .containsExactly("ktfmtFormatMain", "ktfmtFormatTest") + .containsExactly("ktfmtFormatMain", "ktfmtFormatTest", "ktfmtFormatScript") } @Test @@ -50,9 +53,9 @@ class KtfmtPluginTest { assertThat(project["ktfmtFormatTest"]).isInstanceOf(KtfmtFormatTask::class.java) assertThat(project["ktfmtCheck"].dependencies) - .containsExactly("ktfmtCheckMain", "ktfmtCheckTest") + .containsExactly("ktfmtCheckMain", "ktfmtCheckTest", "ktfmtCheckScript") assertThat(project["ktfmtFormat"].dependencies) - .containsExactly("ktfmtFormatMain", "ktfmtFormatTest") + .containsExactly("ktfmtFormatMain", "ktfmtFormatTest", "ktfmtFormatScript") } @Test @@ -71,9 +74,17 @@ class KtfmtPluginTest { .isInstanceOf(KtfmtFormatTask::class.java) assertThat(project["ktfmtCheck"].dependencies) - .containsExactly("ktfmtCheckKmpCommonMain", "ktfmtCheckKmpCommonTest") + .containsExactly( + "ktfmtCheckKmpCommonMain", + "ktfmtCheckKmpCommonTest", + "ktfmtCheckScript", + ) assertThat(project["ktfmtFormat"].dependencies) - .containsExactly("ktfmtFormatKmpCommonMain", "ktfmtFormatKmpCommonTest") + .containsExactly( + "ktfmtFormatKmpCommonMain", + "ktfmtFormatKmpCommonTest", + "ktfmtFormatScript", + ) } @Suppress("LongMethod") @@ -158,6 +169,7 @@ class KtfmtPluginTest { "ktfmtCheckTestFixtures", "ktfmtCheckTestFixturesRelease", "ktfmtCheckTestFixturesDebug", + "ktfmtCheckScript", ) assertThat(project["ktfmtFormat"].dependencies) .containsExactly( @@ -173,6 +185,7 @@ class KtfmtPluginTest { "ktfmtFormatTestFixtures", "ktfmtFormatTestFixturesRelease", "ktfmtFormatTestFixturesDebug", + "ktfmtFormatScript", ) } From 625e0e62dc80d78a5d9ab15148265d26a9a5abf4 Mon Sep 17 00:00:00 2001 From: Julian Roggendorf Date: Mon, 25 Nov 2024 17:32:37 +0100 Subject: [PATCH 2/9] Use utility function --- .../tasks/KtfmtCheckTaskIntegrationTest.kt | 19 ++++++++----------- .../tasks/KtfmtFormatTaskIntegrationTest.kt | 19 ++++++++----------- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtCheckTaskIntegrationTest.kt b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtCheckTaskIntegrationTest.kt index 186e758..089ad58 100644 --- a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtCheckTaskIntegrationTest.kt +++ b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtCheckTaskIntegrationTest.kt @@ -273,17 +273,14 @@ internal class KtfmtCheckTaskIntegrationTest { fun `custom formatCheck task should be compatible with configuration cache`() { createTempFile(content = "val answer = 42\n") - tempDir - .resolve("build.gradle.kts") - .appendText( - """ - | - |tasks.register("customFormatCheck") { - | source = fileTree("src/main/java") - |} - """ - .trimMargin() - ) + appendToBuildGradle( + """ + |tasks.register("customFormatCheck") { + | source = fileTree("src/main/java") + |} + """ + .trimMargin() + ) GradleRunner.create() .withProjectDir(tempDir) diff --git a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtFormatTaskIntegrationTest.kt b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtFormatTaskIntegrationTest.kt index 76d8b83..cf4af71 100644 --- a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtFormatTaskIntegrationTest.kt +++ b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtFormatTaskIntegrationTest.kt @@ -265,17 +265,14 @@ internal class KtfmtFormatTaskIntegrationTest { fun `custom format task should be compatible with configuration cache`() { createTempFile(content = "val answer = 42\n") - tempDir - .resolve("build.gradle.kts") - .appendText( - """ - | - |tasks.register("customFormatTask") { - | source = fileTree("src/main/java") - |} - """ - .trimMargin() - ) + appendToBuildGradle( + """ + |tasks.register("customFormatTask") { + | source = fileTree("src/main/java") + |} + """ + .trimMargin() + ) GradleRunner.create() .withProjectDir(tempDir) From 313168a4185e88a600dc6c032e01f6d6e6ecd295 Mon Sep 17 00:00:00 2001 From: Julian Roggendorf Date: Mon, 25 Nov 2024 17:33:42 +0100 Subject: [PATCH 3/9] Adjust existing tests to comply with script formatting task --- .../tasks/KtfmtCheckTaskIntegrationTest.kt | 32 ++++++------------- .../tasks/KtfmtFormatTaskIntegrationTest.kt | 29 ++++------------- .../resources/jvmProject/build.gradle.kts | 6 ++-- 3 files changed, 19 insertions(+), 48 deletions(-) diff --git a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtCheckTaskIntegrationTest.kt b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtCheckTaskIntegrationTest.kt index 089ad58..a26fa17 100644 --- a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtCheckTaskIntegrationTest.kt +++ b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtCheckTaskIntegrationTest.kt @@ -276,7 +276,7 @@ internal class KtfmtCheckTaskIntegrationTest { appendToBuildGradle( """ |tasks.register("customFormatCheck") { - | source = fileTree("src/main/java") + | source = fileTree("src/main/java") |} """ .trimMargin() @@ -294,12 +294,8 @@ internal class KtfmtCheckTaskIntegrationTest { appendToBuildGradle( """ |kotlin { - | sourceSets.main { - | kotlin.setSrcDirs(listOf("src")) - | } - | sourceSets.test { - | kotlin.setSrcDirs(listOf("test")) - | } + | sourceSets.main { kotlin.setSrcDirs(listOf("src")) } + | sourceSets.test { kotlin.setSrcDirs(listOf("test")) } |} """ .trimMargin() @@ -323,11 +319,7 @@ internal class KtfmtCheckTaskIntegrationTest { fun `check task should by default ignore sourceSets in the build folder`() { appendToBuildGradle( """ - |kotlin { - | sourceSets.main { - | kotlin.srcDirs("build/main") - | } - |} + |kotlin { sourceSets.main { kotlin.srcDirs("build/main") } } """ .trimMargin() ) @@ -349,15 +341,9 @@ internal class KtfmtCheckTaskIntegrationTest { fun `check task should not ignore sourceSets in build folder when a custom exclusion pattern is specified`() { appendToBuildGradle( """ - |kotlin { - | sourceSets.main { - | kotlin.srcDirs("build/generated") - | } - |} + |kotlin { sourceSets.main { kotlin.srcDirs("build/generated") } } | - |ktfmt{ - | srcSetPathExclusionPattern.set(Regex("customRules.*")) - |} + |ktfmt { srcSetPathExclusionPattern.set(Regex("customRules.*")) } """ .trimMargin() ) @@ -373,15 +359,14 @@ internal class KtfmtCheckTaskIntegrationTest { .buildAndFail() assertThat(result.task(":ktfmtCheckMain")?.outcome).isEqualTo(FAILED) + assertThat(result.output).containsMatch("Invalid formatting for: .*TestFile.kt") } @Test fun `check task should ignore the main sourceSets when specified as exclusion pattern`() { appendToBuildGradle( """ - |ktfmt{ - | srcSetPathExclusionPattern.set(Regex(".*[\\\\/]main[\\\\/].*")) - |} + |ktfmt { srcSetPathExclusionPattern.set(Regex(".*[\\\\/]main[\\\\/].*")) } """ .trimMargin() ) @@ -403,6 +388,7 @@ internal class KtfmtCheckTaskIntegrationTest { tempDir.resolve("build.gradle.kts").apply { appendText(System.lineSeparator()) appendText(content) + appendText(System.lineSeparator()) } } diff --git a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtFormatTaskIntegrationTest.kt b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtFormatTaskIntegrationTest.kt index cf4af71..045a2b2 100644 --- a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtFormatTaskIntegrationTest.kt +++ b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtFormatTaskIntegrationTest.kt @@ -353,12 +353,8 @@ internal class KtfmtFormatTaskIntegrationTest { appendToBuildGradle( """ |kotlin { - | sourceSets.main { - | kotlin.setSrcDirs(listOf("src")) - | } - | sourceSets.test { - | kotlin.setSrcDirs(listOf("test")) - | } + | sourceSets.main { kotlin.setSrcDirs(listOf("src")) } + | sourceSets.test { kotlin.setSrcDirs(listOf("test")) } |} """ .trimMargin() @@ -385,11 +381,7 @@ internal class KtfmtFormatTaskIntegrationTest { fun `format task should by default not format sourceSets in the build folder`() { appendToBuildGradle( """ - |kotlin { - | sourceSets.main { - | kotlin.srcDirs("build/main") - | } - |} + |kotlin { sourceSets.main { kotlin.srcDirs("build/main") } } """ .trimMargin() ) @@ -413,15 +405,9 @@ internal class KtfmtFormatTaskIntegrationTest { fun `format task should not ignore sourceSets in build folder when a custom exclusion pattern is specified`() { appendToBuildGradle( """ - |kotlin { - | sourceSets.main { - | kotlin.srcDirs("build/generated") - | } - |} + |kotlin { sourceSets.main { kotlin.srcDirs("build/generated") } } | - |ktfmt{ - | srcSetPathExclusionPattern.set(Regex("customRules.*")) - |} + |ktfmt { srcSetPathExclusionPattern.set(Regex("customRules.*")) } """ .trimMargin() ) @@ -443,9 +429,7 @@ internal class KtfmtFormatTaskIntegrationTest { fun `format task should ignore the main sourceSets when specified as exclusion pattern`() { appendToBuildGradle( """ - |ktfmt{ - | srcSetPathExclusionPattern.set(Regex(".*[\\\\/]main[\\\\/].*")) - |} + |ktfmt { srcSetPathExclusionPattern.set(Regex(".*[\\\\/]main[\\\\/].*")) } """ .trimMargin() ) @@ -478,6 +462,7 @@ internal class KtfmtFormatTaskIntegrationTest { tempDir.resolve("build.gradle.kts").apply { appendText(System.lineSeparator()) appendText(content) + appendText(System.lineSeparator()) } } } diff --git a/plugin-build/plugin/src/test/resources/jvmProject/build.gradle.kts b/plugin-build/plugin/src/test/resources/jvmProject/build.gradle.kts index f28040e..4072841 100644 --- a/plugin-build/plugin/src/test/resources/jvmProject/build.gradle.kts +++ b/plugin-build/plugin/src/test/resources/jvmProject/build.gradle.kts @@ -3,6 +3,6 @@ plugins { id("com.ncorti.ktfmt.gradle") } -repositories { - mavenCentral() -} \ No newline at end of file +ktfmt { kotlinLangStyle() } + +repositories { mavenCentral() } From 1753362a53b3c0395227ac37fed6850f851000f1 Mon Sep 17 00:00:00 2001 From: Julian Roggendorf Date: Mon, 25 Nov 2024 17:34:08 +0100 Subject: [PATCH 4/9] Create tests for script tasks --- .../tasks/KtfmtCheckTaskIntegrationTest.kt | 34 ++++++++++++ .../tasks/KtfmtFormatTaskIntegrationTest.kt | 54 ++++++++++++++++++- 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtCheckTaskIntegrationTest.kt b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtCheckTaskIntegrationTest.kt index a26fa17..255423c 100644 --- a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtCheckTaskIntegrationTest.kt +++ b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtCheckTaskIntegrationTest.kt @@ -384,6 +384,40 @@ internal class KtfmtCheckTaskIntegrationTest { assertThat(result.task(":ktfmtCheckMain")?.outcome).isEqualTo(NO_SOURCE) } + @Test + fun `check script task should validate top-level script file`() { + createTempFile(content = "val answer=42\n", fileName = "TestFile.kts", path = "") + + val result = + GradleRunner.create() + .withProjectDir(tempDir) + .withPluginClasspath() + .withArguments("ktfmtCheckScript") + .buildAndFail() + + assertThat(result.task(":ktfmtCheckScript")?.outcome).isEqualTo(FAILED) + assertThat(result.output).containsMatch("Invalid formatting for: .*TestFile.kts") + } + + @Test + fun `check script task should ignore non top-level script files`() { + createTempFile( + content = "val answer=42\n", + fileName = "TestFile.kts", + path = "src/main/java", + ) + + val result = + GradleRunner.create() + .withProjectDir(tempDir) + .withPluginClasspath() + .withArguments("ktfmtCheckScript") + .forwardOutput() + .build() + + assertThat(result.task(":ktfmtCheckScript")?.outcome).isEqualTo(SUCCESS) + } + private fun appendToBuildGradle(content: String) { tempDir.resolve("build.gradle.kts").apply { appendText(System.lineSeparator()) diff --git a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtFormatTaskIntegrationTest.kt b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtFormatTaskIntegrationTest.kt index 045a2b2..2d7ac4e 100644 --- a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtFormatTaskIntegrationTest.kt +++ b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtFormatTaskIntegrationTest.kt @@ -447,6 +447,57 @@ internal class KtfmtFormatTaskIntegrationTest { assertThat(result.task(":ktfmtFormatMain")?.outcome).isEqualTo(NO_SOURCE) } + @Test + fun `format script task should fail if top-level script file could not be parsed`() { + val scriptFile = createTempFile(content = "val answer=\n", fileName = "my.kts", path = "") + + val result = + GradleRunner.create() + .withProjectDir(tempDir) + .withPluginClasspath() + .withArguments("ktfmtFormatScript") + .forwardOutput() + .buildAndFail() + + val actual = scriptFile.readText() + assertThat(actual).isEqualTo("val answer=\n") + assertThat(result.task(":ktfmtFormatScript")?.outcome).isEqualTo(FAILED) + } + + @Test + fun `format script task should format top-level script file`() { + val scriptFile = createTempFile(content = "val answer=42\n", fileName = "my.kts", path = "") + + val result = + GradleRunner.create() + .withProjectDir(tempDir) + .withPluginClasspath() + .withArguments("ktfmtFormatScript") + .forwardOutput() + .build() + + val actual = scriptFile.readText() + assertThat(actual).isEqualTo("val answer = 42\n") + assertThat(result.task(":ktfmtFormatScript")?.outcome).isEqualTo(SUCCESS) + } + + @Test + fun `format script task should not format non top-level script file`() { + val scriptFile = createTempFile(content = "val answer=42\n", fileName = "my.kts") + + val result = + GradleRunner.create() + .withProjectDir(tempDir) + .withPluginClasspath() + .withArguments("ktfmtFormatScript") + .forwardOutput() + .build() + + val actual = scriptFile.readText() + assertThat(actual).isEqualTo("val answer=42\n") + assertThat(result.task(":ktfmtFormatScript")?.outcome).isEqualTo(SUCCESS) + } + private fun createTempFile( @Language("kotlin") content: String, fileName: String = "TestFile.kt", @@ -458,11 +509,10 @@ internal class KtfmtFormatTaskIntegrationTest { writeText(content) } - private fun appendToBuildGradle(content: String) { + private fun appendToBuildGradle(content: String) = tempDir.resolve("build.gradle.kts").apply { appendText(System.lineSeparator()) appendText(content) appendText(System.lineSeparator()) } - } } From 0391b986064d0adcb55ed2655b98ccb6f1131495 Mon Sep 17 00:00:00 2001 From: Julian Roggendorf Date: Mon, 25 Nov 2024 18:14:13 +0100 Subject: [PATCH 5/9] Update documentation --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 57f1fc6..bdaf348 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,11 @@ By default, `ktfmt-gradle` will add two Gradle tasks to your build: Those two tasks will invoke `ktfmt` on the **whole module**. More specific tasks are avialable based on the module type. +Additionally, the plugin will create check/format tasks for top-level Kotlin script files: + +- `ktfmtCheckScript` that will check if the top-level script files in your module is ktfmt-compliant +- `ktfmtFormatScript` that will reformat top-level script files with ktfmt + #### Jvm/Js Modules For Jvm/Js modules, the plugin will create a check/format task for **every source set**. For example, jvm modules will From 4bd1fa6f9ddb4228c390763218eda1ffad842870 Mon Sep 17 00:00:00 2001 From: Julian Roggendorf Date: Fri, 29 Nov 2024 15:49:23 +0100 Subject: [PATCH 6/9] Pluralize script task names --- README.md | 4 ++-- .../com/ncorti/ktfmt/gradle/KtfmtPlugin.kt | 8 ++++---- .../ncorti/ktfmt/gradle/KtfmtPluginUtils.kt | 6 +++--- .../ncorti/ktfmt/gradle/KtfmtPluginTest.kt | 20 +++++++++---------- .../tasks/KtfmtCheckTaskIntegrationTest.kt | 12 +++++------ .../tasks/KtfmtFormatTaskIntegrationTest.kt | 18 ++++++++--------- 6 files changed, 34 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index bdaf348..ff99bb6 100644 --- a/README.md +++ b/README.md @@ -58,8 +58,8 @@ Those two tasks will invoke `ktfmt` on the **whole module**. More specific tasks Additionally, the plugin will create check/format tasks for top-level Kotlin script files: -- `ktfmtCheckScript` that will check if the top-level script files in your module is ktfmt-compliant -- `ktfmtFormatScript` that will reformat top-level script files with ktfmt +- `ktfmtCheckScripts` that will check if the top-level script files in your module is ktfmt-compliant +- `ktfmtFormatScripts` that will reformat top-level script files with ktfmt #### Jvm/Js Modules diff --git a/plugin-build/plugin/src/main/java/com/ncorti/ktfmt/gradle/KtfmtPlugin.kt b/plugin-build/plugin/src/main/java/com/ncorti/ktfmt/gradle/KtfmtPlugin.kt index 9df7a03..91c5c5b 100644 --- a/plugin-build/plugin/src/main/java/com/ncorti/ktfmt/gradle/KtfmtPlugin.kt +++ b/plugin-build/plugin/src/main/java/com/ncorti/ktfmt/gradle/KtfmtPlugin.kt @@ -4,7 +4,7 @@ import com.ncorti.ktfmt.gradle.KtfmtAndroidUtils.applyKtfmtToAndroidProject import com.ncorti.ktfmt.gradle.KtfmtPluginUtils.EXTENSION_NAME import com.ncorti.ktfmt.gradle.KtfmtPluginUtils.TASK_NAME_CHECK import com.ncorti.ktfmt.gradle.KtfmtPluginUtils.TASK_NAME_FORMAT -import com.ncorti.ktfmt.gradle.KtfmtPluginUtils.createScriptTasks +import com.ncorti.ktfmt.gradle.KtfmtPluginUtils.createScriptsTasks import com.ncorti.ktfmt.gradle.KtfmtPluginUtils.createTasksForSourceSet import com.ncorti.ktfmt.gradle.tasks.KtfmtBaseTask import com.ncorti.ktfmt.gradle.util.i @@ -63,7 +63,7 @@ abstract class KtfmtPlugin : Plugin { if (project.plugins.hasPlugin("org.jetbrains.kotlin.multiplatform")) { project.logger.i("Skipping Android task creation, as KMP is applied") } else { - createScriptTasks(project, project.projectDir, topLevelFormat, topLevelCheck) + createScriptsTasks(project, project.projectDir, topLevelFormat, topLevelCheck) applyKtfmtToAndroidProject(project, topLevelFormat, topLevelCheck, ktfmtExtension) } } @@ -75,7 +75,7 @@ abstract class KtfmtPlugin : Plugin { private fun applyKtfmt(project: Project, ktfmtExtension: KtfmtExtension) { val extension = project.extensions.getByType(KotlinProjectExtension::class.java) - createScriptTasks(project, project.projectDir, topLevelFormat, topLevelCheck) + createScriptsTasks(project, project.projectDir, topLevelFormat, topLevelCheck) extension.sourceSets.all { createTasksForSourceSet( project, @@ -90,7 +90,7 @@ abstract class KtfmtPlugin : Plugin { private fun applyKtfmtToMultiplatformProject(project: Project, ktfmtExtension: KtfmtExtension) { val extension = project.extensions.getByType(KotlinMultiplatformExtension::class.java) - createScriptTasks(project, project.projectDir, topLevelFormat, topLevelCheck) + createScriptsTasks(project, project.projectDir, topLevelFormat, topLevelCheck) extension.sourceSets.all { val name = "kmp ${it.name}" if (it.name.startsWith("android")) { diff --git a/plugin-build/plugin/src/main/java/com/ncorti/ktfmt/gradle/KtfmtPluginUtils.kt b/plugin-build/plugin/src/main/java/com/ncorti/ktfmt/gradle/KtfmtPluginUtils.kt index 6a4d20d..b09d464 100644 --- a/plugin-build/plugin/src/main/java/com/ncorti/ktfmt/gradle/KtfmtPluginUtils.kt +++ b/plugin-build/plugin/src/main/java/com/ncorti/ktfmt/gradle/KtfmtPluginUtils.kt @@ -63,14 +63,14 @@ internal object KtfmtPluginUtils { } } - internal fun createScriptTasks( + internal fun createScriptsTasks( project: Project, projectDir: File, topLevelFormat: TaskProvider, topLevelCheck: TaskProvider, ) { - val checkTaskName = "${TASK_NAME_CHECK}Script" - val formatTaskName = "${TASK_NAME_FORMAT}Script" + val checkTaskName = "${TASK_NAME_CHECK}Scripts" + val formatTaskName = "${TASK_NAME_FORMAT}Scripts" val scriptFiles = project diff --git a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/KtfmtPluginTest.kt b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/KtfmtPluginTest.kt index 4920656..6e9ce4a 100644 --- a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/KtfmtPluginTest.kt +++ b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/KtfmtPluginTest.kt @@ -32,13 +32,13 @@ class KtfmtPluginTest { assertThat(project["ktfmtCheckTest"]).isInstanceOf(KtfmtCheckTask::class.java) assertThat(project["ktfmtFormatTest"]).isInstanceOf(KtfmtFormatTask::class.java) - assertThat(project["ktfmtCheckScript"]).isInstanceOf(KtfmtCheckTask::class.java) - assertThat(project["ktfmtFormatScript"]).isInstanceOf(KtfmtFormatTask::class.java) + assertThat(project["ktfmtCheckScripts"]).isInstanceOf(KtfmtCheckTask::class.java) + assertThat(project["ktfmtFormatScripts"]).isInstanceOf(KtfmtFormatTask::class.java) assertThat(project["ktfmtCheck"].dependencies) - .containsExactly("ktfmtCheckMain", "ktfmtCheckTest", "ktfmtCheckScript") + .containsExactly("ktfmtCheckMain", "ktfmtCheckTest", "ktfmtCheckScripts") assertThat(project["ktfmtFormat"].dependencies) - .containsExactly("ktfmtFormatMain", "ktfmtFormatTest", "ktfmtFormatScript") + .containsExactly("ktfmtFormatMain", "ktfmtFormatTest", "ktfmtFormatScripts") } @Test @@ -53,9 +53,9 @@ class KtfmtPluginTest { assertThat(project["ktfmtFormatTest"]).isInstanceOf(KtfmtFormatTask::class.java) assertThat(project["ktfmtCheck"].dependencies) - .containsExactly("ktfmtCheckMain", "ktfmtCheckTest", "ktfmtCheckScript") + .containsExactly("ktfmtCheckMain", "ktfmtCheckTest", "ktfmtCheckScripts") assertThat(project["ktfmtFormat"].dependencies) - .containsExactly("ktfmtFormatMain", "ktfmtFormatTest", "ktfmtFormatScript") + .containsExactly("ktfmtFormatMain", "ktfmtFormatTest", "ktfmtFormatScripts") } @Test @@ -77,13 +77,13 @@ class KtfmtPluginTest { .containsExactly( "ktfmtCheckKmpCommonMain", "ktfmtCheckKmpCommonTest", - "ktfmtCheckScript", + "ktfmtCheckScripts", ) assertThat(project["ktfmtFormat"].dependencies) .containsExactly( "ktfmtFormatKmpCommonMain", "ktfmtFormatKmpCommonTest", - "ktfmtFormatScript", + "ktfmtFormatScripts", ) } @@ -169,7 +169,7 @@ class KtfmtPluginTest { "ktfmtCheckTestFixtures", "ktfmtCheckTestFixturesRelease", "ktfmtCheckTestFixturesDebug", - "ktfmtCheckScript", + "ktfmtCheckScripts", ) assertThat(project["ktfmtFormat"].dependencies) .containsExactly( @@ -185,7 +185,7 @@ class KtfmtPluginTest { "ktfmtFormatTestFixtures", "ktfmtFormatTestFixturesRelease", "ktfmtFormatTestFixturesDebug", - "ktfmtFormatScript", + "ktfmtFormatScripts", ) } diff --git a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtCheckTaskIntegrationTest.kt b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtCheckTaskIntegrationTest.kt index 255423c..8c866c7 100644 --- a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtCheckTaskIntegrationTest.kt +++ b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtCheckTaskIntegrationTest.kt @@ -385,22 +385,22 @@ internal class KtfmtCheckTaskIntegrationTest { } @Test - fun `check script task should validate top-level script file`() { + fun `check scripts task should validate top-level script file`() { createTempFile(content = "val answer=42\n", fileName = "TestFile.kts", path = "") val result = GradleRunner.create() .withProjectDir(tempDir) .withPluginClasspath() - .withArguments("ktfmtCheckScript") + .withArguments("ktfmtCheckScripts") .buildAndFail() - assertThat(result.task(":ktfmtCheckScript")?.outcome).isEqualTo(FAILED) + assertThat(result.task(":ktfmtCheckScripts")?.outcome).isEqualTo(FAILED) assertThat(result.output).containsMatch("Invalid formatting for: .*TestFile.kts") } @Test - fun `check script task should ignore non top-level script files`() { + fun `check scripts task should ignore non top-level script files`() { createTempFile( content = "val answer=42\n", fileName = "TestFile.kts", @@ -411,11 +411,11 @@ internal class KtfmtCheckTaskIntegrationTest { GradleRunner.create() .withProjectDir(tempDir) .withPluginClasspath() - .withArguments("ktfmtCheckScript") + .withArguments("ktfmtCheckScripts") .forwardOutput() .build() - assertThat(result.task(":ktfmtCheckScript")?.outcome).isEqualTo(SUCCESS) + assertThat(result.task(":ktfmtCheckScripts")?.outcome).isEqualTo(SUCCESS) } private fun appendToBuildGradle(content: String) { diff --git a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtFormatTaskIntegrationTest.kt b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtFormatTaskIntegrationTest.kt index 2d7ac4e..8c77cb9 100644 --- a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtFormatTaskIntegrationTest.kt +++ b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtFormatTaskIntegrationTest.kt @@ -448,54 +448,54 @@ internal class KtfmtFormatTaskIntegrationTest { } @Test - fun `format script task should fail if top-level script file could not be parsed`() { + fun `format scripts task should fail if top-level script file could not be parsed`() { val scriptFile = createTempFile(content = "val answer=\n", fileName = "my.kts", path = "") val result = GradleRunner.create() .withProjectDir(tempDir) .withPluginClasspath() - .withArguments("ktfmtFormatScript") + .withArguments("ktfmtFormatScripts") .forwardOutput() .buildAndFail() val actual = scriptFile.readText() assertThat(actual).isEqualTo("val answer=\n") - assertThat(result.task(":ktfmtFormatScript")?.outcome).isEqualTo(FAILED) + assertThat(result.task(":ktfmtFormatScripts")?.outcome).isEqualTo(FAILED) } @Test - fun `format script task should format top-level script file`() { + fun `format scripts task should format top-level script file`() { val scriptFile = createTempFile(content = "val answer=42\n", fileName = "my.kts", path = "") val result = GradleRunner.create() .withProjectDir(tempDir) .withPluginClasspath() - .withArguments("ktfmtFormatScript") + .withArguments("ktfmtFormatScripts") .forwardOutput() .build() val actual = scriptFile.readText() assertThat(actual).isEqualTo("val answer = 42\n") - assertThat(result.task(":ktfmtFormatScript")?.outcome).isEqualTo(SUCCESS) + assertThat(result.task(":ktfmtFormatScripts")?.outcome).isEqualTo(SUCCESS) } @Test - fun `format script task should not format non top-level script file`() { + fun `format scripts task should not format non top-level script file`() { val scriptFile = createTempFile(content = "val answer=42\n", fileName = "my.kts") val result = GradleRunner.create() .withProjectDir(tempDir) .withPluginClasspath() - .withArguments("ktfmtFormatScript") + .withArguments("ktfmtFormatScripts") .forwardOutput() .build() val actual = scriptFile.readText() assertThat(actual).isEqualTo("val answer=42\n") - assertThat(result.task(":ktfmtFormatScript")?.outcome).isEqualTo(SUCCESS) + assertThat(result.task(":ktfmtFormatScripts")?.outcome).isEqualTo(SUCCESS) } private fun createTempFile( From c077b834dd77c1368997f5a25a1cf18c169c72d3 Mon Sep 17 00:00:00 2001 From: Julian Roggendorf Date: Sat, 30 Nov 2024 11:30:24 +0100 Subject: [PATCH 7/9] Extract shared test utility functions --- .../tasks/KtfmtCheckTaskIntegrationTest.kt | 85 +++++++---------- .../tasks/KtfmtFormatTaskIntegrationTest.kt | 91 ++++++++----------- .../com/ncorti/ktfmt/gradle/testutil/File.kt | 23 +++++ 3 files changed, 98 insertions(+), 101 deletions(-) create mode 100644 plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/testutil/File.kt diff --git a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtCheckTaskIntegrationTest.kt b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtCheckTaskIntegrationTest.kt index 8c866c7..2a0dbdc 100644 --- a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtCheckTaskIntegrationTest.kt +++ b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtCheckTaskIntegrationTest.kt @@ -1,6 +1,8 @@ package com.ncorti.ktfmt.gradle.tasks import com.google.common.truth.Truth.assertThat +import com.ncorti.ktfmt.gradle.testutil.appendToBuildGradle +import com.ncorti.ktfmt.gradle.testutil.createTempFile import java.io.File import org.gradle.testkit.runner.BuildResult import org.gradle.testkit.runner.GradleRunner @@ -9,7 +11,6 @@ import org.gradle.testkit.runner.TaskOutcome.FROM_CACHE import org.gradle.testkit.runner.TaskOutcome.NO_SOURCE import org.gradle.testkit.runner.TaskOutcome.SUCCESS import org.gradle.testkit.runner.TaskOutcome.UP_TO_DATE -import org.intellij.lang.annotations.Language import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.io.TempDir @@ -27,7 +28,7 @@ internal class KtfmtCheckTaskIntegrationTest { @Test fun `check task fails if there is invalid code`() { - createTempFile(content = "val answer = `") + tempDir.createTempFile(content = "val answer = `") val result = GradleRunner.create() .withProjectDir(tempDir) @@ -41,7 +42,7 @@ internal class KtfmtCheckTaskIntegrationTest { @Test fun `check task fails if there is not formatted code`() { - createTempFile(content = "val answer=42") + tempDir.createTempFile(content = "val answer=42") val result = GradleRunner.create() .withProjectDir(tempDir) @@ -56,7 +57,7 @@ internal class KtfmtCheckTaskIntegrationTest { @Test fun `check task fails if ktfmt fails to parse the code`() { // The following code will case ktfmt to fail with error: Failed to parse file - createTempFile( + tempDir.createTempFile( """ val res = when { ```` @@ -79,7 +80,7 @@ internal class KtfmtCheckTaskIntegrationTest { @Test fun `check task succeed if code is formatted`() { - createTempFile(content = "val answer = 42\n") + tempDir.createTempFile(content = "val answer = 42\n") val result = GradleRunner.create() .withProjectDir(tempDir) @@ -92,7 +93,7 @@ internal class KtfmtCheckTaskIntegrationTest { @Test fun `check task runs before compilation`() { - createTempFile(content = "val answer = 42\n") + tempDir.createTempFile(content = "val answer = 42\n") val result = GradleRunner.create() .withProjectDir(tempDir) @@ -108,7 +109,7 @@ internal class KtfmtCheckTaskIntegrationTest { @Test fun `check task prints formatted files with --info`() { - createTempFile(content = "val answer = 42\n") + tempDir.createTempFile(content = "val answer = 42\n") val result = GradleRunner.create() .withProjectDir(tempDir) @@ -123,7 +124,7 @@ internal class KtfmtCheckTaskIntegrationTest { @Test fun `format task uses configuration cache correctly`() { - createTempFile(content = "val answer = 42\n") + tempDir.createTempFile(content = "val answer = 42\n") GradleRunner.create() .withProjectDir(tempDir) .withPluginClasspath() @@ -142,8 +143,8 @@ internal class KtfmtCheckTaskIntegrationTest { @Test fun `check task validates all the file with a failure`() { - createTempFile(content = "val answer = `\n", fileName = "File1.kt") - createTempFile(content = "val answer = 42\n", fileName = "File2.kt") + tempDir.createTempFile(content = "val answer = `\n", fileName = "File1.kt") + tempDir.createTempFile(content = "val answer = 42\n", fileName = "File2.kt") val result = GradleRunner.create() @@ -159,8 +160,8 @@ internal class KtfmtCheckTaskIntegrationTest { @Test fun `check task skips a file if with --include-only`() { - createTempFile(content = "val answer = `\n", fileName = "File1.kt") - val file2 = createTempFile(content = "val answer = 42\n", fileName = "File2.kt") + tempDir.createTempFile(content = "val answer = `\n", fileName = "File1.kt") + val file2 = tempDir.createTempFile(content = "val answer = 42\n", fileName = "File2.kt") val result = GradleRunner.create() @@ -183,7 +184,10 @@ internal class KtfmtCheckTaskIntegrationTest { @ValueSource(ints = [10, 15, 30, 50, 100, 1000]) fun `check task can check the formatting of multiple files`(n: Int) { repeat(n) { index -> - createTempFile(content = "val answer${index} = 42\n", fileName = "TestFile$index.kt") + tempDir.createTempFile( + content = "val answer${index} = 42\n", + fileName = "TestFile$index.kt", + ) } val result = GradleRunner.create() @@ -198,7 +202,7 @@ internal class KtfmtCheckTaskIntegrationTest { @Test fun `check task is cacheable`() { - createTempFile(content = "val answer = 42\n") + tempDir.createTempFile(content = "val answer = 42\n") var result: BuildResult? = null repeat(2) { @@ -215,17 +219,17 @@ internal class KtfmtCheckTaskIntegrationTest { @Test fun `check task should be up-to-date when invoked twice with multiple different sized sourceSets`() { - createTempFile( + tempDir.createTempFile( content = "val answer = 42\n", fileName = "SrcFile.kt", path = "src/main/java", ) - createTempFile( + tempDir.createTempFile( content = "val answer = 42\n", fileName = "TestFile.kt", path = "src/test/java", ) - createTempFile( + tempDir.createTempFile( content = "val answer = 42\n", fileName = "TestFile2.kt", path = "src/test/java", @@ -254,7 +258,7 @@ internal class KtfmtCheckTaskIntegrationTest { @Test fun `check task is configuration cache compatible`() { - createTempFile(content = "val answer = 42\n") + tempDir.createTempFile(content = "val answer = 42\n") var result: BuildResult? = null repeat(2) { @@ -271,9 +275,9 @@ internal class KtfmtCheckTaskIntegrationTest { @Test fun `custom formatCheck task should be compatible with configuration cache`() { - createTempFile(content = "val answer = 42\n") + tempDir.createTempFile(content = "val answer = 42\n") - appendToBuildGradle( + tempDir.appendToBuildGradle( """ |tasks.register("customFormatCheck") { | source = fileTree("src/main/java") @@ -291,7 +295,7 @@ internal class KtfmtCheckTaskIntegrationTest { @Test fun `check task should detect the source and test files in a flattened project structure`() { - appendToBuildGradle( + tempDir.appendToBuildGradle( """ |kotlin { | sourceSets.main { kotlin.setSrcDirs(listOf("src")) } @@ -301,8 +305,8 @@ internal class KtfmtCheckTaskIntegrationTest { .trimMargin() ) - createTempFile("val answer = 42\n", path = "src/someFolder") - createTempFile("val answer = 42\n", path = "test/someOtherFolder") + tempDir.createTempFile("val answer = 42\n", path = "src/someFolder") + tempDir.createTempFile("val answer = 42\n", path = "test/someOtherFolder") val result = GradleRunner.create() @@ -317,14 +321,14 @@ internal class KtfmtCheckTaskIntegrationTest { @Test fun `check task should by default ignore sourceSets in the build folder`() { - appendToBuildGradle( + tempDir.appendToBuildGradle( """ |kotlin { sourceSets.main { kotlin.srcDirs("build/main") } } """ .trimMargin() ) - createTempFile(content = "val answer=42\n", path = "build/main") + tempDir.createTempFile(content = "val answer=42\n", path = "build/main") val result = GradleRunner.create() @@ -339,7 +343,7 @@ internal class KtfmtCheckTaskIntegrationTest { @Test fun `check task should not ignore sourceSets in build folder when a custom exclusion pattern is specified`() { - appendToBuildGradle( + tempDir.appendToBuildGradle( """ |kotlin { sourceSets.main { kotlin.srcDirs("build/generated") } } | @@ -348,7 +352,7 @@ internal class KtfmtCheckTaskIntegrationTest { .trimMargin() ) - createTempFile(content = "val answer=42\n", path = "build/generated/main") + tempDir.createTempFile(content = "val answer=42\n", path = "build/generated/main") val result = GradleRunner.create() @@ -364,14 +368,14 @@ internal class KtfmtCheckTaskIntegrationTest { @Test fun `check task should ignore the main sourceSets when specified as exclusion pattern`() { - appendToBuildGradle( + tempDir.appendToBuildGradle( """ |ktfmt { srcSetPathExclusionPattern.set(Regex(".*[\\\\/]main[\\\\/].*")) } """ .trimMargin() ) - createTempFile(content = "val answer=42\n") + tempDir.createTempFile(content = "val answer=42\n") val result = GradleRunner.create() @@ -386,7 +390,7 @@ internal class KtfmtCheckTaskIntegrationTest { @Test fun `check scripts task should validate top-level script file`() { - createTempFile(content = "val answer=42\n", fileName = "TestFile.kts", path = "") + tempDir.createTempFile(content = "val answer=42\n", fileName = "TestFile.kts", path = "") val result = GradleRunner.create() @@ -401,7 +405,7 @@ internal class KtfmtCheckTaskIntegrationTest { @Test fun `check scripts task should ignore non top-level script files`() { - createTempFile( + tempDir.createTempFile( content = "val answer=42\n", fileName = "TestFile.kts", path = "src/main/java", @@ -417,23 +421,4 @@ internal class KtfmtCheckTaskIntegrationTest { assertThat(result.task(":ktfmtCheckScripts")?.outcome).isEqualTo(SUCCESS) } - - private fun appendToBuildGradle(content: String) { - tempDir.resolve("build.gradle.kts").apply { - appendText(System.lineSeparator()) - appendText(content) - appendText(System.lineSeparator()) - } - } - - private fun createTempFile( - @Language("kotlin") content: String, - fileName: String = "TestFile.kt", - path: String = "src/main/java", - ): File = - tempDir.resolve(path).resolve(fileName).apply { - parentFile.mkdirs() - createNewFile() - writeText(content) - } } diff --git a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtFormatTaskIntegrationTest.kt b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtFormatTaskIntegrationTest.kt index 8c77cb9..2e4b5ed 100644 --- a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtFormatTaskIntegrationTest.kt +++ b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/tasks/KtfmtFormatTaskIntegrationTest.kt @@ -1,13 +1,14 @@ package com.ncorti.ktfmt.gradle.tasks import com.google.common.truth.Truth.assertThat +import com.ncorti.ktfmt.gradle.testutil.appendToBuildGradle +import com.ncorti.ktfmt.gradle.testutil.createTempFile import java.io.File import org.gradle.testkit.runner.GradleRunner import org.gradle.testkit.runner.TaskOutcome.FAILED import org.gradle.testkit.runner.TaskOutcome.NO_SOURCE import org.gradle.testkit.runner.TaskOutcome.SUCCESS import org.gradle.testkit.runner.TaskOutcome.UP_TO_DATE -import org.intellij.lang.annotations.Language import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.io.TempDir @@ -25,7 +26,7 @@ internal class KtfmtFormatTaskIntegrationTest { @Test fun `format task fails if there is invalid code`() { - createTempFile(content = "val answer = `") + tempDir.createTempFile(content = "val answer = `") val result = GradleRunner.create() .withProjectDir(tempDir) @@ -39,7 +40,7 @@ internal class KtfmtFormatTaskIntegrationTest { @Test fun `format formats correctly`() { - val tempFile = createTempFile(content = "val answer=42") + val tempFile = tempDir.createTempFile(content = "val answer=42") val result = GradleRunner.create() .withProjectDir(tempDir) @@ -53,7 +54,7 @@ internal class KtfmtFormatTaskIntegrationTest { @Test fun `format task succeed if code is formatted`() { - createTempFile(content = "val answer = 42\n") + tempDir.createTempFile(content = "val answer = 42\n") val result = GradleRunner.create() .withProjectDir(tempDir) @@ -66,7 +67,7 @@ internal class KtfmtFormatTaskIntegrationTest { @Test fun `format task is up to date after subsequent execution`() { - createTempFile(content = "val answer = 42\n") + tempDir.createTempFile(content = "val answer = 42\n") var result = GradleRunner.create() .withProjectDir(tempDir) @@ -88,7 +89,7 @@ internal class KtfmtFormatTaskIntegrationTest { @Test fun `format task is up to date after subsequent execution when formatting`() { - createTempFile(content = "val answer=42") + tempDir.createTempFile(content = "val answer=42") var result = GradleRunner.create() .withProjectDir(tempDir) @@ -117,7 +118,7 @@ internal class KtfmtFormatTaskIntegrationTest { @Test fun `format task is up to executed again after edit`() { - val tempFile = createTempFile(content = "val answer = 42\n") + val tempFile = tempDir.createTempFile(content = "val answer = 42\n") var result = GradleRunner.create() .withProjectDir(tempDir) @@ -152,7 +153,7 @@ internal class KtfmtFormatTaskIntegrationTest { @Test fun `format task prints formatted files with --info`() { - createTempFile(content = "val answer=42\n") + tempDir.createTempFile(content = "val answer=42\n") val result = GradleRunner.create() .withProjectDir(tempDir) @@ -167,7 +168,7 @@ internal class KtfmtFormatTaskIntegrationTest { @Test fun `format task uses configuration cache correctly`() { - createTempFile(content = "val answer = 42\n") + tempDir.createTempFile(content = "val answer = 42\n") GradleRunner.create() .withProjectDir(tempDir) .withPluginClasspath() @@ -186,8 +187,8 @@ internal class KtfmtFormatTaskIntegrationTest { @Test fun `format task reformats all the file even with a failure`() { - val file1 = createTempFile(content = "val answer = `", fileName = "File1.kt") - val file2 = createTempFile(content = "val answer=42", fileName = "File2.kt") + val file1 = tempDir.createTempFile(content = "val answer = `", fileName = "File1.kt") + val file2 = tempDir.createTempFile(content = "val answer=42", fileName = "File2.kt") val result = GradleRunner.create() @@ -207,7 +208,7 @@ internal class KtfmtFormatTaskIntegrationTest { @Test fun `format task runs before compilation`() { - createTempFile(content = "val answer = 42\n") + tempDir.createTempFile(content = "val answer = 42\n") val result = GradleRunner.create() .withProjectDir(tempDir) @@ -223,8 +224,8 @@ internal class KtfmtFormatTaskIntegrationTest { @Test fun `format task skips a file if with --include-only`() { - createTempFile(content = "val answer = `\n", fileName = "File1.kt") - val file2 = createTempFile(content = "val answer=42\n", fileName = "File2.kt") + tempDir.createTempFile(content = "val answer = `\n", fileName = "File1.kt") + val file2 = tempDir.createTempFile(content = "val answer=42\n", fileName = "File2.kt") val result = GradleRunner.create() @@ -248,7 +249,10 @@ internal class KtfmtFormatTaskIntegrationTest { @ValueSource(ints = [10, 15, 30, 50, 100, 1000]) fun `format task can format multiple files`(n: Int) { repeat(n) { index -> - createTempFile(content = "val answer${index}=42\n", fileName = "TestFile$index.kt") + tempDir.createTempFile( + content = "val answer${index}=42\n", + fileName = "TestFile$index.kt", + ) } val result = GradleRunner.create() @@ -263,9 +267,9 @@ internal class KtfmtFormatTaskIntegrationTest { @Test fun `custom format task should be compatible with configuration cache`() { - createTempFile(content = "val answer = 42\n") + tempDir.createTempFile(content = "val answer = 42\n") - appendToBuildGradle( + tempDir.appendToBuildGradle( """ |tasks.register("customFormatTask") { | source = fileTree("src/main/java") @@ -284,7 +288,7 @@ internal class KtfmtFormatTaskIntegrationTest { @Test fun `should format the files in kotlinLang style with a 4 space indentation`() { val file = - createTempFile( + tempDir.createTempFile( content = """ |fun someFun(){ @@ -295,7 +299,7 @@ internal class KtfmtFormatTaskIntegrationTest { .trimMargin() ) - appendToBuildGradle("ktfmt { kotlinLangStyle() }") + tempDir.appendToBuildGradle("ktfmt { kotlinLangStyle() }") GradleRunner.create() .withProjectDir(tempDir) @@ -317,7 +321,7 @@ internal class KtfmtFormatTaskIntegrationTest { @Test fun `should format the files in googleStyle style with a 2 space indentation`() { val file = - createTempFile( + tempDir.createTempFile( content = """ |fun someFun(){ @@ -328,7 +332,7 @@ internal class KtfmtFormatTaskIntegrationTest { .trimMargin() ) - appendToBuildGradle("ktfmt { googleStyle() }") + tempDir.appendToBuildGradle("ktfmt { googleStyle() }") GradleRunner.create() .withProjectDir(tempDir) @@ -350,7 +354,7 @@ internal class KtfmtFormatTaskIntegrationTest { @Test fun `format task should detect the source and test files in a flattened project structure and format them`() { - appendToBuildGradle( + tempDir.appendToBuildGradle( """ |kotlin { | sourceSets.main { kotlin.setSrcDirs(listOf("src")) } @@ -360,8 +364,8 @@ internal class KtfmtFormatTaskIntegrationTest { .trimMargin() ) - val sourceFile = createTempFile("val answer = 42\n", path = "src/someFolder") - val testFile = createTempFile("val answer = 42\n", path = "test/someOtherFolder") + val sourceFile = tempDir.createTempFile("val answer = 42\n", path = "src/someFolder") + val testFile = tempDir.createTempFile("val answer = 42\n", path = "test/someOtherFolder") val result = GradleRunner.create() @@ -379,14 +383,14 @@ internal class KtfmtFormatTaskIntegrationTest { @Test fun `format task should by default not format sourceSets in the build folder`() { - appendToBuildGradle( + tempDir.appendToBuildGradle( """ |kotlin { sourceSets.main { kotlin.srcDirs("build/main") } } """ .trimMargin() ) - val file = createTempFile(content = "val answer=42\n", path = "build/main") + val file = tempDir.createTempFile(content = "val answer=42\n", path = "build/main") val result = GradleRunner.create() @@ -403,7 +407,7 @@ internal class KtfmtFormatTaskIntegrationTest { @Test fun `format task should not ignore sourceSets in build folder when a custom exclusion pattern is specified`() { - appendToBuildGradle( + tempDir.appendToBuildGradle( """ |kotlin { sourceSets.main { kotlin.srcDirs("build/generated") } } | @@ -412,7 +416,8 @@ internal class KtfmtFormatTaskIntegrationTest { .trimMargin() ) - val file = createTempFile(content = "val answer=42\n", path = "build/generated/main") + val file = + tempDir.createTempFile(content = "val answer=42\n", path = "build/generated/main") GradleRunner.create() .withProjectDir(tempDir) @@ -427,14 +432,14 @@ internal class KtfmtFormatTaskIntegrationTest { @Test fun `format task should ignore the main sourceSets when specified as exclusion pattern`() { - appendToBuildGradle( + tempDir.appendToBuildGradle( """ |ktfmt { srcSetPathExclusionPattern.set(Regex(".*[\\\\/]main[\\\\/].*")) } """ .trimMargin() ) - createTempFile(content = "val answer=42\n") + tempDir.createTempFile(content = "val answer=42\n") val result = GradleRunner.create() @@ -449,7 +454,8 @@ internal class KtfmtFormatTaskIntegrationTest { @Test fun `format scripts task should fail if top-level script file could not be parsed`() { - val scriptFile = createTempFile(content = "val answer=\n", fileName = "my.kts", path = "") + val scriptFile = + tempDir.createTempFile(content = "val answer=\n", fileName = "my.kts", path = "") val result = GradleRunner.create() @@ -466,7 +472,8 @@ internal class KtfmtFormatTaskIntegrationTest { @Test fun `format scripts task should format top-level script file`() { - val scriptFile = createTempFile(content = "val answer=42\n", fileName = "my.kts", path = "") + val scriptFile = + tempDir.createTempFile(content = "val answer=42\n", fileName = "my.kts", path = "") val result = GradleRunner.create() @@ -483,7 +490,7 @@ internal class KtfmtFormatTaskIntegrationTest { @Test fun `format scripts task should not format non top-level script file`() { - val scriptFile = createTempFile(content = "val answer=42\n", fileName = "my.kts") + val scriptFile = tempDir.createTempFile(content = "val answer=42\n", fileName = "my.kts") val result = GradleRunner.create() @@ -497,22 +504,4 @@ internal class KtfmtFormatTaskIntegrationTest { assertThat(actual).isEqualTo("val answer=42\n") assertThat(result.task(":ktfmtFormatScripts")?.outcome).isEqualTo(SUCCESS) } - - private fun createTempFile( - @Language("kotlin") content: String, - fileName: String = "TestFile.kt", - path: String = "src/main/java", - ): File = - tempDir.resolve(path).resolve(fileName).apply { - parentFile.mkdirs() - createNewFile() - writeText(content) - } - - private fun appendToBuildGradle(content: String) = - tempDir.resolve("build.gradle.kts").apply { - appendText(System.lineSeparator()) - appendText(content) - appendText(System.lineSeparator()) - } } diff --git a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/testutil/File.kt b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/testutil/File.kt new file mode 100644 index 0000000..071af28 --- /dev/null +++ b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/testutil/File.kt @@ -0,0 +1,23 @@ +package com.ncorti.ktfmt.gradle.testutil + +import java.io.File +import org.intellij.lang.annotations.Language + +fun File.appendToBuildGradle(content: String) { + resolve("build.gradle.kts").apply { + appendText(System.lineSeparator()) + appendText(content) + appendText(System.lineSeparator()) + } +} + +fun File.createTempFile( + @Language("kotlin") content: String, + fileName: String = "TestFile.kt", + path: String = "src/main/java", +): File = + resolve(path).resolve(fileName).apply { + parentFile.mkdirs() + createNewFile() + writeText(content) + } From 29cdea9e54fae03035a6d87b1bea0cded061428e Mon Sep 17 00:00:00 2001 From: Julian Roggendorf Date: Sat, 30 Nov 2024 11:30:37 +0100 Subject: [PATCH 8/9] Fix inserting incorrect line breaks in temp files --- .../src/test/java/com/ncorti/ktfmt/gradle/testutil/File.kt | 2 +- .../src/test/java/com/ncorti/ktfmt/gradle/testutil/String.kt | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/testutil/String.kt diff --git a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/testutil/File.kt b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/testutil/File.kt index 071af28..7e00810 100644 --- a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/testutil/File.kt +++ b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/testutil/File.kt @@ -6,7 +6,7 @@ import org.intellij.lang.annotations.Language fun File.appendToBuildGradle(content: String) { resolve("build.gradle.kts").apply { appendText(System.lineSeparator()) - appendText(content) + appendText(content.ensureLineSeparator()) appendText(System.lineSeparator()) } } diff --git a/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/testutil/String.kt b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/testutil/String.kt new file mode 100644 index 0000000..206a3b2 --- /dev/null +++ b/plugin-build/plugin/src/test/java/com/ncorti/ktfmt/gradle/testutil/String.kt @@ -0,0 +1,3 @@ +package com.ncorti.ktfmt.gradle.testutil + +fun String.ensureLineSeparator(): String = replace(Regex("\r|\n|\r\n}"), System.lineSeparator()) From 6333d0c07138d053db9951423440eedcca620566 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Sat, 7 Dec 2024 22:01:02 +0000 Subject: [PATCH 9/9] Update CHANGELOG --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 785fca6..0e07cc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ Please add your entries according to this format. ## Unreleased +- Add tasks `ktfmtCheckScripts` and `ktfmtFormatScripts` to check and format the `.kts` files in the project folder. + ## Version 0.21.0 _(2024-11-01)_ - KtFmt to 0.53 - AGP to 8.7.1 @@ -187,4 +189,4 @@ Please add your entries according to this format. ## Version 0.1.0 _(2020-12-22)_ -That's the first version of `ktfmt-gradle` \ No newline at end of file +That's the first version of `ktfmt-gradle`