Kapt3: Always write Kotlin stubs to .java files, and make javac always parse them from source files, not from JCTree (in order to support incremental compilation).
This commit is contained in:
committed by
Yan Zhulanow
parent
9b9b36e332
commit
78a3dae314
+1
-1
@@ -180,10 +180,10 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pluginOptions += SubpluginOption("useLightAnalysis", "${kaptExtension.useLightAnalysis}")
|
pluginOptions += SubpluginOption("useLightAnalysis", "${kaptExtension.useLightAnalysis}")
|
||||||
|
pluginOptions += SubpluginOption("stubs", getKaptStubsDir(project, sourceSetName).canonicalPath)
|
||||||
|
|
||||||
if (project.hasProperty(VERBOSE_OPTION_NAME) && project.property(VERBOSE_OPTION_NAME) == "true") {
|
if (project.hasProperty(VERBOSE_OPTION_NAME) && project.property(VERBOSE_OPTION_NAME) == "true") {
|
||||||
pluginOptions += SubpluginOption("verbose", "true")
|
pluginOptions += SubpluginOption("verbose", "true")
|
||||||
pluginOptions += SubpluginOption("stubs", getKaptStubsDir(project, sourceSetName).canonicalPath)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.kapt3
|
|||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.sun.tools.javac.tree.JCTree
|
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.analyzer.AnalysisResult
|
||||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||||
@@ -49,7 +48,7 @@ class ClasspathBasedKapt3Extension(
|
|||||||
javaSourceRoots: List<File>,
|
javaSourceRoots: List<File>,
|
||||||
sourcesOutputDir: File,
|
sourcesOutputDir: File,
|
||||||
classFilesOutputDir: File,
|
classFilesOutputDir: File,
|
||||||
stubsOutputDir: File?,
|
stubsOutputDir: File,
|
||||||
incrementalDataOutputDir: File?,
|
incrementalDataOutputDir: File?,
|
||||||
options: Map<String, String>,
|
options: Map<String, String>,
|
||||||
aptOnly: Boolean,
|
aptOnly: Boolean,
|
||||||
@@ -98,7 +97,7 @@ abstract class AbstractKapt3Extension(
|
|||||||
val javaSourceRoots: List<File>,
|
val javaSourceRoots: List<File>,
|
||||||
val sourcesOutputDir: File,
|
val sourcesOutputDir: File,
|
||||||
val classFilesOutputDir: File,
|
val classFilesOutputDir: File,
|
||||||
val stubsOutputDir: File?,
|
val stubsOutputDir: File,
|
||||||
val incrementalDataOutputDir: File?,
|
val incrementalDataOutputDir: File?,
|
||||||
val options: Map<String, String>,
|
val options: Map<String, String>,
|
||||||
val aptOnly: Boolean,
|
val aptOnly: Boolean,
|
||||||
@@ -141,13 +140,13 @@ abstract class AbstractKapt3Extension(
|
|||||||
val (kaptContext, generationState) = compileStubs(project, module, bindingTrace.bindingContext, files.toList())
|
val (kaptContext, generationState) = compileStubs(project, module, bindingTrace.bindingContext, files.toList())
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
generateKotlinSourceStubs(kaptContext, generationState)
|
||||||
val javaSourceFiles = collectJavaSourceFiles()
|
val javaSourceFiles = collectJavaSourceFiles()
|
||||||
val kotlinSourceStubs = generateKotlinSourceStubs(kaptContext, generationState)
|
|
||||||
|
|
||||||
val (annotationProcessingTime) = measureTimeMillis {
|
val (annotationProcessingTime) = measureTimeMillis {
|
||||||
kaptContext.doAnnotationProcessing(
|
kaptContext.doAnnotationProcessing(
|
||||||
javaSourceFiles, processors, compileClasspath, annotationProcessingClasspath,
|
javaSourceFiles, processors, compileClasspath, annotationProcessingClasspath,
|
||||||
sourcesOutputDir, classFilesOutputDir, kotlinSourceStubs)
|
sourcesOutputDir, classFilesOutputDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info { "Annotation processing took $annotationProcessingTime ms" }
|
logger.info { "Annotation processing took $annotationProcessingTime ms" }
|
||||||
@@ -202,7 +201,7 @@ abstract class AbstractKapt3Extension(
|
|||||||
return Pair(KaptContext(logger, compiledClasses, origins, options), generationState)
|
return Pair(KaptContext(logger, compiledClasses, origins, options), generationState)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateKotlinSourceStubs(kaptContext: KaptContext, generationState: GenerationState): JavacList<JCCompilationUnit> {
|
private fun generateKotlinSourceStubs(kaptContext: KaptContext, generationState: GenerationState) {
|
||||||
val converter = ClassFileToSourceStubConverter(kaptContext, generationState.typeMapper, generateNonExistentClass = true)
|
val converter = ClassFileToSourceStubConverter(kaptContext, generationState.typeMapper, generateNonExistentClass = true)
|
||||||
|
|
||||||
val (stubGenerationTime, kotlinSourceStubs) = measureTimeMillis {
|
val (stubGenerationTime, kotlinSourceStubs) = measureTimeMillis {
|
||||||
@@ -214,11 +213,10 @@ abstract class AbstractKapt3Extension(
|
|||||||
|
|
||||||
saveStubs(kotlinSourceStubs)
|
saveStubs(kotlinSourceStubs)
|
||||||
saveIncrementalData(generationState, logger.messageCollector, converter)
|
saveIncrementalData(generationState, logger.messageCollector, converter)
|
||||||
return kotlinSourceStubs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun collectJavaSourceFiles(): List<File> {
|
private fun collectJavaSourceFiles(): List<File> {
|
||||||
val javaFilesFromJavaSourceRoots = javaSourceRoots.flatMap {
|
val javaFilesFromJavaSourceRoots = (javaSourceRoots + stubsOutputDir).flatMap {
|
||||||
root -> root.walk().filter { it.isFile && it.extension == "java" }.toList()
|
root -> root.walk().filter { it.isFile && it.extension == "java" }.toList()
|
||||||
}
|
}
|
||||||
logger.info { "Java source files: " + javaFilesFromJavaSourceRoots.joinToString { it.canonicalPath } }
|
logger.info { "Java source files: " + javaFilesFromJavaSourceRoots.joinToString { it.canonicalPath } }
|
||||||
@@ -227,12 +225,11 @@ abstract class AbstractKapt3Extension(
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected open fun saveStubs(stubs: JavacList<JCTree.JCCompilationUnit>) {
|
protected open fun saveStubs(stubs: JavacList<JCTree.JCCompilationUnit>) {
|
||||||
val outputDir = stubsOutputDir ?: return
|
|
||||||
for (stub in stubs) {
|
for (stub in stubs) {
|
||||||
val className = (stub.defs.first { it is JCTree.JCClassDecl } as JCTree.JCClassDecl).simpleName.toString()
|
val className = (stub.defs.first { it is JCTree.JCClassDecl } as JCTree.JCClassDecl).simpleName.toString()
|
||||||
|
|
||||||
val packageName = stub.packageName?.toString() ?: ""
|
val packageName = stub.packageName?.toString() ?: ""
|
||||||
val packageDir = if (packageName.isEmpty()) outputDir else File(outputDir, packageName.replace('.', '/'))
|
val packageDir = if (packageName.isEmpty()) stubsOutputDir else File(stubsOutputDir, packageName.replace('.', '/'))
|
||||||
packageDir.mkdirs()
|
packageDir.mkdirs()
|
||||||
File(packageDir, className + ".java").writeText(stub.toString())
|
File(packageDir, className + ".java").writeText(stub.toString())
|
||||||
}
|
}
|
||||||
@@ -246,7 +243,7 @@ abstract class AbstractKapt3Extension(
|
|||||||
|
|
||||||
generationState.factory.writeAll(incrementalDataOutputDir) { file, sources, output ->
|
generationState.factory.writeAll(incrementalDataOutputDir) { file, sources, output ->
|
||||||
val stubFileObject = converter.bindings[file.relativePath.substringBeforeLast(".class", missingDelimiterValue = "")]
|
val stubFileObject = converter.bindings[file.relativePath.substringBeforeLast(".class", missingDelimiterValue = "")]
|
||||||
if (stubFileObject != null && stubsOutputDir != null) {
|
if (stubFileObject != null) {
|
||||||
val stubFile = File(stubsOutputDir, stubFileObject.name)
|
val stubFile = File(stubsOutputDir, stubFileObject.name)
|
||||||
if (stubFile.exists()) {
|
if (stubFile.exists()) {
|
||||||
messageCollector.report(CompilerMessageSeverity.OUTPUT,
|
messageCollector.report(CompilerMessageSeverity.OUTPUT,
|
||||||
|
|||||||
@@ -153,10 +153,16 @@ class Kapt3ComponentRegistrar : ComponentRegistrar {
|
|||||||
|
|
||||||
val apClasspath = configuration.get(ANNOTATION_PROCESSOR_CLASSPATH)?.map(::File)
|
val apClasspath = configuration.get(ANNOTATION_PROCESSOR_CLASSPATH)?.map(::File)
|
||||||
|
|
||||||
if (sourcesOutputDir == null || classFilesOutputDir == null || apClasspath == null) {
|
if (sourcesOutputDir == null || classFilesOutputDir == null || apClasspath == null || stubsOutputDir == null) {
|
||||||
if (isAptOnly) {
|
if (isAptOnly) {
|
||||||
val subject = if (apClasspath == null) "Annotation processing classpath" else "Generated files output directories"
|
val nonExistentOptionName = when {
|
||||||
logger.warn("$subject is not specified, skipping annotation processing")
|
sourcesOutputDir == null -> "Sources output directory"
|
||||||
|
classFilesOutputDir == null -> "Classes output directory"
|
||||||
|
apClasspath == null -> "Annotation processing classpath"
|
||||||
|
stubsOutputDir == null -> "Stubs output directory"
|
||||||
|
else -> throw IllegalStateException()
|
||||||
|
}
|
||||||
|
logger.warn("$nonExistentOptionName is not specified, skipping annotation processing")
|
||||||
AnalysisHandlerExtension.registerExtension(project, AbortAnalysisHandlerExtension())
|
AnalysisHandlerExtension.registerExtension(project, AbortAnalysisHandlerExtension())
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ class KotlinKapt3IntegrationTests : AbstractKotlinKapt3IntegrationTest() {
|
|||||||
|
|
||||||
val bindings = kaptExtension.savedBindings!!
|
val bindings = kaptExtension.savedBindings!!
|
||||||
|
|
||||||
test(stubsOutputDir!!, incrementalDataOutputDir!!, bindings)
|
test(stubsOutputDir, incrementalDataOutputDir!!, bindings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user