From 853cfdb70b9a41d24c101e651b848279bf10048c Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Tue, 9 Jun 2015 21:04:56 +0300 Subject: [PATCH] kapt: Move class generation methods to core plugin --- .../tasks/kapt/kaptStubGeneratorUtils.kt | 67 ++++++++++++++ .../internal/AnnotationProcessingManager.kt | 90 ++++++------------- .../kotlin/gradle/plugin/KotlinPlugin.kt | 5 +- 3 files changed, 98 insertions(+), 64 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/kapt/kaptStubGeneratorUtils.kt diff --git a/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/kapt/kaptStubGeneratorUtils.kt b/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/kapt/kaptStubGeneratorUtils.kt new file mode 100644 index 00000000000..c80be5ab2d9 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/kapt/kaptStubGeneratorUtils.kt @@ -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, "", "()V", null, null)) { + visitVarInsn(ALOAD, 0) + visitLdcInsn(processorFqName) + visitLdcInsn(taskQualifier) + visitMethodInsn(INVOKESPECIAL, superClass, "", "(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 +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/AnnotationProcessingManager.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/AnnotationProcessingManager.kt index e415bd007c5..eb16446be06 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/AnnotationProcessingManager.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/AnnotationProcessingManager.kt @@ -20,8 +20,6 @@ import org.gradle.api.plugins.ExtraPropertiesExtension import org.gradle.api.tasks.compile.AbstractCompile import org.gradle.api.tasks.compile.JavaCompile import org.jetbrains.kotlin.gradle.plugin.kotlinDebug -import org.objectweb.asm.ClassWriter -import org.objectweb.asm.Opcodes.* import java.io.File import java.io.IOException import java.lang.ref.WeakReference @@ -30,11 +28,12 @@ import java.util.zip.ZipFile public class AnnotationProcessingManager( private val task: AbstractCompile, - val javaTask: JavaCompile, - val taskQualifier: String, - val aptFiles: Set, - val aptOutputDir: File, - val aptWorkingDir: File) { + private val javaTask: JavaCompile, + private val taskQualifier: String, + private val aptFiles: Set, + private val aptOutputDir: File, + private val aptWorkingDir: File, + private val coreClassLoader: ClassLoader) { private val project = task.getProject() @@ -97,13 +96,21 @@ public class AnnotationProcessingManager( } private fun generateAnnotationProcessorStubs(javaTask: JavaCompile, processorFqNames: Set, outputDir: File) { - generateKotlinAptAnnotation(outputDir) + val aptAnnotationFile = invokeCoreKaptMethod("generateKotlinAptAnnotation", outputDir) as File + project.getLogger().kotlinDebug("kapt: Stub annotation generated: $aptAnnotationFile") val stubOutputPackageDir = File(outputDir, "__gen") stubOutputPackageDir.mkdirs() - for (processor in processorFqNames) { - generateAnnotationProcessorWrapper(processor, "__gen", stubOutputPackageDir) + for (processorFqName in processorFqNames) { + val wrapperFile = invokeCoreKaptMethod("generateAnnotationProcessorWrapper", + processorFqName, + "__gen", + stubOutputPackageDir, + getProcessorStubClassName(processorFqName), + taskQualifier) as File + + project.getLogger().kotlinDebug("kapt: Wrapper for $processorFqName generated: $wrapperFile") } val annotationProcessorWrapperFqNames = processorFqNames @@ -164,58 +171,6 @@ public class AnnotationProcessingManager( 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, "", "()V", null, null)) { - visitVarInsn(ALOAD, 0) - visitLdcInsn(processorFqName) - visitLdcInsn(taskQualifier) - visitMethodInsn(INVOKESPECIAL, superClass, "", "(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): Set { fun withZipFile(file: File, job: (ZipFile) -> Unit) { var zipFile: ZipFile? = null @@ -261,4 +216,15 @@ public class AnnotationProcessingManager( return annotationProcessors } + private fun invokeCoreKaptMethod(methodName: String, vararg args: Any): Any { + val array = arrayOfNulls>(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) + } + } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt index fc48e558634..bb1db74584d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt @@ -165,7 +165,7 @@ class Kotlin2JvmSourceSetProcessor( val (aptOutputDir, aptWorkingDir) = project.getAptDirsForSourceSet(kotlinTask, sourceSetName) val kaptManager = AnnotationProcessingManager(kotlinTask, javaTask, sourceSetName, - aptConfiguration.resolve(), aptOutputDir, aptWorkingDir) + aptConfiguration.resolve(), aptOutputDir, aptWorkingDir, tasksProvider.tasksLoader) project.initKapt(kotlinTask, javaTask, kaptManager, sourceSetName, kotlinDestinationDir) { createKotlinCompileTask(it) @@ -437,7 +437,8 @@ open class KotlinAndroidPlugin [Inject] (val scriptHandler: ScriptHandler, val t if (javaTask is JavaCompile && aptFiles.isNotEmpty()) { val kaptManager = AnnotationProcessingManager(kotlinTask, javaTask, variantDataName, - aptFiles.toSet(), aptOutputDir, aptWorkingDir) + aptFiles.toSet(), aptOutputDir, aptWorkingDir, tasksProvider.tasksLoader) + kotlinTask.storeKaptAnnotationsFile(kaptManager) project.initKapt(kotlinTask, javaTask, kaptManager, variantDataName, kotlinOutputDir, subpluginEnvironment) {