From e01c2bc651468b4545907a646116a856da2c2d3c Mon Sep 17 00:00:00 2001 From: Hung Nguyen Date: Thu, 16 Jun 2022 15:56:41 +0100 Subject: [PATCH] Warn in Gradle log when incremental compilation fails When incremental compilation fails, we currently log it at the `debug` level (and fall back to non-incremental compilation). This commit will change it to `warning` so that we can get more user reports, which will allow us to fix the root cause. Also make sure the warning includes a stack trace. Additionally, let ReportSeverity.fromCode() return a non-null value or throw an exception otherwise as that case is not expected. ^KT-52839 In Progress --- .../kotlin/build/report/ICReporter.kt | 18 +++-- ...CompilerServicesWithResultsFacadeServer.kt | 3 +- .../common/CompilerServicesFacadeBase.kt | 5 +- .../report/BuildReportICReporterTest.kt | 51 +++++++++++++ .../report/DebugMessagesICReporterTest.kt | 71 +++++++++++++++++++ .../testfixtures/FakeCompilationResults.kt | 21 ++++++ .../FakeCompilerServicesFacadeBase.kt | 23 ++++++ .../daemon/report/BuildReportICReporter.kt | 21 +++--- .../report/CompileIterationICReporter.kt | 10 ++- .../daemon/report/CompositeICReporter.kt | 9 +-- .../daemon/report/DaemonMessageReporter.kt | 2 +- .../daemon/report/DebugMessagesICReporter.kt | 38 ++++++---- .../DaemonMessageReporterAsync.kt | 2 +- .../report/experimental/RemoteICReporter.kt | 45 ++++++------ .../kotlin/daemon/report/getICReporter.kt | 52 +++++++++++++- .../incremental/IncrementalCompilerRunner.kt | 11 +-- .../ClasspathSnapshotBuildReporter.kt | 4 +- .../incremental/utils/TestICReporter.kt | 6 +- .../kotlin/jps/build/KotlinBuilder.kt | 19 +++-- ...leIncrementalCompilerServicesFacadeImpl.kt | 12 +++- .../GradleKotlinCompilerWork.kt | 4 +- .../gradle/logging/gradleLoggingUtils.kt | 18 +++-- .../maven/incremental/MavenICReporter.java | 31 ++++---- 23 files changed, 358 insertions(+), 118 deletions(-) create mode 100644 compiler/daemon/daemon-tests/test/org/jetbrains/kotlin/daemon/report/BuildReportICReporterTest.kt create mode 100644 compiler/daemon/daemon-tests/test/org/jetbrains/kotlin/daemon/report/DebugMessagesICReporterTest.kt create mode 100644 compiler/daemon/daemon-tests/test/org/jetbrains/kotlin/daemon/testfixtures/FakeCompilationResults.kt create mode 100644 compiler/daemon/daemon-tests/test/org/jetbrains/kotlin/daemon/testfixtures/FakeCompilerServicesFacadeBase.kt diff --git a/build-common/src/org/jetbrains/kotlin/build/report/ICReporter.kt b/build-common/src/org/jetbrains/kotlin/build/report/ICReporter.kt index 34467edf1d3..db7c869984e 100644 --- a/build-common/src/org/jetbrains/kotlin/build/report/ICReporter.kt +++ b/build-common/src/org/jetbrains/kotlin/build/report/ICReporter.kt @@ -9,8 +9,19 @@ import org.jetbrains.kotlin.cli.common.ExitCode import java.io.File interface ICReporter { - fun report(message: () -> String) - fun reportVerbose(message: () -> String) + + enum class ReportSeverity(val level: Int) { + WARNING(3), + INFO(2), + DEBUG(1); + } + + fun report(message: () -> String, severity: ReportSeverity) + + // TODO: Move these 3 functions outside of this interface and make them extension functions so they can't be overridden + fun warn(message: () -> String) = report(message, severity = ReportSeverity.WARNING) + fun report(message: () -> String) = report(message, severity = ReportSeverity.INFO) + fun reportVerbose(message: () -> String) = report(message, severity = ReportSeverity.DEBUG) fun reportCompileIteration(incremental: Boolean, sourceFiles: Collection, exitCode: ExitCode) fun reportMarkDirtyClass(affectedFiles: Iterable, classFqName: String) @@ -19,8 +30,7 @@ interface ICReporter { } object DoNothingICReporter : ICReporter { - override fun report(message: () -> String) {} - override fun reportVerbose(message: () -> String) {} + override fun report(message: () -> String, severity: ICReporter.ReportSeverity) {} override fun reportCompileIteration(incremental: Boolean, sourceFiles: Collection, exitCode: ExitCode) {} override fun reportMarkDirtyClass(affectedFiles: Iterable, classFqName: String) {} override fun reportMarkDirtyMember(affectedFiles: Iterable, scope: String, name: String) {} diff --git a/compiler/daemon/daemon-client/src/org/jetbrains/kotlin/daemon/client/BasicCompilerServicesWithResultsFacadeServer.kt b/compiler/daemon/daemon-client/src/org/jetbrains/kotlin/daemon/client/BasicCompilerServicesWithResultsFacadeServer.kt index 06a7418f14f..eba21060d0b 100644 --- a/compiler/daemon/daemon-client/src/org/jetbrains/kotlin/daemon/client/BasicCompilerServicesWithResultsFacadeServer.kt +++ b/compiler/daemon/daemon-client/src/org/jetbrains/kotlin/daemon/client/BasicCompilerServicesWithResultsFacadeServer.kt @@ -63,7 +63,6 @@ fun MessageCollector.reportFromDaemon(outputsCollector: ((File, List) -> U ReportSeverity.WARNING -> CompilerMessageSeverity.WARNING ReportSeverity.INFO -> CompilerMessageSeverity.INFO ReportSeverity.DEBUG -> CompilerMessageSeverity.LOGGING - else -> throw IllegalStateException("Unexpected compiler message report severity $severity") } if (message != null) { report(compilerSeverity, message, attachment as? CompilerMessageSourceLocation) @@ -92,7 +91,7 @@ private fun MessageCollector.reportUnexpected(category: Int, severity: Int, mess ReportSeverity.ERROR -> CompilerMessageSeverity.ERROR ReportSeverity.WARNING -> CompilerMessageSeverity.WARNING ReportSeverity.INFO -> CompilerMessageSeverity.INFO - else -> CompilerMessageSeverity.LOGGING + ReportSeverity.DEBUG -> CompilerMessageSeverity.LOGGING } report(compilerMessageSeverity, "Unexpected message: category=$category; severity=$severity; message='$message'; attachment=$attachment") diff --git a/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompilerServicesFacadeBase.kt b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompilerServicesFacadeBase.kt index 0e65caa0de6..c3777923878 100644 --- a/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompilerServicesFacadeBase.kt +++ b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompilerServicesFacadeBase.kt @@ -48,8 +48,9 @@ enum class ReportSeverity(val code: Int) { DEBUG(3); companion object { - fun fromCode(code: Int): ReportSeverity? = - ReportSeverity.values().firstOrNull { it.code == code } + fun fromCode(code: Int): ReportSeverity { + return values().firstOrNull { it.code == code } ?: error("Can't find a matching ReportSeverity with code = $code") + } } } diff --git a/compiler/daemon/daemon-tests/test/org/jetbrains/kotlin/daemon/report/BuildReportICReporterTest.kt b/compiler/daemon/daemon-tests/test/org/jetbrains/kotlin/daemon/report/BuildReportICReporterTest.kt new file mode 100644 index 00000000000..8b5e64aa1c4 --- /dev/null +++ b/compiler/daemon/daemon-tests/test/org/jetbrains/kotlin/daemon/report/BuildReportICReporterTest.kt @@ -0,0 +1,51 @@ +/* + * 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.daemon.report + +import org.jetbrains.kotlin.build.report.debug +import org.jetbrains.kotlin.build.report.info +import org.jetbrains.kotlin.build.report.warn +import org.jetbrains.kotlin.daemon.testfixtures.FakeCompilationResults +import org.junit.Test +import java.io.File +import kotlin.test.assertEquals + +class BuildReportICReporterTest { + + @Test + fun testVerboseMode() { + val compilationResults = FakeCompilationResults() + val reporter = BuildReportICReporter(compilationResults, File("unusedRootDir"), isVerbose = true) + reporter.warn { WARNING_MESSAGE } + reporter.info { INFO_MESSAGE } + reporter.debug { DEBUG_MESSAGE } + reporter.flush() + + assertEquals( + expected = listOf(WARNING_MESSAGE, INFO_MESSAGE, DEBUG_MESSAGE), + actual = compilationResults.results.single() as List<*> + ) + } + + @Test + fun testNonVerboseMode() { + val compilationResults = FakeCompilationResults() + val reporter = BuildReportICReporter(compilationResults, File("unusedRootDir"), isVerbose = false) + reporter.warn { WARNING_MESSAGE } + reporter.info { INFO_MESSAGE } + reporter.debug { DEBUG_MESSAGE } + reporter.flush() + + assertEquals( + expected = listOf(WARNING_MESSAGE, INFO_MESSAGE), + actual = compilationResults.results.single() as List<*> + ) + } +} + +internal const val WARNING_MESSAGE = "Warning message" +internal const val INFO_MESSAGE = "Info message" +internal const val DEBUG_MESSAGE = "Debug message" diff --git a/compiler/daemon/daemon-tests/test/org/jetbrains/kotlin/daemon/report/DebugMessagesICReporterTest.kt b/compiler/daemon/daemon-tests/test/org/jetbrains/kotlin/daemon/report/DebugMessagesICReporterTest.kt new file mode 100644 index 00000000000..e0e5709d629 --- /dev/null +++ b/compiler/daemon/daemon-tests/test/org/jetbrains/kotlin/daemon/report/DebugMessagesICReporterTest.kt @@ -0,0 +1,71 @@ +/* + * 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.daemon.report + +import org.jetbrains.kotlin.build.report.ICReporter +import org.jetbrains.kotlin.build.report.debug +import org.jetbrains.kotlin.build.report.info +import org.jetbrains.kotlin.build.report.warn +import org.jetbrains.kotlin.daemon.common.ReportCategory +import org.jetbrains.kotlin.daemon.common.ReportSeverity +import org.jetbrains.kotlin.daemon.testfixtures.FakeCompilerServicesFacadeBase +import org.junit.Test +import java.io.File +import kotlin.test.assertEquals + +class DebugMessagesICReporterTest { + + @Test + fun testWarningLevel() { + val compilerServices = FakeCompilerServicesFacadeBase() + val reporter = DebugMessagesICReporter(compilerServices, File("unusedRootDir"), ICReporter.ReportSeverity.WARNING) + reporter.warn { WARNING_MESSAGE } + reporter.info { INFO_MESSAGE } + reporter.debug { DEBUG_MESSAGE } + + assertEquals( + expected = mapOf( + WARNING_MESSAGE to Pair(ReportCategory.IC_MESSAGE, ReportSeverity.WARNING), + ), + actual = compilerServices.messages + ) + } + + @Test + fun testInfoLevel() { + val compilerServices = FakeCompilerServicesFacadeBase() + val reporter = DebugMessagesICReporter(compilerServices, File("unusedRootDir"), ICReporter.ReportSeverity.INFO) + reporter.warn { WARNING_MESSAGE } + reporter.info { INFO_MESSAGE } + reporter.debug { DEBUG_MESSAGE } + + assertEquals( + expected = mapOf( + WARNING_MESSAGE to Pair(ReportCategory.IC_MESSAGE, ReportSeverity.WARNING), + INFO_MESSAGE to Pair(ReportCategory.IC_MESSAGE, ReportSeverity.INFO), + ), + actual = compilerServices.messages + ) + } + + @Test + fun testDebugLevel() { + val compilerServices = FakeCompilerServicesFacadeBase() + val reporter = DebugMessagesICReporter(compilerServices, File("unusedRootDir"), ICReporter.ReportSeverity.DEBUG) + reporter.warn { WARNING_MESSAGE } + reporter.info { INFO_MESSAGE } + reporter.debug { DEBUG_MESSAGE } + + assertEquals( + mapOf( + WARNING_MESSAGE to Pair(ReportCategory.IC_MESSAGE, ReportSeverity.WARNING), + INFO_MESSAGE to Pair(ReportCategory.IC_MESSAGE, ReportSeverity.INFO), + DEBUG_MESSAGE to Pair(ReportCategory.IC_MESSAGE, ReportSeverity.DEBUG) + ), + actual = compilerServices.messages + ) + } +} diff --git a/compiler/daemon/daemon-tests/test/org/jetbrains/kotlin/daemon/testfixtures/FakeCompilationResults.kt b/compiler/daemon/daemon-tests/test/org/jetbrains/kotlin/daemon/testfixtures/FakeCompilationResults.kt new file mode 100644 index 00000000000..b0a8ddb2844 --- /dev/null +++ b/compiler/daemon/daemon-tests/test/org/jetbrains/kotlin/daemon/testfixtures/FakeCompilationResults.kt @@ -0,0 +1,21 @@ +/* + * 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.daemon.testfixtures + +import org.jetbrains.kotlin.daemon.common.CompilationResults +import java.io.Serializable + +class FakeCompilationResults : CompilationResults { + + val results: List + get() = resultList.toList() + + private val resultList = mutableListOf() + + override fun add(compilationResultCategory: Int, value: Serializable) { + resultList.add(value) + } +} diff --git a/compiler/daemon/daemon-tests/test/org/jetbrains/kotlin/daemon/testfixtures/FakeCompilerServicesFacadeBase.kt b/compiler/daemon/daemon-tests/test/org/jetbrains/kotlin/daemon/testfixtures/FakeCompilerServicesFacadeBase.kt new file mode 100644 index 00000000000..637f5e5dc10 --- /dev/null +++ b/compiler/daemon/daemon-tests/test/org/jetbrains/kotlin/daemon/testfixtures/FakeCompilerServicesFacadeBase.kt @@ -0,0 +1,23 @@ +/* + * 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.daemon.testfixtures + +import org.jetbrains.kotlin.daemon.common.CompilerServicesFacadeBase +import org.jetbrains.kotlin.daemon.common.ReportCategory +import org.jetbrains.kotlin.daemon.common.ReportSeverity +import java.io.Serializable + +class FakeCompilerServicesFacadeBase : CompilerServicesFacadeBase { + + val messages: Map> + get() = messageMap.toMap() + + private val messageMap = mutableMapOf>() + + override fun report(category: Int, severity: Int, message: String?, attachment: Serializable?) { + messageMap[message!!] = ReportCategory.fromCode(category)!! to ReportSeverity.fromCode(severity) + } +} diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/BuildReportICReporter.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/BuildReportICReporter.kt index e60c68fdeb0..c6e3e78efb6 100644 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/BuildReportICReporter.kt +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/BuildReportICReporter.kt @@ -5,16 +5,19 @@ package org.jetbrains.kotlin.daemon.report +import com.google.common.annotations.VisibleForTesting +import org.jetbrains.kotlin.build.report.ICReporter.ReportSeverity +import org.jetbrains.kotlin.build.report.ICReporter.ReportSeverity.DEBUG +import org.jetbrains.kotlin.build.report.ICReporterBase +import org.jetbrains.kotlin.build.report.RemoteICReporter import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.daemon.common.CompilationResultCategory import org.jetbrains.kotlin.daemon.common.CompilationResults -import org.jetbrains.kotlin.build.report.ICReporterBase -import org.jetbrains.kotlin.build.report.RemoteICReporter import java.io.File -import java.util.* // todo: sync BuildReportICReporterAsync -internal class BuildReportICReporter( +@VisibleForTesting +class BuildReportICReporter( private val compilationResults: CompilationResults, rootDir: File, private val isVerbose: Boolean = false @@ -22,14 +25,10 @@ internal class BuildReportICReporter( private val icLogLines = arrayListOf() private val recompilationReason = HashMap() - override fun report(message: () -> String) { - icLogLines.add(message()) - } + override fun report(message: () -> String, severity: ReportSeverity) { + if (severity == DEBUG && !isVerbose) return - override fun reportVerbose(message: () -> String) { - if (isVerbose) { - report(message) - } + icLogLines.add(message()) } override fun reportCompileIteration(incremental: Boolean, sourceFiles: Collection, exitCode: ExitCode) { diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/CompileIterationICReporter.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/CompileIterationICReporter.kt index dd67aae6e91..9ec70973ef6 100644 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/CompileIterationICReporter.kt +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/CompileIterationICReporter.kt @@ -5,12 +5,13 @@ package org.jetbrains.kotlin.daemon.report +import org.jetbrains.kotlin.build.report.ICReporter.ReportSeverity +import org.jetbrains.kotlin.build.report.ICReporterBase +import org.jetbrains.kotlin.build.report.RemoteICReporter import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.daemon.common.CompilationResultCategory import org.jetbrains.kotlin.daemon.common.CompilationResults import org.jetbrains.kotlin.daemon.common.CompileIterationResult -import org.jetbrains.kotlin.build.report.ICReporterBase -import org.jetbrains.kotlin.build.report.RemoteICReporter import java.io.File internal class CompileIterationICReporter( @@ -23,10 +24,7 @@ internal class CompileIterationICReporter( ) } - override fun report(message: () -> String) { - } - - override fun reportVerbose(message: () -> String) { + override fun report(message: () -> String, severity: ReportSeverity) { } override fun flush() { diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/CompositeICReporter.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/CompositeICReporter.kt index 89e59dabe87..8e9880f2473 100644 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/CompositeICReporter.kt +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/CompositeICReporter.kt @@ -5,17 +5,14 @@ package org.jetbrains.kotlin.daemon.report +import org.jetbrains.kotlin.build.report.ICReporter.ReportSeverity import org.jetbrains.kotlin.build.report.RemoteICReporter import org.jetbrains.kotlin.cli.common.ExitCode import java.io.File internal class CompositeICReporter(private val reporters: Iterable) : RemoteICReporter { - override fun report(message: () -> String) { - reporters.forEach { it.report(message) } - } - - override fun reportVerbose(message: () -> String) { - reporters.forEach { it.reportVerbose(message) } + override fun report(message: () -> String, severity: ReportSeverity) { + reporters.forEach { it.report(message, severity) } } override fun reportCompileIteration(incremental: Boolean, sourceFiles: Collection, exitCode: ExitCode) { diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/DaemonMessageReporter.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/DaemonMessageReporter.kt index 4ba022c0a19..16e330ca2d2 100644 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/DaemonMessageReporter.kt +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/DaemonMessageReporter.kt @@ -28,7 +28,7 @@ fun DaemonMessageReporter( compilationOptions: CompilationOptions ): DaemonMessageReporter = if (ReportCategory.DAEMON_MESSAGE.code in compilationOptions.reportCategories) { - val mySeverity = ReportSeverity.fromCode(compilationOptions.reportSeverity)!! + val mySeverity = ReportSeverity.fromCode(compilationOptions.reportSeverity) DaemonMessageReporterImpl(servicesFacade, mySeverity) } else { diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/DebugMessagesICReporter.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/DebugMessagesICReporter.kt index d416cdf3cb5..2cf85fab6cf 100644 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/DebugMessagesICReporter.kt +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/DebugMessagesICReporter.kt @@ -5,28 +5,28 @@ package org.jetbrains.kotlin.daemon.report -import org.jetbrains.kotlin.cli.common.ExitCode -import org.jetbrains.kotlin.daemon.common.* +import com.google.common.annotations.VisibleForTesting +import org.jetbrains.kotlin.build.report.ICReporter import org.jetbrains.kotlin.build.report.ICReporterBase import org.jetbrains.kotlin.build.report.RemoteICReporter +import org.jetbrains.kotlin.cli.common.ExitCode +import org.jetbrains.kotlin.daemon.common.CompilerServicesFacadeBase +import org.jetbrains.kotlin.daemon.common.ReportCategory +import org.jetbrains.kotlin.daemon.common.ReportSeverity +import org.jetbrains.kotlin.daemon.common.report import java.io.File -internal class DebugMessagesICReporter( +@VisibleForTesting +class DebugMessagesICReporter( private val servicesFacade: CompilerServicesFacadeBase, rootDir: File, - private val isVerbose: Boolean + private val reportSeverity: ICReporter.ReportSeverity ) : ICReporterBase(rootDir), RemoteICReporter { - override fun report(message: () -> String) { - servicesFacade.report( - ReportCategory.IC_MESSAGE, - ReportSeverity.DEBUG, message() - ) - } - override fun reportVerbose(message: () -> String) { - if (isVerbose) { - report(message) - } + override fun report(message: () -> String, severity: ICReporter.ReportSeverity) { + if (severity.level < reportSeverity.level) return + + servicesFacade.report(ReportCategory.IC_MESSAGE, severity.getSeverity(), message()) } override fun reportCompileIteration(incremental: Boolean, sourceFiles: Collection, exitCode: ExitCode) { @@ -34,4 +34,12 @@ internal class DebugMessagesICReporter( override fun flush() { } -} \ No newline at end of file +} + +internal fun ICReporter.ReportSeverity.getSeverity(): ReportSeverity { + return when (this) { + ICReporter.ReportSeverity.WARNING -> ReportSeverity.WARNING + ICReporter.ReportSeverity.INFO -> ReportSeverity.INFO + ICReporter.ReportSeverity.DEBUG -> ReportSeverity.DEBUG + } +} diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/experimental/DaemonMessageReporterAsync.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/experimental/DaemonMessageReporterAsync.kt index 6a3529b136a..d031d21aaeb 100644 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/experimental/DaemonMessageReporterAsync.kt +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/experimental/DaemonMessageReporterAsync.kt @@ -18,7 +18,7 @@ internal fun DaemonMessageReporterAsync( compilationOptions: CompilationOptions ): DaemonMessageReporter = if (ReportCategory.DAEMON_MESSAGE.code in compilationOptions.reportCategories) { - val mySeverity = ReportSeverity.fromCode(compilationOptions.reportSeverity)!! + val mySeverity = ReportSeverity.fromCode(compilationOptions.reportSeverity) DaemonMessageReporterAsyncAsyncImpl(servicesFacade, mySeverity) } else { DummyDaemonMessageReporterAsync diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/experimental/RemoteICReporter.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/experimental/RemoteICReporter.kt index cb7d92e00c5..b950e84ca09 100644 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/experimental/RemoteICReporter.kt +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/experimental/RemoteICReporter.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.daemon.report.experimental import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.async +import org.jetbrains.kotlin.build.report.ICReporter import org.jetbrains.kotlin.build.report.ICReporterBase import org.jetbrains.kotlin.build.report.RemoteBuildReporter import org.jetbrains.kotlin.build.report.RemoteICReporter @@ -16,25 +17,20 @@ import org.jetbrains.kotlin.build.report.metrics.RemoteBuildMetricsReporter import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.daemon.common.* import org.jetbrains.kotlin.daemon.report.CompositeICReporter +import org.jetbrains.kotlin.daemon.report.getSeverity import java.io.File internal class DebugMessagesICReporterAsync( private val servicesFacade: CompilerServicesFacadeBaseAsync, rootDir: File, - private val isVerbose: Boolean + private val reportSeverity: ICReporter.ReportSeverity ) : ICReporterBase(rootDir), RemoteICReporter { - override fun report(message: () -> String) { - GlobalScope.async { - servicesFacade.report( - ReportCategory.IC_MESSAGE, - ReportSeverity.DEBUG, message() - ) - } - } - override fun reportVerbose(message: () -> String) { - if (isVerbose) { - report(message) + override fun report(message: () -> String, severity: ICReporter.ReportSeverity) { + if (severity.level < reportSeverity.level) return + + GlobalScope.async { + servicesFacade.report(ReportCategory.IC_MESSAGE, severity.getSeverity(), message()) } } @@ -57,10 +53,7 @@ internal class CompileIterationICReporterAsync( } } - override fun report(message: () -> String) { - } - - override fun reportVerbose(message: () -> String) { + override fun report(message: () -> String, severity: ICReporter.ReportSeverity) { } override fun flush() { @@ -75,14 +68,10 @@ internal class BuildReportICReporterAsync( private val icLogLines = arrayListOf() private val recompilationReason = HashMap() - override fun report(message: () -> String) { - icLogLines.add(message()) - } + override fun report(message: () -> String, severity: ICReporter.ReportSeverity) { + if (severity == ICReporter.ReportSeverity.DEBUG && !isVerbose) return - override fun reportVerbose(message: () -> String) { - if (isVerbose) { - report(message) - } + icLogLines.add(message()) } override fun reportCompileIteration(incremental: Boolean, sourceFiles: Collection, exitCode: ExitCode) { @@ -116,8 +105,14 @@ fun getICReporterAsync( val reporters = ArrayList() if (ReportCategory.IC_MESSAGE.code in compilationOptions.reportCategories) { - val isVerbose = compilationOptions.reportSeverity == ReportSeverity.DEBUG.code - reporters.add(DebugMessagesICReporterAsync(servicesFacade, root, isVerbose = isVerbose)) + reporters.add( + DebugMessagesICReporterAsync( + servicesFacade = servicesFacade, + rootDir = root, + reportSeverity = ReportSeverity.fromCode(compilationOptions.reportSeverity) + .getSeverity(mapErrorToWarning = true, mapInfoToWarning = true) + ) + ) } val requestedResults = compilationOptions diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/getICReporter.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/getICReporter.kt index 8476d7818b3..fd5126b98bc 100644 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/getICReporter.kt +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/getICReporter.kt @@ -16,12 +16,12 @@ package org.jetbrains.kotlin.daemon.report +import org.jetbrains.kotlin.build.report.ICReporter import org.jetbrains.kotlin.build.report.RemoteBuildReporter import org.jetbrains.kotlin.build.report.RemoteICReporter import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporterImpl import org.jetbrains.kotlin.build.report.metrics.DoNothingBuildMetricsReporter import org.jetbrains.kotlin.daemon.common.* -import java.util.* fun getBuildReporter( servicesFacade: CompilerServicesFacadeBase, @@ -32,8 +32,14 @@ fun getBuildReporter( val reporters = ArrayList() if (ReportCategory.IC_MESSAGE.code in compilationOptions.reportCategories) { - val isVerbose = compilationOptions.reportSeverity == ReportSeverity.DEBUG.code - reporters.add(DebugMessagesICReporter(servicesFacade, root, isVerbose = isVerbose)) + reporters.add( + DebugMessagesICReporter( + servicesFacade = servicesFacade, + rootDir = root, + reportSeverity = ReportSeverity.fromCode(compilationOptions.reportSeverity) + .getSeverity(mapErrorToWarning = true, mapInfoToWarning = true) + ) + ) } val requestedResults = compilationOptions @@ -63,3 +69,43 @@ fun getBuildReporter( return RemoteBuildReporter(CompositeICReporter(reporters), metricsReporter) } + +internal fun ReportSeverity.getSeverity( + + /** + * If true, [ReportSeverity.ERROR] will be mapped to [ICReporter.ReportSeverity.WARNING] (i.e., when [ReportSeverity.ERROR] is + * specified, [ICReporter.ReportSeverity.WARNING] messages will also be shown). + * + * NOTE: This parameter exists only because we don't have `ICReporter.ReportSeverity.ERROR` yet. Once that we create that enum, we can + * remove this parameter. + */ + mapErrorToWarning: Boolean, + + /** + * If true, [ReportSeverity.INFO] will be mapped to [ICReporter.ReportSeverity.WARNING] (i.e., when [ReportSeverity.INFO] is specified, + * only messages with severity [ICReporter.ReportSeverity.WARNING] and above will be shown). + * + * NOTE: This parameter exists only to preserve the previous behavior (`mapInfoToWarning = true`). If `mapInfoToWarning` is never set + * to `true`, we can remove this parameter. + */ + mapInfoToWarning: Boolean + +): ICReporter.ReportSeverity { + return when (this) { + ReportSeverity.ERROR -> if (mapErrorToWarning) { + ICReporter.ReportSeverity.WARNING + } else { + throw IllegalArgumentException( + "No mapping exists for `ReportSeverity.ERROR`." + + " Add `ICReporter.ReportSeverity.ERROR` and remove mapErrorToWarning, or set mapErrorToWarning = true." + ) + } + ReportSeverity.WARNING -> ICReporter.ReportSeverity.WARNING + ReportSeverity.INFO -> if (mapInfoToWarning) { + ICReporter.ReportSeverity.WARNING + } else { + ICReporter.ReportSeverity.INFO + } + ReportSeverity.DEBUG -> ICReporter.ReportSeverity.DEBUG + } +} diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt index 584d640d4cb..85bbb140651 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt @@ -37,6 +37,7 @@ import org.jetbrains.kotlin.incremental.parsing.classesFqNames import org.jetbrains.kotlin.incremental.util.BufferingMessageCollector import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.progress.CompilationCanceledStatus +import org.jetbrains.kotlin.util.suffixIfNot import java.io.File abstract class IncrementalCompilerRunner< @@ -179,8 +180,9 @@ abstract class IncrementalCompilerRunner< } return exitCode } catch (e: Throwable) { - reporter.report { - "Incremental compilation failed: ${e.stackTraceToString()}.\nFalling back to non-incremental compilation." + reporter.warn { + "Incremental compilation failed: ${e.stackTraceToString().suffixIfNot("\n")}" + + "Falling back to non-incremental compilation" } rebuildReason = BuildAttribute.INCREMENTAL_COMPILATION_FAILED } @@ -188,8 +190,9 @@ abstract class IncrementalCompilerRunner< is CompilationMode.Rebuild -> rebuildReason = compilationMode.reason } } catch (e: Exception) { - reporter.report { - "Incremental compilation analysis failed: ${e.stackTraceToString()}.\nFalling back to non-incremental compilation." + reporter.warn { + "Incremental compilation analysis failed: ${e.stackTraceToString().suffixIfNot("\n")}" + + "Falling back to non-incremental compilation" } } finally { if (!caches.close(flush = true)) { diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotBuildReporter.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotBuildReporter.kt index ba06014ccbf..3736102e0cc 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotBuildReporter.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotBuildReporter.kt @@ -12,8 +12,8 @@ import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter class ClasspathSnapshotBuildReporter(private val buildReporter: BuildReporter) : ICReporter by buildReporter, BuildMetricsReporter by buildReporter { - override fun reportVerbose(message: () -> String) { - buildReporter.reportVerbose { "[ClasspathSnapshot] ${message()}" } + override fun report(message: () -> String, severity: ICReporter.ReportSeverity) { + buildReporter.report({ "[ClasspathSnapshot] ${message()}" }, severity) } fun reportVerboseWithLimit(maxLength: Int = 1000, message: () -> String) { diff --git a/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/utils/TestICReporter.kt b/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/utils/TestICReporter.kt index 2c224ec38f7..75bbd3fae59 100644 --- a/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/utils/TestICReporter.kt +++ b/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/utils/TestICReporter.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.incremental.utils +import org.jetbrains.kotlin.build.report.ICReporter.ReportSeverity import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.build.report.ICReporterBase import java.io.File @@ -29,10 +30,7 @@ class TestICReporter : ICReporterBase() { var exitCode: ExitCode = ExitCode.OK private set - override fun report(message: () -> String) { - } - - override fun reportVerbose(message: () -> String) { + override fun report(message: () -> String, severity: ReportSeverity) { } override fun reportCompileIteration(incremental: Boolean, sourceFiles: Collection, exitCode: ExitCode) { diff --git a/jps/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt b/jps/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt index 66fab6f2b3b..6bedcf6174c 100644 --- a/jps/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt +++ b/jps/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt @@ -20,9 +20,12 @@ import org.jetbrains.jps.incremental.java.JavaBuilder import org.jetbrains.jps.model.JpsProject import org.jetbrains.kotlin.build.GeneratedFile import org.jetbrains.kotlin.build.GeneratedJvmClass +import org.jetbrains.kotlin.build.report.ICReporter.ReportSeverity +import org.jetbrains.kotlin.build.report.ICReporterBase import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.* +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.INFO import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil import org.jetbrains.kotlin.compilerRunner.* import org.jetbrains.kotlin.config.IncrementalCompilation @@ -30,12 +33,11 @@ import org.jetbrains.kotlin.config.KotlinModuleKind import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.daemon.common.isDaemonEnabled import org.jetbrains.kotlin.incremental.* -import org.jetbrains.kotlin.incremental.components.ExpectActualTracker -import org.jetbrains.kotlin.incremental.components.LookupTracker -import org.jetbrains.kotlin.build.report.ICReporterBase import org.jetbrains.kotlin.incremental.components.EnumWhenTracker -import org.jetbrains.kotlin.jps.KotlinJpsBundle +import org.jetbrains.kotlin.incremental.components.ExpectActualTracker import org.jetbrains.kotlin.incremental.components.InlineConstTracker +import org.jetbrains.kotlin.incremental.components.LookupTracker +import org.jetbrains.kotlin.jps.KotlinJpsBundle import org.jetbrains.kotlin.jps.incremental.JpsIncrementalCache import org.jetbrains.kotlin.jps.incremental.JpsLookupStorageManager import org.jetbrains.kotlin.jps.model.kotlinKind @@ -731,15 +733,12 @@ private class JpsICReporter : ICReporterBase() { override fun reportCompileIteration(incremental: Boolean, sourceFiles: Collection, exitCode: ExitCode) { } - override fun report(message: () -> String) { + override fun report(message: () -> String, severity: ReportSeverity) { + // Currently, all severity levels are mapped to debug if (KotlinBuilder.LOG.isDebugEnabled) { KotlinBuilder.LOG.debug(message()) } } - - override fun reportVerbose(message: () -> String) { - report(message) - } } private fun ChangesCollector.processChangesUsingLookups( diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/GradleIncrementalCompilerServicesFacadeImpl.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/GradleIncrementalCompilerServicesFacadeImpl.kt index 84698e22157..4c4cc33d4a1 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/GradleIncrementalCompilerServicesFacadeImpl.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/GradleIncrementalCompilerServicesFacadeImpl.kt @@ -7,8 +7,8 @@ package org.jetbrains.kotlin.compilerRunner import org.jetbrains.kotlin.daemon.client.reportFromDaemon import org.jetbrains.kotlin.daemon.common.* -import org.jetbrains.kotlin.gradle.logging.GradleBufferingMessageCollector -import org.jetbrains.kotlin.gradle.logging.kotlinDebug +import org.jetbrains.kotlin.daemon.common.ReportSeverity.* +import org.jetbrains.kotlin.gradle.logging.* import java.io.Serializable import java.rmi.Remote import java.rmi.server.UnicastRemoteObject @@ -27,7 +27,13 @@ internal open class GradleCompilerServicesFacadeImpl( override fun report(category: Int, severity: Int, message: String?, attachment: Serializable?) { when (ReportCategory.fromCode(category)) { ReportCategory.IC_MESSAGE -> { - log.kotlinDebug { "[IC] $message" } + @Suppress("UNUSED_VARIABLE") + val unusedValueForExhaustiveWhen = when (ReportSeverity.fromCode(severity)) { + ERROR -> log.kotlinError { "[IC] $message" } + WARNING -> log.kotlinWarn { "[IC] $message" } + INFO -> log.kotlinInfo { "[IC] $message" } + DEBUG -> log.kotlinDebug { "[IC] $message" } + } } ReportCategory.DAEMON_MESSAGE -> { log.kotlinDebug { "[DAEMON] $message" } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerWork.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerWork.kt index 3a2bdc4231e..0efe4898e51 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerWork.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerWork.kt @@ -7,10 +7,8 @@ package org.jetbrains.kotlin.compilerRunner import org.gradle.api.logging.Logger import org.jetbrains.kotlin.build.report.metrics.* -import org.jetbrains.kotlin.cli.common.CompilerSystemProperties import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.cli.common.messages.MessageCollector -import org.jetbrains.kotlin.cli.common.toBooleanLenient import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.daemon.common.* import org.jetbrains.kotlin.gradle.logging.* @@ -385,7 +383,7 @@ internal class GradleKotlinCompilerWork @Inject constructor( private fun reportCategories(verbose: Boolean): Array = if (!verbose) { - arrayOf(ReportCategory.COMPILER_MESSAGE.code) + arrayOf(ReportCategory.COMPILER_MESSAGE.code, ReportCategory.IC_MESSAGE.code) } else { ReportCategory.values().map { it.code }.toTypedArray() } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/logging/gradleLoggingUtils.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/logging/gradleLoggingUtils.kt index bb28d0d8450..46ea81c104b 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/logging/gradleLoggingUtils.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/logging/gradleLoggingUtils.kt @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.gradle.logging -import org.gradle.api.Task import org.gradle.api.logging.Logger import org.jetbrains.kotlin.compilerRunner.KotlinLogger @@ -27,10 +26,21 @@ internal inline fun Logger.kotlinDebug(message: () -> String) { } } -internal inline fun KotlinLogger.kotlinDebug(fn: () -> String) { +internal inline fun KotlinLogger.kotlinError(message: () -> String) { + error("[KOTLIN] ${message()}") +} + +internal inline fun KotlinLogger.kotlinWarn(message: () -> String) { + warn("[KOTLIN] ${message()}") +} + +internal inline fun KotlinLogger.kotlinInfo(message: () -> String) { + info("[KOTLIN] ${message()}") +} + +internal inline fun KotlinLogger.kotlinDebug(message: () -> String) { if (isDebugEnabled) { - val msg = fn() - debug("[KOTLIN] $msg") + debug("[KOTLIN] ${message()}") } } diff --git a/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/incremental/MavenICReporter.java b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/incremental/MavenICReporter.java index 8031b21606a..a2127b00be5 100644 --- a/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/incremental/MavenICReporter.java +++ b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/incremental/MavenICReporter.java @@ -20,6 +20,8 @@ import kotlin.jvm.functions.Function0; import org.apache.maven.plugin.logging.Log; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.cli.common.ExitCode; +import org.jetbrains.kotlin.build.report.ICReporter; +import org.jetbrains.kotlin.build.report.ICReporterKt; import org.jetbrains.kotlin.build.report.ICReporterBase; import java.io.File; @@ -69,26 +71,31 @@ public class MavenICReporter extends ICReporterBase { } @Override - public void report(@NotNull Function0 getMessage) { + public void report(@NotNull Function0 getMessage, @NotNull ICReporter.ReportSeverity severity) { switch (logLevel) { case NONE: break; case INFO: - log.info(getMessage.invoke()); + if (severity == ICReporter.ReportSeverity.WARNING) { + log.warn(getMessage.invoke()); + } else if (severity == ICReporter.ReportSeverity.INFO) { + log.info(getMessage.invoke()); + } else if (severity == ICReporter.ReportSeverity.DEBUG) { + // Don't log + } else throw new IllegalArgumentException(severity.toString() + " is not yet handled"); break; case DEBUG: - log.debug(getMessage.invoke()); + if (severity == ICReporter.ReportSeverity.WARNING) { + log.warn(getMessage.invoke()); + } else if (severity == ICReporter.ReportSeverity.INFO) { + log.info(getMessage.invoke()); + } else if (severity == ICReporter.ReportSeverity.DEBUG) { + log.debug(getMessage.invoke()); + } else throw new IllegalArgumentException(severity.toString() + " is not yet handled"); break; } } - @Override - public void reportVerbose(@NotNull Function0 getMessage) { - if (logLevel == LogLevel.DEBUG) { - log.debug(getMessage.invoke()); - } - } - @NotNull public Set getCompiledKotlinFiles() { return compiledKotlinFiles; @@ -97,7 +104,7 @@ public class MavenICReporter extends ICReporterBase { @Override public void reportCompileIteration(boolean b, @NotNull Collection sourceFiles, @NotNull ExitCode exitCode) { compiledKotlinFiles.addAll(sourceFiles); - report(() -> "Kotlin compile iteration: " + pathsAsString(sourceFiles)); - report(() -> "Exit code: " + exitCode.toString()); + ICReporterKt.info(this, () -> "Kotlin compile iteration: " + pathsAsString(sourceFiles)); + ICReporterKt.info(this, () -> "Exit code: " + exitCode.toString()); } }