.kotlin.kotlin-compiler-client-embeddable.2.1.0-RC2.source-code.daemonProblemReportingOutputListener.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-compiler-client-embeddable Show documentation
Show all versions of kotlin-compiler-client-embeddable Show documentation
Kotlin compiler client embeddable
The newest version!
/*
* Copyright 2010-2024 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.daemon.client
import org.jetbrains.kotlin.daemon.common.COMPILE_DAEMON_IS_READY_MESSAGE
import java.util.concurrent.atomic.AtomicBoolean
internal interface DaemonProblemReportingOutputListener {
fun onOutputLine(line: String)
fun retrieveProblems(): List
}
internal fun CompositeDaemonErrorReportingOutputListener(vararg listeners: DaemonProblemReportingOutputListener) =
CompositeErrorReportingOutputListener(listeners.toList())
internal class CompositeErrorReportingOutputListener(private val listeners: List) :
DaemonProblemReportingOutputListener {
override fun onOutputLine(line: String) {
listeners.forEach { it.onOutputLine(line) }
}
override fun retrieveProblems(): List {
return listeners.flatMap { it.retrieveProblems() }
}
}
/**
* Holds the last [LIMIT] lines of the daemon process standard output to be able to print them in the case of problems with the daemon.
*/
internal class DaemonLastOutputLinesListener : DaemonProblemReportingOutputListener {
private val lastPrintedLines: MutableList = LimitedLinkedList(LIMIT)
private var totalCount = 0
override fun onOutputLine(line: String) {
lastPrintedLines.add(line)
totalCount++
}
private fun calculateAbsoluteIndex(relativeIndex: Int) = totalCount - lastPrintedLines.size + relativeIndex
private val ellipsisIfRequired
get() = if (totalCount > LIMIT) " ".repeat(OUTPUT_INDENT) + "... (${totalCount - LIMIT} more lines)${System.lineSeparator()}" else ""
override fun retrieveProblems(): List {
val retrievedOutputs = (lastPrintedLines
.takeIf { it.isNotEmpty() }
?.withIndex()
?.joinToString(
System.lineSeparator(),
prefix = "The daemon process output:${System.lineSeparator()}$ellipsisIfRequired",
) { (index, line) -> " ".repeat(OUTPUT_INDENT) + "${calculateAbsoluteIndex(index) + 1}. $line" }
?: (" ".repeat(OUTPUT_INDENT) + "The daemon process produced no output"))
return listOf(retrievedOutputs)
}
companion object {
private const val LIMIT = 10
private const val OUTPUT_INDENT = 4
}
}
internal class DaemonGcAutoConfigurationProblemsListener(
private val gcAutoConfiguration: KotlinCompilerClient.GcAutoConfiguration,
private val startupAttempt: Int,
) :
DaemonProblemReportingOutputListener {
private var hasGcSelectionProblems = false
override fun onOutputLine(line: String) {
if (!gcAutoConfiguration.shouldAutoConfigureGc) return
if (line.contains("Multiple garbage collectors selected") || line.contains("Conflicting collector combinations in option list")) {
hasGcSelectionProblems = true
gcAutoConfiguration.shouldAutoConfigureGc = false
}
}
override fun retrieveProblems(): List {
val shouldReport = when {
hasGcSelectionProblems -> true
gcAutoConfiguration.shouldAutoConfigureGc && startupAttempt >= 1 -> {
gcAutoConfiguration.shouldAutoConfigureGc = false
true
}
else -> false
}
if (!shouldReport) return emptyList()
return listOf(
"Problems may have occurred during auto-selection of GC. The preferred GC is ${gcAutoConfiguration.preferredGc} GC.",
"If the problems persist, try adding the JVM option to the Kotlin daemon JVM arguments: -XX:-Use${gcAutoConfiguration.preferredGc}GC.",
"GC auto-selection logic is disabled temporary for the next daemon startup.",
)
}
}
internal class DaemonInitMessageListener : DaemonProblemReportingOutputListener {
var caughtInitMessage = false
private set
override fun onOutputLine(line: String) {
if (caughtInitMessage) return
if (line == COMPILE_DAEMON_IS_READY_MESSAGE) {
caughtInitMessage = true
}
}
override fun retrieveProblems(): List {
if (caughtInitMessage) return emptyList()
return listOf(
"The daemon didn't produce the message \"$COMPILE_DAEMON_IS_READY_MESSAGE\" during startup.",
)
}
}