Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatically format generated files using ktlint if possible #34

Merged
merged 1 commit into from
Jan 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions gradle-plugin/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@ kotlinVersion = 2.1.0
publishVersion = 1.3.0

jacksonVersion = 2.18.2
ktlintVersion = 1.5.0
ec4jVersion = 1.1.0

typescriptVersion = ^5.7.2
4 changes: 4 additions & 0 deletions gradle-plugin/karakum-gradle-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ dependencies {
compileOnly(kotlin("gradle-plugin"))

implementation(libs.jackson.databind)
implementation(libs.ktlint.ruleEngine)
implementation(libs.ktlint.ruleEngine.core)
implementation(libs.ktlint.ruleset.standard)
implementation(libs.ec4j)

testImplementation(kotlin("test"))
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
package io.github.sgrishchenko.karakum.gradle.plugin

import io.github.sgrishchenko.karakum.gradle.plugin.service.KtLintService
import io.github.sgrishchenko.karakum.gradle.plugin.tasks.KarakumConfig
import io.github.sgrishchenko.karakum.gradle.plugin.tasks.KarakumGenerate
import io.github.sgrishchenko.karakum.gradle.plugin.tasks.KarakumSync
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.file.FileTree
import org.gradle.api.services.BuildServiceRegistry
import org.gradle.kotlin.dsl.create
import org.gradle.kotlin.dsl.getValue
import org.gradle.kotlin.dsl.provideDelegate
import org.gradle.kotlin.dsl.registerIfAbsent
import org.gradle.kotlin.dsl.registering
import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
import javax.inject.Inject

abstract class KarakumPlugin : Plugin<Project> {
@get:Inject
abstract val sharedServices: BuildServiceRegistry

class KarakumPlugin : Plugin<Project> {
override fun apply(project: Project): Unit = with(project) {
plugins.withId("org.jetbrains.kotlin.multiplatform") {
val karakum = extensions.create<KarakumExtension>("karakum").apply {
Expand Down Expand Up @@ -51,6 +58,8 @@ class KarakumPlugin : Plugin<Project> {
destinationDirectory.convention(layout.dir(npmProjectDirectory).map { it.dir("karakum") })
}

sharedServices.registerIfAbsent("ktlintService", KtLintService::class)

val generateKarakumExternals by tasks.registering(KarakumGenerate::class) {
group = KARAKUM_GRADLE_PLUGIN_GROUP
description = "Generates the Kotlin external declarations using Karakum."
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.github.sgrishchenko.karakum.gradle.plugin.service

import com.pinterest.ktlint.rule.engine.api.KtLintRuleEngine
import com.pinterest.ktlint.ruleset.standard.StandardRuleSetProvider
import org.gradle.api.services.BuildService
import org.gradle.api.services.BuildServiceParameters.None

abstract class KtLintService : BuildService<None> {
val ktlint = KtLintRuleEngine(
ruleProviders = StandardRuleSetProvider().getRuleProviders()
).apply {
// ktlint stores .editorconfig files in a companion object and thus as static state
// this is not good when running multiple builds within the same Gradle daemon
// and the .editorconfig file might have changed, so clear that cache
// so that .editorconfig files are read freshly
trimMemory()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,27 @@ import com.fasterxml.jackson.databind.node.ArrayNode
import com.fasterxml.jackson.databind.node.ObjectNode
import io.github.sgrishchenko.karakum.gradle.plugin.karakumDependency
import io.github.sgrishchenko.karakum.gradle.plugin.kotlinJsCompilation
import io.github.sgrishchenko.karakum.gradle.plugin.service.KtLintService
import io.github.sgrishchenko.karakum.gradle.plugin.typescriptDependency
import io.github.sgrishchenko.karakum.gradle.plugin.worker.KtLintFormatWorker
import org.ec4j.core.Resource.Resources
import org.ec4j.core.ResourcePropertiesService
import org.gradle.api.DefaultTask
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.ProjectLayout
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import org.gradle.api.services.ServiceReference
import org.gradle.api.tasks.*
import org.gradle.kotlin.dsl.submit
import org.gradle.process.ExecOperations
import org.gradle.workers.WorkerExecutor
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrCompilation
import org.jetbrains.kotlin.gradle.targets.js.npm.RequiresNpmDependencies
import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
import java.nio.file.Path
import javax.inject.Inject
import kotlin.text.Charsets.UTF_8

abstract class KarakumGenerate : DefaultTask(), RequiresNpmDependencies {
@get:Inject
Expand All @@ -24,6 +34,12 @@ abstract class KarakumGenerate : DefaultTask(), RequiresNpmDependencies {
@get:Inject
abstract val layout: ProjectLayout

@get:Inject
abstract val workerExecutor: WorkerExecutor

@get:ServiceReference
abstract val ktlintService: Property<KtLintService>
sgrishchenko marked this conversation as resolved.
Show resolved Hide resolved

@get:InputFile
abstract val configFile: RegularFileProperty

Expand Down Expand Up @@ -71,6 +87,18 @@ abstract class KarakumGenerate : DefaultTask(), RequiresNpmDependencies {
}
}

@get:InputFiles
@get:Optional
val editorConfigFiles = destinationDirectory.map { destinationDirectory ->
ResourcePropertiesService
.builder()
.build()
.queryProperties(Resources.ofPath(destinationDirectory.asFile.absoluteFile.toPath(), UTF_8))
.editorConfigFiles
.map { it.getAdapter(Path::class.java) }
.let { layout.files(it) }
}

@TaskAction
fun generate() {
exec.exec {
Expand All @@ -80,5 +108,12 @@ abstract class KarakumGenerate : DefaultTask(), RequiresNpmDependencies {
args = listOf("--config", configFile.get().asFile.absolutePath)
)
}

logger.lifecycle("Formatting generated files")
destinationDirectory.get().asFileTree.forEach { file ->
workerExecutor.noIsolation().submit(KtLintFormatWorker::class) {
this.file.set(file)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package io.github.sgrishchenko.karakum.gradle.plugin.worker

import com.pinterest.ktlint.rule.engine.api.Code
import com.pinterest.ktlint.rule.engine.core.api.AutocorrectDecision.ALLOW_AUTOCORRECT
import com.pinterest.ktlint.rule.engine.core.api.AutocorrectDecision.NO_AUTOCORRECT
import io.github.sgrishchenko.karakum.gradle.plugin.service.KtLintService
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.logging.Logging
import org.gradle.api.provider.Property
import org.gradle.api.services.ServiceReference
import org.gradle.workers.WorkAction
import org.gradle.workers.WorkParameters

abstract class KtLintFormatWorker : WorkAction<KtLintFormatWorker.Parameters> {
private val logger = Logging.getLogger(KtLintFormatWorker::class.java)

@get:ServiceReference
abstract val ktlintService: Property<KtLintService>

override fun execute() {
val file = parameters.file.get().asFile
logger.info("Formatting ${file.absolutePath}")
runCatching {
ktlintService
.get()
.ktlint
.format(Code.fromFile(file)) { lintError ->
if (lintError.canBeAutoCorrected) ALLOW_AUTOCORRECT else NO_AUTOCORRECT
}.also(file::writeText)
}.onFailure {
logger.info("Formatting failed for ${file.absolutePath}")
logger.info(it.stackTraceToString())
}.onSuccess {
logger.info("Formatting successful for ${file.absolutePath}")
}
}

interface Parameters : WorkParameters {
val file: RegularFileProperty
}
}
6 changes: 6 additions & 0 deletions gradle-plugin/settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ dependencyResolutionManagement {
val libs by creating {
val jacksonVersion: String by settings
library("jackson-databind", "com.fasterxml.jackson.core", "jackson-databind").version(jacksonVersion)
val ktlintVersion: String by settings
library("ktlint-ruleEngine", "com.pinterest.ktlint", "ktlint-rule-engine").version(ktlintVersion)
library("ktlint-ruleEngine-core", "com.pinterest.ktlint", "ktlint-rule-engine-core").version(ktlintVersion)
sgrishchenko marked this conversation as resolved.
Show resolved Hide resolved
library("ktlint-ruleset-standard", "com.pinterest.ktlint", "ktlint-ruleset-standard").version(ktlintVersion)
val ec4jVersion: String by settings
library("ec4j", "org.ec4j.core", "ec4j-core").version(ec4jVersion)
}
}
}
Expand Down
Loading