aboutsummaryrefslogtreecommitdiff
path: root/build-logic/src/main
diff options
context:
space:
mode:
authorHarsh Shandilya <me@msfjarvis.dev>2023-03-04 02:01:15 +0530
committerHarsh Shandilya <me@msfjarvis.dev>2023-03-04 02:01:15 +0530
commit3e56fa2e120db21676074e15da80eea3337df4e0 (patch)
treef3c8c2cbf18c9dadf05f8c1735d719a2673c3e38 /build-logic/src/main
parent3a694c7255c9feea489bd7db240814a05d62bd12 (diff)
refactor: use worker API for `KtfmtFormatTask`
Diffstat (limited to 'build-logic/src/main')
-rw-r--r--build-logic/src/main/kotlin/app/passwordstore/gradle/KtfmtPlugin.kt22
-rw-r--r--build-logic/src/main/kotlin/app/passwordstore/gradle/ktfmt/KtfmtFormatTask.kt75
-rw-r--r--build-logic/src/main/kotlin/app/passwordstore/gradle/ktfmt/KtfmtWorkerAction.kt46
-rw-r--r--build-logic/src/main/kotlin/app/passwordstore/gradle/ktfmt/KtfmtWorkerParameters.kt13
4 files changed, 104 insertions, 52 deletions
diff --git a/build-logic/src/main/kotlin/app/passwordstore/gradle/KtfmtPlugin.kt b/build-logic/src/main/kotlin/app/passwordstore/gradle/KtfmtPlugin.kt
index 74e8ba95..c7ff2f06 100644
--- a/build-logic/src/main/kotlin/app/passwordstore/gradle/KtfmtPlugin.kt
+++ b/build-logic/src/main/kotlin/app/passwordstore/gradle/KtfmtPlugin.kt
@@ -2,6 +2,7 @@ package app.passwordstore.gradle
import app.passwordstore.gradle.ktfmt.KtfmtCheckTask
import app.passwordstore.gradle.ktfmt.KtfmtFormatTask
+import java.util.concurrent.Callable
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.register
@@ -9,23 +10,14 @@ import org.gradle.kotlin.dsl.register
class KtfmtPlugin : Plugin<Project> {
override fun apply(target: Project) {
- target.tasks.register<KtfmtFormatTask>("ktfmtFormat") {
- source =
- project.layout.projectDirectory.asFileTree
- .filter { file ->
- file.extension == "kt" ||
- file.extension == "kts" && !file.canonicalPath.contains("build")
- }
- .asFileTree
+ val input = Callable {
+ target.layout.projectDirectory.asFileTree.filter { file ->
+ file.extension == "kt" || file.extension == "kts" && !file.canonicalPath.contains("build")
+ }
}
+ target.tasks.register<KtfmtFormatTask>("ktfmtFormat") { source(input) }
target.tasks.register<KtfmtCheckTask>("ktfmtCheck") {
- source =
- project.layout.projectDirectory.asFileTree
- .filter { file ->
- file.extension == "kt" ||
- file.extension == "kts" && !file.canonicalPath.contains("build")
- }
- .asFileTree
+ source(input)
projectDirectory.set(target.layout.projectDirectory)
}
}
diff --git a/build-logic/src/main/kotlin/app/passwordstore/gradle/ktfmt/KtfmtFormatTask.kt b/build-logic/src/main/kotlin/app/passwordstore/gradle/ktfmt/KtfmtFormatTask.kt
index 82ce4ca3..934d6171 100644
--- a/build-logic/src/main/kotlin/app/passwordstore/gradle/ktfmt/KtfmtFormatTask.kt
+++ b/build-logic/src/main/kotlin/app/passwordstore/gradle/ktfmt/KtfmtFormatTask.kt
@@ -1,52 +1,53 @@
package app.passwordstore.gradle.ktfmt
-import com.facebook.ktfmt.format.Formatter
-import com.facebook.ktfmt.format.FormattingOptions
-import java.io.File
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.async
-import kotlinx.coroutines.awaitAll
-import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.runBlocking
-import org.gradle.api.file.FileCollection
-import org.gradle.api.tasks.IgnoreEmptyDirectories
-import org.gradle.api.tasks.InputFiles
-import org.gradle.api.tasks.PathSensitive
-import org.gradle.api.tasks.PathSensitivity
+import javax.inject.Inject
+import org.gradle.api.GradleException
+import org.gradle.api.file.ProjectLayout
import org.gradle.api.tasks.SourceTask
import org.gradle.api.tasks.TaskAction
+import org.gradle.internal.exceptions.MultiCauseException
+import org.gradle.workers.WorkerExecutor
+import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
-@OptIn(ExperimentalCoroutinesApi::class)
-abstract class KtfmtFormatTask : SourceTask() {
+abstract class KtfmtFormatTask
+@Inject
+constructor(
+ private val workerExecutor: WorkerExecutor,
+ private val projectLayout: ProjectLayout,
+) : SourceTask() {
- @get:PathSensitive(PathSensitivity.RELATIVE)
- @get:InputFiles
- @get:IgnoreEmptyDirectories
- protected val inputFiles: FileCollection
- get() = super.getSource()
+ init {
+ outputs.upToDateWhen { false }
+ }
@TaskAction
fun execute() {
- runBlocking(Dispatchers.IO.limitedParallelism(PARALLEL_TASK_LIMIT)) {
- coroutineScope { inputFiles.map { async { formatFile(it) } }.awaitAll() }
+ val result =
+ with(workerExecutor.noIsolation()) {
+ submit(KtfmtWorkerAction::class.java) {
+ name.set("foofoo")
+ files.from(source)
+ projectDirectory.set(projectLayout.projectDirectory.asFile)
+ }
+ runCatching { await() }
+ }
+
+ result.exceptionOrNull()?.workErrorCauses<Exception>()?.ifNotEmpty {
+ forEach { logger.error(it.message, it.cause) }
+ throw GradleException("error formatting sources for $name")
}
}
- private fun formatFile(input: File) {
- val originCode = input.readText()
- val formattedCode =
- Formatter.format(
- FormattingOptions(
- style = FormattingOptions.Style.GOOGLE,
- maxWidth = 100,
- continuationIndent = 2,
- ),
- originCode
- )
- if (originCode != formattedCode) {
- input.writeText(formattedCode)
- }
+ private inline fun <reified T : Throwable> Throwable.workErrorCauses(): List<Throwable> {
+ return when (this) {
+ is MultiCauseException -> this.causes.map { it.cause }
+ else -> listOf(this.cause)
+ }
+ .filter {
+ // class instance comparison doesn't work due to different classloaders
+ it?.javaClass?.canonicalName == T::class.java.canonicalName
+ }
+ .filterNotNull()
}
companion object {
diff --git a/build-logic/src/main/kotlin/app/passwordstore/gradle/ktfmt/KtfmtWorkerAction.kt b/build-logic/src/main/kotlin/app/passwordstore/gradle/ktfmt/KtfmtWorkerAction.kt
new file mode 100644
index 00000000..d9b265b7
--- /dev/null
+++ b/build-logic/src/main/kotlin/app/passwordstore/gradle/ktfmt/KtfmtWorkerAction.kt
@@ -0,0 +1,46 @@
+package app.passwordstore.gradle.ktfmt
+
+import com.facebook.ktfmt.format.Formatter
+import com.facebook.ktfmt.format.FormattingOptions
+import java.io.File
+import org.gradle.api.logging.LogLevel
+import org.gradle.api.logging.Logger
+import org.gradle.api.logging.Logging
+import org.gradle.internal.logging.slf4j.DefaultContextAwareTaskLogger
+import org.gradle.workers.WorkAction
+
+abstract class KtfmtWorkerAction : WorkAction<KtfmtWorkerParameters> {
+ private val logger: Logger =
+ DefaultContextAwareTaskLogger(Logging.getLogger(KtfmtFormatTask::class.java))
+ private val files: List<File> = parameters.files.toList()
+ private val projectDirectory: File = parameters.projectDirectory.asFile.get()
+ private val name: String = parameters.name.get()
+
+ override fun execute() {
+ try {
+ files.forEach { file ->
+ val sourceText = file.readText()
+ val relativePath = file.toRelativeString(projectDirectory)
+
+ logger.log(LogLevel.DEBUG, "$name checking format: $relativePath")
+
+ val formattedText =
+ Formatter.format(
+ FormattingOptions(
+ style = FormattingOptions.Style.GOOGLE,
+ maxWidth = 100,
+ continuationIndent = 2,
+ ),
+ sourceText
+ )
+
+ if (!formattedText.contentEquals(sourceText)) {
+ logger.log(LogLevel.QUIET, "${file.toRelativeString(projectDirectory)}: Format fixed")
+ file.writeText(formattedText)
+ }
+ }
+ } catch (t: Throwable) {
+ throw Exception("format worker execution error", t)
+ }
+ }
+}
diff --git a/build-logic/src/main/kotlin/app/passwordstore/gradle/ktfmt/KtfmtWorkerParameters.kt b/build-logic/src/main/kotlin/app/passwordstore/gradle/ktfmt/KtfmtWorkerParameters.kt
new file mode 100644
index 00000000..9d4a3e92
--- /dev/null
+++ b/build-logic/src/main/kotlin/app/passwordstore/gradle/ktfmt/KtfmtWorkerParameters.kt
@@ -0,0 +1,13 @@
+package app.passwordstore.gradle.ktfmt
+
+import org.gradle.api.file.ConfigurableFileCollection
+import org.gradle.api.file.RegularFileProperty
+import org.gradle.api.provider.Property
+import org.gradle.workers.WorkParameters
+
+interface KtfmtWorkerParameters : WorkParameters {
+ val name: Property<String>
+ val files: ConfigurableFileCollection
+ val projectDirectory: RegularFileProperty
+ val output: RegularFileProperty
+}