Kapt3: Write stub class files with metadata (needed for incremental compilation)

This commit is contained in:
Yan Zhulanow
2016-12-28 22:11:05 +03:00
parent 400759826f
commit 5844f3cf1b
2588 changed files with 6270 additions and 14 deletions
@@ -20,9 +20,10 @@ import com.intellij.openapi.project.Project
import com.sun.tools.javac.tree.JCTree
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit
import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.output.outputUtils.writeAll
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.kapt3.diagnostic.ErrorsKapt3
@@ -46,6 +47,7 @@ class ClasspathBasedKapt3Extension(
sourcesOutputDir: File,
classFilesOutputDir: File,
val stubsOutputDir: File?,
val incrementalDataOutputDir: File?,
options: Map<String, String>,
aptOnly: Boolean,
val useLightAnalysis: Boolean,
@@ -97,6 +99,12 @@ class ClasspathBasedKapt3Extension(
File(packageDir, className + ".java").writeText(stub.toString())
}
}
override fun saveIncrementalData(generationState: GenerationState, messageCollector: MessageCollector) {
if (incrementalDataOutputDir != null) {
generationState.factory.writeAll(incrementalDataOutputDir, messageCollector)
}
}
}
abstract class AbstractKapt3Extension(
@@ -144,7 +152,7 @@ abstract class AbstractKapt3Extension(
try {
val javaSourceFiles = collectJavaSourceFiles()
val kotlinSourceStubs = generateKotlinSourceStubs(kaptContext, generationState.typeMapper)
val kotlinSourceStubs = generateKotlinSourceStubs(kaptContext, generationState)
val (annotationProcessingTime) = measureTimeMillis {
kaptContext.doAnnotationProcessing(
@@ -204,15 +212,16 @@ abstract class AbstractKapt3Extension(
return Pair(KaptContext(logger, compiledClasses, origins, options), generationState)
}
private fun generateKotlinSourceStubs(kaptContext: KaptContext, typeMapper: KotlinTypeMapper): JavacList<JCCompilationUnit> {
private fun generateKotlinSourceStubs(kaptContext: KaptContext, generationState: GenerationState): JavacList<JCCompilationUnit> {
val (stubGenerationTime, kotlinSourceStubs) = measureTimeMillis {
ClassFileToSourceStubConverter(kaptContext, typeMapper, generateNonExistentClass = true).convert()
ClassFileToSourceStubConverter(kaptContext, generationState.typeMapper, generateNonExistentClass = true).convert()
}
logger.info { "Java stub generation took $stubGenerationTime ms" }
logger.info { "Stubs for Kotlin classes: " + kotlinSourceStubs.joinToString { it.sourcefile.name } }
saveStubs(kotlinSourceStubs)
saveIncrementalData(generationState, logger.messageCollector)
return kotlinSourceStubs
}
@@ -227,6 +236,8 @@ abstract class AbstractKapt3Extension(
protected abstract fun saveStubs(stubs: JavacList<JCTree.JCCompilationUnit>)
protected abstract fun saveIncrementalData(generationState: GenerationState, messageCollector: MessageCollector)
protected abstract fun loadProcessors(): List<Processor>
}
@@ -57,6 +57,9 @@ object Kapt3ConfigurationKeys {
val STUBS_OUTPUT_DIR: CompilerConfigurationKey<String> =
CompilerConfigurationKey.create<String>("stubs output directory")
val INCREMENTAL_DATA_OUTPUT_DIR: CompilerConfigurationKey<String> =
CompilerConfigurationKey.create<String>("incremental data output directory")
val ANNOTATION_PROCESSOR_CLASSPATH: CompilerConfigurationKey<List<String>> =
CompilerConfigurationKey.create<List<String>>("annotation processor classpath")
@@ -86,6 +89,9 @@ class Kapt3CommandLineProcessor : CommandLineProcessor {
val STUBS_OUTPUT_DIR_OPTION: CliOption =
CliOption("stubs", "<path>", "Output path for the Java stubs", required = false)
val INCREMENTAL_DATA_OUTPUT_DIR_OPTION: CliOption =
CliOption("incrementalData", "<path>", "Output path for the incremental data", required = false)
val ANNOTATION_PROCESSOR_CLASSPATH_OPTION: CliOption =
CliOption("apclasspath", "<classpath>", "Annotation processor classpath",
required = false, allowMultipleOccurrences = true)
@@ -123,6 +129,7 @@ class Kapt3CommandLineProcessor : CommandLineProcessor {
SOURCE_OUTPUT_DIR_OPTION -> configuration.put(Kapt3ConfigurationKeys.SOURCE_OUTPUT_DIR, value)
CLASS_OUTPUT_DIR_OPTION -> configuration.put(Kapt3ConfigurationKeys.CLASS_OUTPUT_DIR, value)
STUBS_OUTPUT_DIR_OPTION -> configuration.put(Kapt3ConfigurationKeys.STUBS_OUTPUT_DIR, value)
INCREMENTAL_DATA_OUTPUT_DIR_OPTION -> configuration.put(Kapt3ConfigurationKeys.INCREMENTAL_DATA_OUTPUT_DIR, value)
VERBOSE_MODE_OPTION -> configuration.put(Kapt3ConfigurationKeys.VERBOSE_MODE, value)
APT_ONLY_OPTION -> configuration.put(Kapt3ConfigurationKeys.APT_ONLY, value)
USE_LIGHT_ANALYSIS_OPTION -> configuration.put(Kapt3ConfigurationKeys.USE_LIGHT_ANALYSIS, value)
@@ -139,10 +146,10 @@ class Kapt3ComponentRegistrar : ComponentRegistrar {
?: PrintingMessageCollector(System.err, MessageRenderer.PLAIN_FULL_PATHS, isVerbose)
val logger = KaptLogger(isVerbose, messageCollector)
val sourcesOutputDir = configuration.get(Kapt3ConfigurationKeys.SOURCE_OUTPUT_DIR)?.let(::File)
val classFilesOutputDir = configuration.get(Kapt3ConfigurationKeys.CLASS_OUTPUT_DIR)?.let(::File)
val stubsOutputDir = configuration.get(Kapt3ConfigurationKeys.STUBS_OUTPUT_DIR)?.let(::File)
val incrementalDataOutputDir = configuration.get(Kapt3ConfigurationKeys.INCREMENTAL_DATA_OUTPUT_DIR)?.let(::File)
val apClasspath = configuration.get(ANNOTATION_PROCESSOR_CLASSPATH)?.map(::File)
@@ -179,6 +186,7 @@ class Kapt3ComponentRegistrar : ComponentRegistrar {
logger.info("Source output directory: $sourcesOutputDir")
logger.info("Classes output directory: $classFilesOutputDir")
logger.info("Stubs output directory: $stubsOutputDir")
logger.info("Incremental data output directory: $incrementalDataOutputDir")
logger.info("Compile classpath: " + compileClasspath.joinToString())
logger.info("Annotation processing classpath: " + apClasspath.joinToString())
logger.info("Java source roots: " + javaSourceRoots.joinToString())
@@ -186,7 +194,8 @@ class Kapt3ComponentRegistrar : ComponentRegistrar {
}
val kapt3AnalysisCompletedHandlerExtension = ClasspathBasedKapt3Extension(
compileClasspath, apClasspath, javaSourceRoots, sourcesOutputDir, classFilesOutputDir, stubsOutputDir, apOptions,
compileClasspath, apClasspath, javaSourceRoots, sourcesOutputDir, classFilesOutputDir,
stubsOutputDir, incrementalDataOutputDir, apOptions,
isAptOnly, useLightAnalysis, System.currentTimeMillis(), logger)
AnalysisHandlerExtension.registerExtension(project, kapt3AnalysisCompletedHandlerExtension)
}
@@ -16,13 +16,14 @@
package org.jetbrains.kotlin.kapt3.util
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.*
import java.io.ByteArrayOutputStream
import java.io.PrintWriter
class KaptLogger(val isVerbose: Boolean, val messageCollector: MessageCollector) {
class KaptLogger(
val isVerbose: Boolean,
val messageCollector: MessageCollector = PrintingMessageCollector(System.err, MessageRenderer.PLAIN_FULL_PATHS, isVerbose)
) {
private companion object {
val PREFIX = "[kapt] "
}
@@ -40,7 +41,7 @@ class KaptLogger(val isVerbose: Boolean, val messageCollector: MessageCollector)
}
fun warn(message: String) {
println(PREFIX + message)
messageCollector.report(CompilerMessageSeverity.WARNING, PREFIX + message, CompilerMessageLocation.NO_LOCATION)
}
fun error(message: String) {
@@ -54,6 +55,5 @@ class KaptLogger(val isVerbose: Boolean, val messageCollector: MessageCollector)
byteArrayOutputStream.toString("UTF-8")
}
messageCollector.report(CompilerMessageSeverity.EXCEPTION, PREFIX + "An exception occurred: " + stacktrace, CompilerMessageLocation.NO_LOCATION)
}
}
@@ -20,8 +20,10 @@ import com.intellij.openapi.util.text.StringUtil
import com.sun.tools.javac.tree.JCTree
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.codegen.CodegenTestCase
import org.jetbrains.kotlin.codegen.CodegenTestUtil
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.kapt3.AbstractKapt3Extension
import org.jetbrains.kotlin.kapt3.Kapt3BuilderFactory
import org.jetbrains.kotlin.kapt3.util.KaptLogger
@@ -160,5 +162,7 @@ abstract class AbstractKotlinKapt3IntegrationTest : CodegenTestCase() {
.sortedBy(String::hashCode)
.joinToString(AbstractKotlinKapt3Test.FILE_SEPARATOR)
}
override fun saveIncrementalData(generationState: GenerationState, messageCollector: MessageCollector) {}
}
}