Pass arguments to GradleKotlinCompilerWork in GradleKotlinCompilerWorkArguments

It's less error prone to add/remove/reorder arguments this way,
because named arguments can be used and the compiler actually
checks that all arguments are passed to GradleKotlinCompilerWorkArguments's
constructor.
This commit is contained in:
Alexey Tsvetkov
2018-11-01 19:29:05 +03:00
parent 349386960e
commit ff81a46233
4 changed files with 57 additions and 65 deletions
@@ -9,33 +9,16 @@ import org.gradle.api.Project
import org.gradle.workers.ForkMode import org.gradle.workers.ForkMode
import org.gradle.workers.IsolationMode import org.gradle.workers.IsolationMode
import org.gradle.workers.WorkerExecutor import org.gradle.workers.WorkerExecutor
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.gradle.utils.SerializableOptional
internal class GradleCompilerRunnerWithWorkers( internal class GradleCompilerRunnerWithWorkers(
project: Project, project: Project,
private val workersExecutor: WorkerExecutor private val workersExecutor: WorkerExecutor
) : GradleCompilerRunner(project) { ) : GradleCompilerRunner(project) {
override fun compileWithDaemonOrFallback( override fun compileWithDaemonOrFallback(workArgs: GradleKotlinCompilerWorkArguments) {
compilerClassName: String, workersExecutor.submit(GradleKotlinCompilerWork::class.java) { config ->
compilerArgs: CommonCompilerArguments,
environment: GradleCompilerEnvironment
) {
val icEnv = environment.incrementalCompilationEnvironment
val modulesInfo = icEnv?.let { buildModulesInfo(project.gradle) }
workersExecutor.submit(KotlinCompilerRunnable::class.java) { config ->
config.isolationMode = IsolationMode.NONE config.isolationMode = IsolationMode.NONE
config.forkMode = ForkMode.NEVER config.forkMode = ForkMode.NEVER
config.params( config.params(workArgs)
ProjectFilesForCompilation(project),
environment.compilerFullClasspath,
compilerClassName,
ArgumentUtils.convertArgumentsToStringList(compilerArgs).toTypedArray(),
compilerArgs.verbose,
SerializableOptional(icEnv),
SerializableOptional(modulesInfo)
)
} }
} }
@@ -30,7 +30,6 @@ import org.jetbrains.kotlin.daemon.client.CompileServiceSession
import org.jetbrains.kotlin.daemon.common.* import org.jetbrains.kotlin.daemon.common.*
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
import org.jetbrains.kotlin.gradle.tasks.* import org.jetbrains.kotlin.gradle.tasks.*
import org.jetbrains.kotlin.gradle.utils.SerializableOptional
import org.jetbrains.kotlin.gradle.utils.newTmpFile import org.jetbrains.kotlin.gradle.utils.newTmpFile
import org.jetbrains.kotlin.gradle.utils.relativeToRoot import org.jetbrains.kotlin.gradle.utils.relativeToRoot
import org.jetbrains.kotlin.incremental.* import org.jetbrains.kotlin.incremental.*
@@ -117,23 +116,23 @@ internal open class GradleCompilerRunner(protected val project: Project) {
) )
compilerArgs.version = false compilerArgs.version = false
} }
compileWithDaemonOrFallback(compilerClassName, compilerArgs, environment) val argsArray = ArgumentUtils.convertArgumentsToStringList(compilerArgs).toTypedArray()
} val incrementalCompilationEnvironment = environment.incrementalCompilationEnvironment
val modulesInfo = incrementalCompilationEnvironment?.let { buildModulesInfo(project.gradle) }
protected open fun compileWithDaemonOrFallback( val workArgs = GradleKotlinCompilerWorkArguments(
compilerClassName: String,
compilerArgs: CommonCompilerArguments,
environment: GradleCompilerEnvironment
) {
val kotlinCompilerRunnable = KotlinCompilerRunnable(
projectFiles = ProjectFilesForCompilation(project), projectFiles = ProjectFilesForCompilation(project),
compilerFullClasspath = environment.compilerFullClasspath, compilerFullClasspath = environment.compilerFullClasspath,
compilerClassName = compilerClassName, compilerClassName = compilerClassName,
compilerArgs = ArgumentUtils.convertArgumentsToStringList(compilerArgs).toTypedArray(), compilerArgs = argsArray,
isVerbose = compilerArgs.verbose, isVerbose = compilerArgs.verbose,
incrementalCompilationEnvironment = SerializableOptional(environment.incrementalCompilationEnvironment), incrementalCompilationEnvironment = incrementalCompilationEnvironment,
incrementalModuleInfo = SerializableOptional(buildModulesInfo(project.gradle)) incrementalModuleInfo = modulesInfo
) )
compileWithDaemonOrFallback(workArgs)
}
protected open fun compileWithDaemonOrFallback(workArgs: GradleKotlinCompilerWorkArguments) {
val kotlinCompilerRunnable = GradleKotlinCompilerWork(workArgs)
kotlinCompilerRunnable.run() kotlinCompilerRunnable.run()
} }
@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.daemon.common.*
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
import org.jetbrains.kotlin.gradle.tasks.GradleMessageCollector import org.jetbrains.kotlin.gradle.tasks.GradleMessageCollector
import org.jetbrains.kotlin.gradle.tasks.throwGradleExceptionIfError import org.jetbrains.kotlin.gradle.tasks.throwGradleExceptionIfError
import org.jetbrains.kotlin.gradle.utils.SerializableOptional
import org.jetbrains.kotlin.incremental.ChangedFiles import org.jetbrains.kotlin.incremental.ChangedFiles
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
@@ -43,21 +42,46 @@ internal class ProjectFilesForCompilation(
} }
} }
internal class KotlinCompilerRunnable @Inject constructor( internal class GradleKotlinCompilerWorkArguments(
private val projectFiles: ProjectFilesForCompilation, val projectFiles: ProjectFilesForCompilation,
private val compilerFullClasspath: List<File>, val compilerFullClasspath: List<File>,
private val compilerClassName: String, val compilerClassName: String,
private val compilerArgs: Array<String>, val compilerArgs: Array<String>,
private val isVerbose: Boolean, val isVerbose: Boolean,
private val incrementalCompilationEnvironment: SerializableOptional<IncrementalCompilationEnvironment>, val incrementalCompilationEnvironment: IncrementalCompilationEnvironment?,
private val incrementalModuleInfo: SerializableOptional<IncrementalModuleInfo> val incrementalModuleInfo: IncrementalModuleInfo?
) : Serializable {
companion object {
const val serialVersionUID: Long = 0
}
}
internal class GradleKotlinCompilerWork @Inject constructor(
/**
* Arguments are passed through [GradleKotlinCompilerWorkArguments],
* because Gradle Workers API does not support nullable arguments (https://github.com/gradle/gradle/issues/2405),
* and because Workers API does not support named arguments,
* which are useful when there are many arguments with the same type
* (to protect against parameters reordering bugs)
*/
config: GradleKotlinCompilerWorkArguments
) : Runnable { ) : Runnable {
private val projectRootFile = config.projectFiles.projectRootFile
private val clientIsAliveFlagFile = config.projectFiles.clientIsAliveFlagFile
private val sessionFlagFile = config.projectFiles.sessionFlagFile
private val compilerFullClasspath = config.compilerFullClasspath
private val compilerClassName = config.compilerClassName
private val compilerArgs = config.compilerArgs
private val isVerbose = config.isVerbose
private val incrementalCompilationEnvironment = config.incrementalCompilationEnvironment
private val incrementalModuleInfo = config.incrementalModuleInfo
private val log: KotlinLogger = private val log: KotlinLogger =
SL4JKotlinLogger(LoggerFactory.getLogger("KotlinCompilerRunnable")) SL4JKotlinLogger(LoggerFactory.getLogger("GradleKotlinCompilerWork"))
private val messageCollector = GradleMessageCollector(log) private val messageCollector = GradleMessageCollector(log)
private val isIncremental: Boolean private val isIncremental: Boolean
get() = incrementalCompilationEnvironment.value != null get() = incrementalCompilationEnvironment != null
override fun run() { override fun run() {
val exitCode = compileWithDaemonOrFallbackImpl() val exitCode = compileWithDaemonOrFallbackImpl()
@@ -66,8 +90,8 @@ internal class KotlinCompilerRunnable @Inject constructor(
private fun compileWithDaemonOrFallbackImpl(): ExitCode { private fun compileWithDaemonOrFallbackImpl(): ExitCode {
with(log) { with(log) {
kotlinDebug { "Kotlin compiler class: $compilerClassName" } kotlinDebug { "Kotlin compiler class: ${compilerClassName}" }
kotlinDebug { "Kotlin compiler classpath: ${compilerFullClasspath.map { it.canonicalPath }.joinToString()}" } kotlinDebug { "Kotlin compiler classpath: ${compilerFullClasspath.joinToString { it.canonicalPath }}" }
kotlinDebug { "Kotlin compiler args: ${compilerArgs.joinToString(" ")}" } kotlinDebug { "Kotlin compiler args: ${compilerArgs.joinToString(" ")}" }
} }
@@ -94,8 +118,8 @@ internal class KotlinCompilerRunnable @Inject constructor(
val connection = val connection =
try { try {
GradleCompilerRunner.getDaemonConnectionImpl( GradleCompilerRunner.getDaemonConnectionImpl(
projectFiles.clientIsAliveFlagFile, clientIsAliveFlagFile,
projectFiles.sessionFlagFile, sessionFlagFile,
compilerFullClasspath, compilerFullClasspath,
messageCollector, messageCollector,
log.isDebugEnabled log.isDebugEnabled
@@ -166,7 +190,7 @@ internal class KotlinCompilerRunnable @Inject constructor(
sessionId: Int, sessionId: Int,
targetPlatform: CompileService.TargetPlatform targetPlatform: CompileService.TargetPlatform
): CompileService.CallResult<Int> { ): CompileService.CallResult<Int> {
val icEnv = incrementalCompilationEnvironment.value ?: error("incrementalCompilationEnvironment is null!") val icEnv = incrementalCompilationEnvironment ?: error("incrementalCompilationEnvironment is null!")
val knownChangedFiles = icEnv.changedFiles as? ChangedFiles.Known val knownChangedFiles = icEnv.changedFiles as? ChangedFiles.Known
val compilationOptions = IncrementalCompilationOptions( val compilationOptions = IncrementalCompilationOptions(
@@ -182,12 +206,12 @@ internal class KotlinCompilerRunnable @Inject constructor(
usePreciseJavaTracking = icEnv.usePreciseJavaTracking, usePreciseJavaTracking = icEnv.usePreciseJavaTracking,
localStateDirs = icEnv.localStateDirs, localStateDirs = icEnv.localStateDirs,
multiModuleICSettings = icEnv.multiModuleICSettings, multiModuleICSettings = icEnv.multiModuleICSettings,
modulesInfo = incrementalModuleInfo.value!! modulesInfo = incrementalModuleInfo!!
) )
log.info("Options for KOTLIN DAEMON: $compilationOptions") log.info("Options for KOTLIN DAEMON: $compilationOptions")
val servicesFacade = GradleIncrementalCompilerServicesFacadeImpl(log, messageCollector) val servicesFacade = GradleIncrementalCompilerServicesFacadeImpl(log, messageCollector)
val compilationResults = GradleCompilationResults(log, projectFiles.projectRootFile) val compilationResults = GradleCompilationResults(log, projectRootFile)
return daemon.compile(sessionId, compilerArgs, compilationOptions, servicesFacade, compilationResults) return daemon.compile(sessionId, compilerArgs, compilationOptions, servicesFacade, compilationResults)
} }
@@ -1,14 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. 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.gradle.utils
import java.io.Serializable
internal class SerializableOptional<T>(val value: T?) : Serializable {
companion object {
const val serialVersionUID: Long = 0
}
}