Update daemon client with wrappers for basic compiler API

Other changes to extract results for compiler, tests.
This commit is contained in:
Ilya Chernikov
2017-01-16 16:49:30 +01:00
parent afd0655776
commit ec7e8873f4
10 changed files with 356 additions and 64 deletions
@@ -0,0 +1,100 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.daemon.client
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
import org.jetbrains.kotlin.daemon.common.*
import java.io.Serializable
import java.io.File
import java.rmi.server.UnicastRemoteObject
open class BasicCompilerServicesWithResultsFacadeServer(
val messageCollector: MessageCollector,
val outputsCollector: ((File, List<File>) -> Unit)? = null,
port: Int = SOCKET_ANY_FREE_PORT
) : CompilerServicesFacadeBase,
UnicastRemoteObject(port, LoopbackNetworkInterface.clientLoopbackSocketFactory, LoopbackNetworkInterface.serverLoopbackSocketFactory)
{
override fun report(category: Int, severity: Int, message: String?, attachment: Serializable?) {
messageCollector.reportFromDaemon(outputsCollector, category, severity, message, attachment)
}
}
fun MessageCollector.reportFromDaemon(outputsCollector: ((File, List<File>) -> Unit)?, category: Int, severity: Int, message: String?, attachment: Serializable?) {
val reportCategory = ReportCategory.fromCode(category)
when (reportCategory) {
ReportCategory.OUTPUT_MESSAGE -> {
if (outputsCollector != null) {
OutputMessageUtil.parseOutputMessage(message.orEmpty())?.let { outs ->
outs.outputFile?.let {
outputsCollector.invoke(it, outs.sourceFiles.toList())
}
}
}
report(CompilerMessageSeverity.OUTPUT, message!!, CompilerMessageLocation.NO_LOCATION)
}
ReportCategory.EXCEPTION -> {
report(CompilerMessageSeverity.EXCEPTION, message.orEmpty(), CompilerMessageLocation.NO_LOCATION)
}
ReportCategory.COMPILER_MESSAGE -> {
val compilerSeverity = when (ReportSeverity.fromCode(severity)) {
ReportSeverity.ERROR -> CompilerMessageSeverity.ERROR
ReportSeverity.WARNING -> CompilerMessageSeverity.WARNING
ReportSeverity.INFO -> CompilerMessageSeverity.INFO
ReportSeverity.DEBUG -> CompilerMessageSeverity.LOGGING
else -> throw IllegalStateException("Unexpected compiler message report severity $severity")
}
if (message != null && attachment is CompilerMessageLocation) {
report(compilerSeverity, message, attachment)
}
else {
reportUnexpected(category, severity, message, attachment)
}
}
ReportCategory.DAEMON_MESSAGE,
ReportCategory.IC_MESSAGE -> {
if (message != null) {
report(CompilerMessageSeverity.LOGGING, message, CompilerMessageLocation.NO_LOCATION)
}
else {
reportUnexpected(category, severity, message, attachment)
}
}
else -> {
reportUnexpected(category, severity, message, attachment)
}
}
}
private fun MessageCollector.reportUnexpected(category: Int, severity: Int, message: String?, attachment: Serializable?) {
val compilerMessageSeverity = when (ReportSeverity.fromCode(severity)) {
ReportSeverity.ERROR -> CompilerMessageSeverity.ERROR
ReportSeverity.WARNING -> CompilerMessageSeverity.WARNING
ReportSeverity.INFO -> CompilerMessageSeverity.INFO
else -> CompilerMessageSeverity.LOGGING
}
report(compilerMessageSeverity,
"Unexpected message: category=$category; severity=$severity; message='$message'; attachment=$attachment",
CompilerMessageLocation.NO_LOCATION)
}
@@ -18,6 +18,9 @@ package org.jetbrains.kotlin.daemon.client
import net.rubygrapefruit.platform.Native
import net.rubygrapefruit.platform.ProcessLauncher
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.daemon.common.*
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
@@ -141,6 +144,32 @@ object KotlinCompilerClient {
operationsTracer).get()
}
fun compile(compilerService: CompileService,
sessionId: Int,
targetPlatform: CompileService.TargetPlatform,
args: Array<out String>,
messageCollector: MessageCollector,
outputsCollector: ((File, List<File>) -> Unit)? = null,
compilerMode: CompilerMode = CompilerMode.NON_INCREMENTAL_COMPILER,
reportSeverity: ReportSeverity = ReportSeverity.INFO,
port: Int = SOCKET_ANY_FREE_PORT,
profiler: Profiler = DummyProfiler()
): Int = profiler.withMeasure(this) {
val services = BasicCompilerServicesWithResultsFacadeServer(messageCollector, outputsCollector, port)
compilerService.compile(
sessionId,
args,
CompilationOptions(
compilerMode,
targetPlatform,
arrayOf(ReportCategory.COMPILER_MESSAGE.code, ReportCategory.DAEMON_MESSAGE.code, ReportCategory.EXCEPTION.code, ReportCategory.OUTPUT_MESSAGE.code),
reportSeverity.code,
emptyArray()),
services,
null
).get()
}
val COMPILE_DAEMON_CLIENT_OPTIONS_PROPERTY: String = "kotlin.daemon.client.options"
data class ClientOptions(
var stop: Boolean = false
@@ -245,9 +274,22 @@ object KotlinCompilerClient {
if (category == DaemonReportCategory.DEBUG && !verboseReporting) return
out?.println("[$source] ${category.name}: $message")
messages?.add(DaemonReportMessage(category, "[$source] $message"))
messageCollector?.let {
when (category) {
DaemonReportCategory.DEBUG -> it.report(CompilerMessageSeverity.LOGGING, message, CompilerMessageLocation.NO_LOCATION)
DaemonReportCategory.INFO -> it.report(CompilerMessageSeverity.INFO, message, CompilerMessageLocation.NO_LOCATION)
DaemonReportCategory.EXCEPTION -> it.report(CompilerMessageSeverity.EXCEPTION, message, CompilerMessageLocation.NO_LOCATION)
}
}
compilerServices?.let {
when (category) {
DaemonReportCategory.DEBUG -> it.report(ReportCategory.DAEMON_MESSAGE, ReportSeverity.DEBUG, message, source)
DaemonReportCategory.INFO -> it.report(ReportCategory.DAEMON_MESSAGE, ReportSeverity.INFO, message, source)
DaemonReportCategory.EXCEPTION -> it.report(ReportCategory.EXCEPTION, ReportSeverity.ERROR, message, source)
}
}
}
private fun tryFindSuitableDaemonOrNewOpts(registryDir: File, compilerId: CompilerId, daemonJVMOptions: DaemonJVMOptions, report: (DaemonReportCategory, String) -> Unit): Pair<CompileService?, DaemonJVMOptions> {
val aliveWithOpts = walkDaemons(registryDir, compilerId, report = report)
.map { Pair(it, it.getDaemonJVMOptions()) }
@@ -337,7 +379,10 @@ object KotlinCompilerClient {
data class DaemonReportMessage(val category: DaemonReportCategory, val message: String)
class DaemonReportingTargets(val out: PrintStream? = null, val messages: MutableCollection<DaemonReportMessage>? = null)
class DaemonReportingTargets(val out: PrintStream? = null,
val messages: MutableCollection<DaemonReportMessage>? = null,
val messageCollector: MessageCollector? = null,
val compilerServices: CompilerServicesFacadeBase? = null)
internal fun isProcessAlive(process: Process) =