kapt: Move class generation methods to core plugin
This commit is contained in:
+67
@@ -0,0 +1,67 @@
|
|||||||
|
package org.jetbrains.kotlin.gradle.tasks.kapt
|
||||||
|
|
||||||
|
import org.jetbrains.org.objectweb.asm.*
|
||||||
|
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/*
|
||||||
|
This file should be a part of AnnotationProcessingManager in kotlin-gradle-plugin,
|
||||||
|
but org.jetbrains.org.objectweb.asm can't be used there.
|
||||||
|
*/
|
||||||
|
|
||||||
|
private fun generateKotlinAptAnnotation(outputDirectory: File): File {
|
||||||
|
val packageName = "__gen"
|
||||||
|
val className = "KotlinAptAnnotation"
|
||||||
|
val classFqName = "$packageName/$className"
|
||||||
|
|
||||||
|
val bytes = with (ClassWriter(0)) {
|
||||||
|
visit(49, ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE + ACC_ANNOTATION, classFqName,
|
||||||
|
null, null, arrayOf("java/lang/annotation/Annotation"))
|
||||||
|
visitSource(null, null)
|
||||||
|
visitEnd()
|
||||||
|
toByteArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
val injectPackage = File(outputDirectory, packageName)
|
||||||
|
injectPackage.mkdirs()
|
||||||
|
val outputFile = File(injectPackage, "$className.class")
|
||||||
|
outputFile.writeBytes(bytes)
|
||||||
|
|
||||||
|
return outputFile
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateAnnotationProcessorWrapper(
|
||||||
|
processorFqName: String,
|
||||||
|
packageName: String,
|
||||||
|
outputDirectory: File,
|
||||||
|
className: String,
|
||||||
|
taskQualifier: String
|
||||||
|
): File {
|
||||||
|
val classFqName = "$packageName/$className"
|
||||||
|
|
||||||
|
val bytes = with (ClassWriter(0)) {
|
||||||
|
val superClass = "org/jetbrains/kotlin/annotation/AnnotationProcessorWrapper"
|
||||||
|
|
||||||
|
visit(49, ACC_PUBLIC + ACC_SUPER, classFqName, null,
|
||||||
|
superClass, null)
|
||||||
|
|
||||||
|
visitSource(null, null)
|
||||||
|
|
||||||
|
with (visitMethod(ACC_PUBLIC, "<init>", "()V", null, null)) {
|
||||||
|
visitVarInsn(ALOAD, 0)
|
||||||
|
visitLdcInsn(processorFqName)
|
||||||
|
visitLdcInsn(taskQualifier)
|
||||||
|
visitMethodInsn(INVOKESPECIAL, superClass, "<init>", "(Ljava/lang/String;Ljava/lang/String;)V", false)
|
||||||
|
visitInsn(RETURN)
|
||||||
|
visitMaxs(3 /*max stack*/, 1 /*max locals*/)
|
||||||
|
visitEnd()
|
||||||
|
}
|
||||||
|
|
||||||
|
visitEnd()
|
||||||
|
toByteArray()
|
||||||
|
}
|
||||||
|
val outputFile = File(outputDirectory, "$className.class")
|
||||||
|
outputFile.writeBytes(bytes)
|
||||||
|
|
||||||
|
return outputFile
|
||||||
|
}
|
||||||
+28
-62
@@ -20,8 +20,6 @@ import org.gradle.api.plugins.ExtraPropertiesExtension
|
|||||||
import org.gradle.api.tasks.compile.AbstractCompile
|
import org.gradle.api.tasks.compile.AbstractCompile
|
||||||
import org.gradle.api.tasks.compile.JavaCompile
|
import org.gradle.api.tasks.compile.JavaCompile
|
||||||
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
|
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
|
||||||
import org.objectweb.asm.ClassWriter
|
|
||||||
import org.objectweb.asm.Opcodes.*
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
@@ -30,11 +28,12 @@ import java.util.zip.ZipFile
|
|||||||
|
|
||||||
public class AnnotationProcessingManager(
|
public class AnnotationProcessingManager(
|
||||||
private val task: AbstractCompile,
|
private val task: AbstractCompile,
|
||||||
val javaTask: JavaCompile,
|
private val javaTask: JavaCompile,
|
||||||
val taskQualifier: String,
|
private val taskQualifier: String,
|
||||||
val aptFiles: Set<File>,
|
private val aptFiles: Set<File>,
|
||||||
val aptOutputDir: File,
|
private val aptOutputDir: File,
|
||||||
val aptWorkingDir: File) {
|
private val aptWorkingDir: File,
|
||||||
|
private val coreClassLoader: ClassLoader) {
|
||||||
|
|
||||||
private val project = task.getProject()
|
private val project = task.getProject()
|
||||||
|
|
||||||
@@ -97,13 +96,21 @@ public class AnnotationProcessingManager(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun generateAnnotationProcessorStubs(javaTask: JavaCompile, processorFqNames: Set<String>, outputDir: File) {
|
private fun generateAnnotationProcessorStubs(javaTask: JavaCompile, processorFqNames: Set<String>, outputDir: File) {
|
||||||
generateKotlinAptAnnotation(outputDir)
|
val aptAnnotationFile = invokeCoreKaptMethod("generateKotlinAptAnnotation", outputDir) as File
|
||||||
|
project.getLogger().kotlinDebug("kapt: Stub annotation generated: $aptAnnotationFile")
|
||||||
|
|
||||||
val stubOutputPackageDir = File(outputDir, "__gen")
|
val stubOutputPackageDir = File(outputDir, "__gen")
|
||||||
stubOutputPackageDir.mkdirs()
|
stubOutputPackageDir.mkdirs()
|
||||||
|
|
||||||
for (processor in processorFqNames) {
|
for (processorFqName in processorFqNames) {
|
||||||
generateAnnotationProcessorWrapper(processor, "__gen", stubOutputPackageDir)
|
val wrapperFile = invokeCoreKaptMethod("generateAnnotationProcessorWrapper",
|
||||||
|
processorFqName,
|
||||||
|
"__gen",
|
||||||
|
stubOutputPackageDir,
|
||||||
|
getProcessorStubClassName(processorFqName),
|
||||||
|
taskQualifier) as File
|
||||||
|
|
||||||
|
project.getLogger().kotlinDebug("kapt: Wrapper for $processorFqName generated: $wrapperFile")
|
||||||
}
|
}
|
||||||
|
|
||||||
val annotationProcessorWrapperFqNames = processorFqNames
|
val annotationProcessorWrapperFqNames = processorFqNames
|
||||||
@@ -164,58 +171,6 @@ public class AnnotationProcessingManager(
|
|||||||
getOptions().setCompilerArgs(newCompilerArgs)
|
getOptions().setCompilerArgs(newCompilerArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateKotlinAptAnnotation(outputDirectory: File) {
|
|
||||||
val packageName = "__gen"
|
|
||||||
val className = "KotlinAptAnnotation"
|
|
||||||
val classFqName = "$packageName/$className"
|
|
||||||
|
|
||||||
val bytes = with (ClassWriter(0)) {
|
|
||||||
visit(49, ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE + ACC_ANNOTATION, classFqName,
|
|
||||||
null, null, arrayOf("java/lang/annotation/Annotation"))
|
|
||||||
visitSource(null, null)
|
|
||||||
visitEnd()
|
|
||||||
toByteArray()
|
|
||||||
}
|
|
||||||
|
|
||||||
val injectPackage = File(outputDirectory, packageName)
|
|
||||||
injectPackage.mkdirs()
|
|
||||||
val outputFile = File(injectPackage, "$className.class")
|
|
||||||
outputFile.writeBytes(bytes)
|
|
||||||
|
|
||||||
project.getLogger().kotlinDebug("kapt: Stub annotation generated: $outputFile")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateAnnotationProcessorWrapper(processorFqName: String, packageName: String, outputDirectory: File) {
|
|
||||||
val className = getProcessorStubClassName(processorFqName)
|
|
||||||
val classFqName = "$packageName/$className"
|
|
||||||
|
|
||||||
val bytes = with (ClassWriter(0)) {
|
|
||||||
val superClass = "org/jetbrains/kotlin/annotation/AnnotationProcessorWrapper"
|
|
||||||
|
|
||||||
visit(49, ACC_PUBLIC + ACC_SUPER, classFqName, null,
|
|
||||||
superClass, null)
|
|
||||||
|
|
||||||
visitSource(null, null)
|
|
||||||
|
|
||||||
with (visitMethod(ACC_PUBLIC, "<init>", "()V", null, null)) {
|
|
||||||
visitVarInsn(ALOAD, 0)
|
|
||||||
visitLdcInsn(processorFqName)
|
|
||||||
visitLdcInsn(taskQualifier)
|
|
||||||
visitMethodInsn(INVOKESPECIAL, superClass, "<init>", "(Ljava/lang/String;Ljava/lang/String;)V", false)
|
|
||||||
visitInsn(RETURN)
|
|
||||||
visitMaxs(3 /*max stack*/, 1 /*max locals*/)
|
|
||||||
visitEnd()
|
|
||||||
}
|
|
||||||
|
|
||||||
visitEnd()
|
|
||||||
toByteArray()
|
|
||||||
}
|
|
||||||
val outputFile = File(outputDirectory, "$className.class")
|
|
||||||
outputFile.writeBytes(bytes)
|
|
||||||
|
|
||||||
project.getLogger().kotlinDebug("kapt: Wrapper for $processorFqName generated: $outputFile")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun lookupAnnotationProcessors(files: Set<File>): Set<String> {
|
private fun lookupAnnotationProcessors(files: Set<File>): Set<String> {
|
||||||
fun withZipFile(file: File, job: (ZipFile) -> Unit) {
|
fun withZipFile(file: File, job: (ZipFile) -> Unit) {
|
||||||
var zipFile: ZipFile? = null
|
var zipFile: ZipFile? = null
|
||||||
@@ -261,4 +216,15 @@ public class AnnotationProcessingManager(
|
|||||||
return annotationProcessors
|
return annotationProcessors
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun invokeCoreKaptMethod(methodName: String, vararg args: Any): Any {
|
||||||
|
val array = arrayOfNulls<Class<*>>(args.size())
|
||||||
|
args.forEachIndexed { i, arg -> array[i] = arg.javaClass }
|
||||||
|
val method = getCoreKaptPackageClass().getMethod(methodName, *array)
|
||||||
|
return method.invoke(null, *args)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getCoreKaptPackageClass(): Class<*> {
|
||||||
|
return Class.forName("org.jetbrains.kotlin.gradle.tasks.kapt.KaptPackage", false, coreClassLoader)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+3
-2
@@ -165,7 +165,7 @@ class Kotlin2JvmSourceSetProcessor(
|
|||||||
val (aptOutputDir, aptWorkingDir) = project.getAptDirsForSourceSet(kotlinTask, sourceSetName)
|
val (aptOutputDir, aptWorkingDir) = project.getAptDirsForSourceSet(kotlinTask, sourceSetName)
|
||||||
|
|
||||||
val kaptManager = AnnotationProcessingManager(kotlinTask, javaTask, sourceSetName,
|
val kaptManager = AnnotationProcessingManager(kotlinTask, javaTask, sourceSetName,
|
||||||
aptConfiguration.resolve(), aptOutputDir, aptWorkingDir)
|
aptConfiguration.resolve(), aptOutputDir, aptWorkingDir, tasksProvider.tasksLoader)
|
||||||
|
|
||||||
project.initKapt(kotlinTask, javaTask, kaptManager, sourceSetName, kotlinDestinationDir) {
|
project.initKapt(kotlinTask, javaTask, kaptManager, sourceSetName, kotlinDestinationDir) {
|
||||||
createKotlinCompileTask(it)
|
createKotlinCompileTask(it)
|
||||||
@@ -437,7 +437,8 @@ open class KotlinAndroidPlugin [Inject] (val scriptHandler: ScriptHandler, val t
|
|||||||
|
|
||||||
if (javaTask is JavaCompile && aptFiles.isNotEmpty()) {
|
if (javaTask is JavaCompile && aptFiles.isNotEmpty()) {
|
||||||
val kaptManager = AnnotationProcessingManager(kotlinTask, javaTask, variantDataName,
|
val kaptManager = AnnotationProcessingManager(kotlinTask, javaTask, variantDataName,
|
||||||
aptFiles.toSet(), aptOutputDir, aptWorkingDir)
|
aptFiles.toSet(), aptOutputDir, aptWorkingDir, tasksProvider.tasksLoader)
|
||||||
|
|
||||||
kotlinTask.storeKaptAnnotationsFile(kaptManager)
|
kotlinTask.storeKaptAnnotationsFile(kaptManager)
|
||||||
|
|
||||||
project.initKapt(kotlinTask, javaTask, kaptManager, variantDataName, kotlinOutputDir, subpluginEnvironment) {
|
project.initKapt(kotlinTask, javaTask, kaptManager, variantDataName, kotlinOutputDir, subpluginEnvironment) {
|
||||||
|
|||||||
Reference in New Issue
Block a user