Report messages from kapt using MessageCollector

This allows to print messages when daemon is used.
System out is not copied to daemon client,
because multiple compilations can occur in parallel.
This commit is contained in:
Alexey Tsvetkov
2016-11-23 16:37:08 +03:00
parent b39cefe5d1
commit 865c6d887c
7 changed files with 54 additions and 20 deletions
@@ -75,7 +75,8 @@ abstract class BaseGradleIT {
val androidHome: File? = null, val androidHome: File? = null,
val androidGradlePluginVersion: String? = null, val androidGradlePluginVersion: String? = null,
val forceOutputToStdout: Boolean = false, val forceOutputToStdout: Boolean = false,
val debug: Boolean = false) val debug: Boolean = false,
val freeCommandLineArgs: List<String> = emptyList())
open inner class Project( open inner class Project(
val projectName: String, val projectName: String,
@@ -280,6 +281,7 @@ abstract class BaseGradleIT {
if (options.debug) { if (options.debug) {
add("-Dorg.gradle.debug=true") add("-Dorg.gradle.debug=true")
} }
addAll(options.freeCommandLineArgs)
} }
private fun Project.createEnvironmentVariablesMap(options: BuildOptions): Map<String, String> = private fun Project.createEnvironmentVariablesMap(options: BuildOptions): Map<String, String> =
@@ -32,7 +32,8 @@ class Kapt3IT : BaseGradleIT() {
private fun androidBuildOptions() = private fun androidBuildOptions() =
BuildOptions(withDaemon = true, BuildOptions(withDaemon = true,
androidHome = File("../../../dependencies/android-sdk-for-tests"), androidHome = File("../../../dependencies/android-sdk-for-tests"),
androidGradlePluginVersion = ANDROID_GRADLE_PLUGIN_VERSION) androidGradlePluginVersion = ANDROID_GRADLE_PLUGIN_VERSION,
freeCommandLineArgs = listOf("-Pkapt.verbose=true"))
override fun defaultBuildOptions(): BuildOptions = override fun defaultBuildOptions(): BuildOptions =
super.defaultBuildOptions().copy(withDaemon = true) super.defaultBuildOptions().copy(withDaemon = true)
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.annotation.processing.RoundAnnotations import org.jetbrains.kotlin.annotation.processing.RoundAnnotations
import org.jetbrains.kotlin.annotation.processing.diagnostic.ErrorsAnnotationProcessing import org.jetbrains.kotlin.annotation.processing.diagnostic.ErrorsAnnotationProcessing
import org.jetbrains.kotlin.annotation.processing.impl.* import org.jetbrains.kotlin.annotation.processing.impl.*
import org.jetbrains.kotlin.cli.common.messages.*
import org.jetbrains.kotlin.codegen.ClassBuilderMode import org.jetbrains.kotlin.codegen.ClassBuilderMode
import org.jetbrains.kotlin.codegen.state.IncompatibleClassTracker import org.jetbrains.kotlin.codegen.state.IncompatibleClassTracker
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
@@ -55,10 +56,11 @@ class ClasspathBasedAnnotationProcessingExtension(
classesOutputDir: File, classesOutputDir: File,
javaSourceRoots: List<File>, javaSourceRoots: List<File>,
verboseOutput: Boolean, verboseOutput: Boolean,
incrementalDataFile: File? incrementalDataFile: File?,
messageCollector: MessageCollector?
) : AbstractAnnotationProcessingExtension(generatedSourcesOutputDir, ) : AbstractAnnotationProcessingExtension(generatedSourcesOutputDir,
classesOutputDir, javaSourceRoots, verboseOutput, classesOutputDir, javaSourceRoots, verboseOutput,
incrementalDataFile) { incrementalDataFile, messageCollector) {
override fun loadAnnotationProcessors(): List<Processor> { override fun loadAnnotationProcessors(): List<Processor> {
val classLoader = URLClassLoader(annotationProcessingClasspath.map { it.toURI().toURL() }.toTypedArray()) val classLoader = URLClassLoader(annotationProcessingClasspath.map { it.toURI().toURL() }.toTypedArray())
return ServiceLoader.load(Processor::class.java, classLoader).toList() return ServiceLoader.load(Processor::class.java, classLoader).toList()
@@ -70,17 +72,23 @@ abstract class AbstractAnnotationProcessingExtension(
val classesOutputDir: File, val classesOutputDir: File,
val javaSourceRoots: List<File>, val javaSourceRoots: List<File>,
val verboseOutput: Boolean, val verboseOutput: Boolean,
val incrementalDataFile: File? = null val incrementalDataFile: File? = null,
messageCollector: MessageCollector? = null
) : AnalysisHandlerExtension { ) : AnalysisHandlerExtension {
private companion object { private companion object {
val LINE_SEPARATOR = System.getProperty("line.separator") ?: "\n" val LINE_SEPARATOR = System.getProperty("line.separator") ?: "\n"
} }
private var annotationProcessingComplete = false private var annotationProcessingComplete = false
private val messager = KotlinMessager() private val messager = run {
val collector = messageCollector ?: PrintingMessageCollector(System.err, MessageRenderer.WITHOUT_PATHS, verboseOutput)
KotlinMessager(collector)
}
private inline fun log(message: () -> String) { private inline fun log(message: () -> String) {
if (verboseOutput) messager.printMessage(Diagnostic.Kind.OTHER, "Kapt: " + message()) if (verboseOutput) {
messager.printMessage(Diagnostic.Kind.OTHER, "Kapt: " + message())
}
} }
private fun Int.count(noun: String) = if (this == 1) "$this $noun" else "$this ${noun}s" private fun Int.count(noun: String) = if (this == 1) "$this $noun" else "$this ${noun}s"
@@ -37,6 +37,7 @@ import java.io.File
import org.jetbrains.kotlin.annotation.processing.AnnotationProcessingConfigurationKeys.ANNOTATION_PROCESSOR_CLASSPATH import org.jetbrains.kotlin.annotation.processing.AnnotationProcessingConfigurationKeys.ANNOTATION_PROCESSOR_CLASSPATH
import org.jetbrains.kotlin.annotation.processing.AnnotationProcessingConfigurationKeys.APT_OPTIONS import org.jetbrains.kotlin.annotation.processing.AnnotationProcessingConfigurationKeys.APT_OPTIONS
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
object AnnotationProcessingConfigurationKeys { object AnnotationProcessingConfigurationKeys {
val GENERATED_OUTPUT_DIR: CompilerConfigurationKey<String> = val GENERATED_OUTPUT_DIR: CompilerConfigurationKey<String> =
@@ -142,9 +143,11 @@ class AnnotationProcessingComponentRegistrar : ComponentRegistrar {
// Annotations with the "SOURCE" retention will be written to class files // Annotations with the "SOURCE" retention will be written to class files
project.putUserData(IS_KAPT2_ENABLED_KEY, true) project.putUserData(IS_KAPT2_ENABLED_KEY, true)
val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
val annotationProcessingExtension = ClasspathBasedAnnotationProcessingExtension( val annotationProcessingExtension = ClasspathBasedAnnotationProcessingExtension(
classpath, apOptions, generatedOutputDirFile, classesOutputDir, javaRoots, verboseOutput, classpath, apOptions, generatedOutputDirFile, classesOutputDir, javaRoots, verboseOutput,
incrementalDataFile) incrementalDataFile, messageCollector)
project.registerService(JeElementRegistry::class.java, JeElementRegistry()) project.registerService(JeElementRegistry::class.java, JeElementRegistry())
@@ -16,6 +16,9 @@
package org.jetbrains.kotlin.annotation.processing.impl package org.jetbrains.kotlin.annotation.processing.impl
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 javax.annotation.processing.Messager import javax.annotation.processing.Messager
import javax.lang.model.element.AnnotationMirror import javax.lang.model.element.AnnotationMirror
import javax.lang.model.element.AnnotationValue import javax.lang.model.element.AnnotationValue
@@ -23,7 +26,7 @@ import javax.lang.model.element.Element
import javax.tools.Diagnostic import javax.tools.Diagnostic
import javax.tools.Diagnostic.Kind import javax.tools.Diagnostic.Kind
class KotlinMessager : Messager { class KotlinMessager(private val messageCollector: MessageCollector) : Messager {
var errorCount: Int = 0 var errorCount: Int = 0
private set private set
@@ -39,17 +42,17 @@ class KotlinMessager : Messager {
} }
override fun printMessage(kind: Diagnostic.Kind, msg: CharSequence, e: Element?, a: AnnotationMirror?, v: AnnotationValue?) { override fun printMessage(kind: Diagnostic.Kind, msg: CharSequence, e: Element?, a: AnnotationMirror?, v: AnnotationValue?) {
val output = when (kind) { val severity = when (kind) {
Kind.ERROR -> { Kind.ERROR -> {
errorCount++ errorCount++
System.err CompilerMessageSeverity.ERROR
} }
Kind.WARNING, Kind.MANDATORY_WARNING -> { Kind.WARNING, Kind.MANDATORY_WARNING -> {
warningCount++ warningCount++
System.err CompilerMessageSeverity.WARNING
} }
else -> System.out else -> CompilerMessageSeverity.LOGGING
} }
output.println(msg) messageCollector.report(severity, msg.toString(), CompilerMessageLocation.NO_LOCATION)
} }
} }
@@ -20,6 +20,9 @@ import com.intellij.mock.MockProject
import com.intellij.openapi.extensions.Extensions import com.intellij.openapi.extensions.Extensions
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector
import org.jetbrains.kotlin.kapt3.Kapt3ConfigurationKeys.ANNOTATION_PROCESSOR_CLASSPATH import org.jetbrains.kotlin.kapt3.Kapt3ConfigurationKeys.ANNOTATION_PROCESSOR_CLASSPATH
import org.jetbrains.kotlin.kapt3.Kapt3ConfigurationKeys.APT_OPTIONS import org.jetbrains.kotlin.kapt3.Kapt3ConfigurationKeys.APT_OPTIONS
import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot
@@ -132,7 +135,10 @@ class Kapt3ComponentRegistrar : ComponentRegistrar {
override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) { override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) {
val isAptOnly = configuration.get(Kapt3ConfigurationKeys.APT_ONLY) == "true" val isAptOnly = configuration.get(Kapt3ConfigurationKeys.APT_ONLY) == "true"
val isVerbose = configuration.get(Kapt3ConfigurationKeys.VERBOSE_MODE) == "true" val isVerbose = configuration.get(Kapt3ConfigurationKeys.VERBOSE_MODE) == "true"
val logger = KaptLogger(isVerbose) val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
?: PrintingMessageCollector(System.err, MessageRenderer.PLAIN_FULL_PATHS, isVerbose)
val logger = KaptLogger(isVerbose, messageCollector)
val sourcesOutputDir = configuration.get(Kapt3ConfigurationKeys.SOURCE_OUTPUT_DIR)?.let(::File) val sourcesOutputDir = configuration.get(Kapt3ConfigurationKeys.SOURCE_OUTPUT_DIR)?.let(::File)
val classFilesOutputDir = configuration.get(Kapt3ConfigurationKeys.CLASS_OUTPUT_DIR)?.let(::File) val classFilesOutputDir = configuration.get(Kapt3ConfigurationKeys.CLASS_OUTPUT_DIR)?.let(::File)
@@ -16,14 +16,20 @@
package org.jetbrains.kotlin.kapt3.util package org.jetbrains.kotlin.kapt3.util
class KaptLogger(val isVerbose: Boolean) { 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 java.io.ByteArrayOutputStream
import java.io.PrintWriter
class KaptLogger(val isVerbose: Boolean, val messageCollector: MessageCollector) {
private companion object { private companion object {
val PREFIX = "[kapt] " val PREFIX = "[kapt] "
} }
fun info(message: String) { fun info(message: String) {
if (isVerbose) { if (isVerbose) {
println(PREFIX + message) messageCollector.report(CompilerMessageSeverity.INFO, PREFIX + message, CompilerMessageLocation.NO_LOCATION)
} }
} }
@@ -38,11 +44,16 @@ class KaptLogger(val isVerbose: Boolean) {
} }
fun error(message: String) { fun error(message: String) {
System.err.println(PREFIX + message) messageCollector.report(CompilerMessageSeverity.ERROR, PREFIX + message, CompilerMessageLocation.NO_LOCATION)
} }
fun exception(e: Throwable) { fun exception(e: Throwable) {
System.err.println(PREFIX + "An exception occurred:") val stacktrace = run {
e.printStackTrace(System.err) val byteArrayOutputStream = ByteArrayOutputStream()
e.printStackTrace(PrintWriter(byteArrayOutputStream))
byteArrayOutputStream.toString("UTF-8")
}
messageCollector.report(CompilerMessageSeverity.EXCEPTION, PREFIX + "An exception occurred: " + stacktrace, CompilerMessageLocation.NO_LOCATION)
} }
} }