From 399059729d1df1a7eb711b0ff93e35cc0d18843a Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Thu, 4 Aug 2016 22:41:01 +0300 Subject: [PATCH] Kapt: verbose output mode (cherry picked from commit e6067d5) --- .../AnnotationProcessingExtension.kt | 48 +++++++++++++++---- .../processing/AnnotationProcessingPlugin.kt | 13 ++++- .../processing/impl/KotlinMessager.kt | 15 +++++- .../test/processor/AbstractProcessorTest.kt | 2 +- 4 files changed, 64 insertions(+), 14 deletions(-) diff --git a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingExtension.kt b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingExtension.kt index c2f2a9187e7..01d59d76c1d 100755 --- a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingExtension.kt +++ b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingExtension.kt @@ -34,13 +34,15 @@ import java.io.File import java.net.URLClassLoader import java.util.* import javax.annotation.processing.Processor +import javax.tools.Diagnostic class ClasspathBasedAnnotationProcessingExtension( val annotationProcessingClasspath: List, generatedSourcesOutputDir: File, classesOutputDir: File, - javaSourceRoots: List -) : AbstractAnnotationProcessingExtension(generatedSourcesOutputDir, classesOutputDir, javaSourceRoots) { + javaSourceRoots: List, + verboseOutput: Boolean +) : AbstractAnnotationProcessingExtension(generatedSourcesOutputDir, classesOutputDir, javaSourceRoots, verboseOutput) { override fun loadAnnotationProcessors(): List { val classLoader = URLClassLoader(annotationProcessingClasspath.map { File(it).toURI().toURL() }.toTypedArray()) return ServiceLoader.load(Processor::class.java, classLoader).toList() @@ -50,10 +52,16 @@ class ClasspathBasedAnnotationProcessingExtension( abstract class AbstractAnnotationProcessingExtension( val generatedSourcesOutputDir: File, val classesOutputDir: File, - val javaSourceRoots: List + val javaSourceRoots: List, + val verboseOutput: Boolean ) : AnalysisCompletedHandlerExtension { private var annotationProcessingComplete = false + private val messager = KotlinMessager() + private inline fun log(message: () -> String) { + if (verboseOutput) messager.printMessage(Diagnostic.Kind.OTHER, "Kapt: " + message()) + } + override fun analysisCompleted( project: Project, module: ModuleDescriptor, @@ -63,13 +71,20 @@ abstract class AbstractAnnotationProcessingExtension( if (annotationProcessingComplete) { return null } - + val processors = loadAnnotationProcessors() - if (processors.isEmpty()) return null + if (processors.isEmpty()) { + log { "No annotation processors detected, exiting" } + return null + } + + log { "Analysing Kotlin files: " + files.map { it.virtualFile.path } } val analysisContext = AnalysisContext(hashMapOf()) analysisContext.analyzeFiles(files) + log { "Analysing Java source roots: $javaSourceRoots" } + val psiManager = PsiManager.getInstance(project) for (javaSourceRoot in javaSourceRoots) { javaSourceRoot.walk().filter { it.isFile && it.extension == "java" }.forEach { @@ -84,19 +99,21 @@ abstract class AbstractAnnotationProcessingExtension( } val options = emptyMap() + log { "Options: $options" } val javaPsiFacade = JavaPsiFacade.getInstance(project) val projectScope = GlobalSearchScope.projectScope(project) val filer = KotlinFiler(generatedSourcesOutputDir, classesOutputDir) - val messages = KotlinMessager() val types = KotlinTypes(javaPsiFacade, PsiManager.getInstance(project), projectScope) val elements = KotlinElements(javaPsiFacade, projectScope) - val processingEnvironment = KotlinProcessingEnvironment(elements, types, messages, options, filer) + val processingEnvironment = KotlinProcessingEnvironment(elements, types, messager, options, filer) processors.forEach { it.init(processingEnvironment) } - // Round 1 + log { "Initialized processors: " + processors.joinToString { it.javaClass.name } } + + log { "Starting round 1" } val round1Environment = KotlinRoundEnvironment(analysisContext) for (processor in processors) { val supportedAnnotationNames = processor.supportedAnnotationTypes @@ -107,20 +124,31 @@ abstract class AbstractAnnotationProcessingExtension( false -> processor.supportedAnnotationTypes.filter { it in analysisContext.annotationsMap } } - if (applicableAnnotationNames.isEmpty()) continue + if (applicableAnnotationNames.isEmpty()) { + log { "Skipping processor " + processor.javaClass.name + ": no relevant annotations" } + continue + } val applicableAnnotations = applicableAnnotationNames .map { javaPsiFacade.findClass(it, projectScope)?.let { JeTypeElement(it) } } .filterNotNullTo(hashSetOf()) + + log { + val annotationNames = applicableAnnotations.joinToString { it.qualifiedName.toString() } + "Processing with " + processor.javaClass.name + " (annotations: " + annotationNames + ")" + } processor.process(applicableAnnotations, round1Environment) } - // Round 2 + log { "Starting round 2 (final)" } val round2Environment = KotlinRoundEnvironment(AnalysisContext(hashMapOf()), isProcessingOver = true) for (processor in processors) { processor.process(emptySet(), round2Environment) } + + fun Int.count(noun: String) = if (this == 1) "$this $noun" else "$this ${noun}s" + log { "Annotation processing complete, ${messager.errorCount.count("error")}, ${messager.warningCount.count("warning")}" } annotationProcessingComplete = true return AnalysisResult.RetryWithAdditionalJavaRoots(bindingContext, module, listOf(generatedSourcesOutputDir)) diff --git a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingPlugin.kt b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingPlugin.kt index 80823dbc538..9e9ffe8b641 100755 --- a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingPlugin.kt +++ b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingPlugin.kt @@ -37,6 +37,9 @@ object AnnotationProcessingConfigurationKeys { val ANNOTATION_PROCESSOR_CLASSPATH: CompilerConfigurationKey> = CompilerConfigurationKey.create>("annotation processor classpath") + + val VERBOSE_MODE: CompilerConfigurationKey = + CompilerConfigurationKey.create("verbose mode") } class AnnotationProcessingCommandLineProcessor : CommandLineProcessor { @@ -52,12 +55,15 @@ class AnnotationProcessingCommandLineProcessor : CommandLineProcessor { val ANNOTATION_PROCESSOR_CLASSPATH_OPTION: CliOption = CliOption("apclasspath", "", "Annotation processor classpath", required = false, allowMultipleOccurrences = true) + + val VERBOSE_MODE_OPTION: CliOption = + CliOption("verbose", "true | false", "Enable verbose output", required = false) } override val pluginId: String = ANNOTATION_PROCESSING_COMPILER_PLUGIN_ID override val pluginOptions: Collection = - listOf(GENERATED_OUTPUT_DIR_OPTION, ANNOTATION_PROCESSOR_CLASSPATH_OPTION, CLASS_FILES_OUTPUT_DIR_OPTION) + listOf(GENERATED_OUTPUT_DIR_OPTION, ANNOTATION_PROCESSOR_CLASSPATH_OPTION, CLASS_FILES_OUTPUT_DIR_OPTION, VERBOSE_MODE_OPTION) override fun processOption(option: CliOption, value: String, configuration: CompilerConfiguration) { when (option) { @@ -68,6 +74,7 @@ class AnnotationProcessingCommandLineProcessor : CommandLineProcessor { } GENERATED_OUTPUT_DIR_OPTION -> configuration.put(AnnotationProcessingConfigurationKeys.GENERATED_OUTPUT_DIR, value) CLASS_FILES_OUTPUT_DIR_OPTION -> configuration.put(AnnotationProcessingConfigurationKeys.CLASS_FILES_OUTPUT_DIR, value) + VERBOSE_MODE_OPTION -> configuration.put(AnnotationProcessingConfigurationKeys.VERBOSE_MODE, value) else -> throw CliOptionProcessingException("Unknown option: ${option.name}") } } @@ -88,8 +95,10 @@ class AnnotationProcessingComponentRegistrar : ComponentRegistrar { val classesOutputDir = File(configuration.get(AnnotationProcessingConfigurationKeys.CLASS_FILES_OUTPUT_DIR) ?: configuration[JVMConfigurationKeys.MODULES]!!.first().getOutputDirectory()) + val verboseOutput = configuration.get(AnnotationProcessingConfigurationKeys.VERBOSE_MODE) == "true" + val annotationProcessingExtension = ClasspathBasedAnnotationProcessingExtension( - classpath, generatedOutputDirFile, classesOutputDir, javaRoots) + classpath, generatedOutputDirFile, classesOutputDir, javaRoots, verboseOutput) AnalysisCompletedHandlerExtension.registerExtension(project, annotationProcessingExtension) } } \ No newline at end of file diff --git a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinMessager.kt b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinMessager.kt index d6f5f4396bc..7f4b81cc2b1 100644 --- a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinMessager.kt +++ b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinMessager.kt @@ -24,6 +24,12 @@ import javax.tools.Diagnostic import javax.tools.Diagnostic.Kind class KotlinMessager : Messager { + var errorCount: Int = 0 + private set + + var warningCount: Int = 0 + private set + override fun printMessage(kind: Diagnostic.Kind, msg: CharSequence) = printMessage(kind, msg, null) override fun printMessage(kind: Diagnostic.Kind, msg: CharSequence, e: Element?) = printMessage(kind, msg, e, null) @@ -34,7 +40,14 @@ class KotlinMessager : Messager { override fun printMessage(kind: Diagnostic.Kind, msg: CharSequence, e: Element?, a: AnnotationMirror?, v: AnnotationValue?) { val output = when (kind) { - Kind.ERROR, Kind.WARNING, Kind.MANDATORY_WARNING -> System.err + Kind.ERROR -> { + errorCount++ + System.err + } + Kind.WARNING, Kind.MANDATORY_WARNING -> { + warningCount++ + System.err + } else -> System.out } output.println(msg) diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/AbstractProcessorTest.kt b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/AbstractProcessorTest.kt index 1399dfec5b5..f5154856fd8 100755 --- a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/AbstractProcessorTest.kt +++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/AbstractProcessorTest.kt @@ -40,7 +40,7 @@ import javax.lang.model.element.* class AnnotationProcessingExtensionForTests( val processors: List -) : AbstractAnnotationProcessingExtension(createTempDir(), createTempDir(), listOf()) { +) : AbstractAnnotationProcessingExtension(createTempDir(), createTempDir(), listOf(), true) { override fun loadAnnotationProcessors() = processors private companion object {