[K/N] Add clangFormat task for automatic patch formatting ^KT-53776

Merge-request: KT-MR-7880
Merged-by: Alexander Shabalin <Alexander.Shabalin@jetbrains.com>
This commit is contained in:
Alexander Shabalin
2022-12-07 14:46:55 +00:00
committed by Space Team
parent 5c9aa88617
commit 314edd7066
6 changed files with 128 additions and 9 deletions
@@ -12,13 +12,11 @@ import org.gradle.process.ExecOperations
import org.gradle.process.ExecResult
import org.gradle.process.ExecSpec
import org.jetbrains.kotlin.konan.target.PlatformManager
import org.jetbrains.kotlin.konan.util.DependencyProcessor
fun execLlvmUtility(project: Project, utility: String, action: Action<in ExecSpec>): ExecResult {
val llvmBinDirectory = "${project.platformManager.hostPlatform.absoluteLlvmHome}/bin"
return project.exec(Action<ExecSpec> {
action.execute(this)
executable = "$llvmBinDirectory/$utility"
executable = project.platformManager.resolveLlvmUtility(utility)
})
}
@@ -26,10 +24,11 @@ fun execLlvmUtility(project: Project, utility: String, closure: Closure<in ExecS
return execLlvmUtility(project, utility) { project.configure(this, closure) }
}
fun PlatformManager.resolveLlvmUtility(utility: String) = "${hostPlatform.absoluteLlvmHome}/bin/$utility"
fun ExecOperations.execLlvmUtility(platformManager: PlatformManager, utility: String, action: Action<in ExecSpec>): ExecResult {
val llvmBinDirectory = "${platformManager.hostPlatform.absoluteLlvmHome}/bin"
return exec {
action.execute(this)
executable = "$llvmBinDirectory/$utility"
executable = platformManager.resolveLlvmUtility(utility)
}
}
@@ -16,10 +16,7 @@ import org.gradle.api.services.BuildServiceParameters
import org.gradle.kotlin.dsl.*
import org.gradle.language.base.plugins.LifecycleBasePlugin
import org.jetbrains.kotlin.ExecClang
import org.jetbrains.kotlin.cpp.CompilationDatabaseExtension
import org.jetbrains.kotlin.cpp.CompilationDatabasePlugin
import org.jetbrains.kotlin.cpp.CompileToExecutable
import org.jetbrains.kotlin.cpp.RunGTest
import org.jetbrains.kotlin.cpp.*
import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.konan.target.PlatformManager
import org.jetbrains.kotlin.konan.target.SanitizerKind
@@ -68,6 +65,7 @@ private abstract class CompileTestsSemaphore : BuildService<BuildServiceParamete
open class CompileToBitcodePlugin : Plugin<Project> {
override fun apply(target: Project) {
target.apply<CompilationDatabasePlugin>()
target.apply<GitClangFormatPlugin>()
target.extensions.create<CompileToBitcodeExtension>(EXTENSION_NAME, target)
}
@@ -0,0 +1,84 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.cpp
import org.gradle.api.DefaultTask
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.UntrackedTask
import org.gradle.api.tasks.options.Option
import org.gradle.kotlin.dsl.getByType
import org.gradle.process.ExecOperations
import org.jetbrains.kotlin.konan.target.PlatformManager
import org.jetbrains.kotlin.resolveLlvmUtility
import java.io.ByteArrayOutputStream
import javax.inject.Inject
/**
* A task that formats changed code with clang-format.
*
* Will run <git-clang-format> --binary <clang-format> --force $(git merge-base [parent] HEAD) [directory]
*/
@UntrackedTask(because = "Formatter should always run when asked")
abstract class GitClangFormat : DefaultTask() {
private val platformManager = project.extensions.getByType<PlatformManager>()
/**
* Parent branch for the current branch.
*/
@get:Option(option = "parent", description = "base parent of the branch; by default origin/master")
@get:Input
abstract val parent: Property<String>
/**
* Directory in which to format sources.
*/
@get:Option(option = "directory", description = "directory in which to format sources; by default project's source directory")
@get:Input
abstract val directory: Property<String>
/**
* Whether to run the tool in interactive mode.
*/
@get:Option(option = "interactive", description = "interactively ask about each change before applying; by default false")
@get:Input
abstract val interactive: Property<Boolean>
@get:Inject
protected abstract val execOperations: ExecOperations
@TaskAction
fun run() {
val gitClangFormat = platformManager.resolveLlvmUtility("git-clang-format")
val clangFormat = platformManager.resolveLlvmUtility("clang-format")
val parent = this.parent.get()
val directory = this.directory.get()
val interactive = this.interactive.get()
val commit = ByteArrayOutputStream().let {
execOperations.exec {
executable = "git"
args("merge-base", parent, "HEAD")
standardOutput = it
}
it.toString().trim()
}
execOperations.exec {
executable = gitClangFormat
args("--binary", clangFormat)
args("--force")
if (interactive) {
args("--patch")
// Not a nice experience, but it works.
standardInput = System.`in`
}
args(commit)
args("--")
args(directory)
}
}
}
@@ -0,0 +1,34 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.cpp
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.*
/**
* Plugin for [GitClangFormat] that creates a task `clangFormat` that will format project sources in the current branch.
*/
open class GitClangFormatPlugin : Plugin<Project> {
override fun apply(target: Project) {
val directory = target.layout.projectDirectory.toString()
target.tasks.register<GitClangFormat>("clangFormat") {
description = "Run clang-format in $directory"
group = TASK_GROUP
parent.convention("origin/master")
this.directory.convention(directory)
interactive.convention(false)
// Needs LLVM toolchain.
// TODO: It does not need every dependency ever, only LLVM toolchain for the host.
dependsOn(":kotlin-native:dependencies:update")
}
}
companion object {
@JvmStatic
val TASK_GROUP = "development support"
}
}