From 09c3bd869943e3ad6ce35f8503655a0ab35387d0 Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Tue, 23 Jun 2015 16:45:09 +0300 Subject: [PATCH] kapt: Support inherited annotations in Kotlin plugin --- .../AnnotationCollectorExtension.kt | 35 +++++++++++++++---- .../annotation/AnnotationCollectorPlugin.kt | 16 +++++++-- .../AbstractAnnotationProcessorBoxTest.kt | 6 ++-- 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/plugins/annotation-collector/src/org/jetbrains/kotlin/annotation/AnnotationCollectorExtension.kt b/plugins/annotation-collector/src/org/jetbrains/kotlin/annotation/AnnotationCollectorExtension.kt index 0fc57f6dfbe..b49e063f65b 100644 --- a/plugins/annotation-collector/src/org/jetbrains/kotlin/annotation/AnnotationCollectorExtension.kt +++ b/plugins/annotation-collector/src/org/jetbrains/kotlin/annotation/AnnotationCollectorExtension.kt @@ -33,7 +33,7 @@ import java.util.regex.Pattern import java.util.regex.PatternSyntaxException import kotlin.properties.Delegates -public abstract class AnnotationCollectorExtensionBase() : ClassBuilderInterceptorExtension { +public abstract class AnnotationCollectorExtensionBase(val supportInheritedAnnotations: Boolean) : ClassBuilderInterceptorExtension { private object RecordTypes { val ANNOTATED_CLASS = "c" @@ -42,6 +42,8 @@ public abstract class AnnotationCollectorExtensionBase() : ClassBuilderIntercept val SHORTENED_ANNOTATION = "a" val SHORTENED_PACKAGE_NAME = "p" + + val CLASS_DECLARATION = "d" } protected abstract val annotationFilterList: List? @@ -126,8 +128,15 @@ public abstract class AnnotationCollectorExtensionBase() : ClassBuilderIntercept superName: String, interfaces: Array ) { - currentClassSimpleName = name.substringAfterLast('/') - currentPackageName = name.substringBeforeLast('/', "").replace('/', '.') + val currentClassSimpleName = name.substringAfterLast('/') + val currentPackageName = name.substringBeforeLast('/', "").replace('/', '.') + + this.currentClassSimpleName = currentClassSimpleName + this.currentPackageName = currentPackageName + + if (supportInheritedAnnotations) { + recordClass(currentPackageName, currentClassSimpleName) + } super.defineClass(origin, version, access, name, signature, superName, interfaces) } @@ -170,6 +179,15 @@ public abstract class AnnotationCollectorExtensionBase() : ClassBuilderIntercept else !annotationFqName.startsWith("kotlin.jvm.internal.") //apply to all } + private fun recordClass(packageName: String, className: String) { + val packageNameId = if (!packageName.isEmpty()) + shortenedPackageNameCache.save(packageName, writer) + else null + + val outputClassName = getOutputClassName(packageNameId, className) + writer.write("${RecordTypes.CLASS_DECLARATION} $outputClassName\n") + } + private fun recordAnnotation(name: String?, type: String, annotationDesc: String) { val annotationFqName = Type.getType(annotationDesc).getClassName() if (!isAnnotationHandled(annotationFqName)) return @@ -183,7 +201,7 @@ public abstract class AnnotationCollectorExtensionBase() : ClassBuilderIntercept else null val className = this.currentClassSimpleName!! - val outputClassName = if (packageNameId == null) className else "$packageNameId/$className" + val outputClassName = getOutputClassName(packageNameId, className) val elementName = if (name != null) " $name" else "" writer.write("$type $annotationId $outputClassName$elementName\n") @@ -193,6 +211,10 @@ public abstract class AnnotationCollectorExtensionBase() : ClassBuilderIntercept } } + private fun getOutputClassName(packageNameId: String?, className: String): String { + return if (packageNameId == null) className else "$packageNameId/$className" + } + private fun String.compilePatternOpt(): Pattern? { return try { Pattern.compile(this) @@ -220,8 +242,9 @@ public abstract class AnnotationCollectorExtensionBase() : ClassBuilderIntercept public class AnnotationCollectorExtension( override val annotationFilterList: List? = null, - val outputFilename: String? = null -) : AnnotationCollectorExtensionBase() { + val outputFilename: String? = null, + supportInheritedAnnotations: Boolean +) : AnnotationCollectorExtensionBase(supportInheritedAnnotations) { private var writerInternal: Writer? = null diff --git a/plugins/annotation-collector/src/org/jetbrains/kotlin/annotation/AnnotationCollectorPlugin.kt b/plugins/annotation-collector/src/org/jetbrains/kotlin/annotation/AnnotationCollectorPlugin.kt index 8043e90d8bb..76f13614d0f 100644 --- a/plugins/annotation-collector/src/org/jetbrains/kotlin/annotation/AnnotationCollectorPlugin.kt +++ b/plugins/annotation-collector/src/org/jetbrains/kotlin/annotation/AnnotationCollectorPlugin.kt @@ -51,6 +51,8 @@ public object AnnotationCollectorConfigurationKeys { CompilerConfigurationKey.create("annotation file name") public val STUBS_PATH: CompilerConfigurationKey = CompilerConfigurationKey.create("stubs output directory") + public val INHERITED: CompilerConfigurationKey = + CompilerConfigurationKey.create("support inherited annotations") } public class AnnotationCollectorCommandLineProcessor : CommandLineProcessor { @@ -64,12 +66,17 @@ public class AnnotationCollectorCommandLineProcessor : CommandLineProcessor { CliOption("output", "", "File in which annotated declarations will be placed", required = false) public val STUBS_PATH_OPTION: CliOption = - CliOption("stubs", "", "Output path for stubs.", required = false) + CliOption("stubs", "", "Output path for stubs", required = false) + + public val INHERITED_ANNOTATIONS_OPTION: CliOption = + CliOption("inherited", "", + "True if collecting Kotlin class names for inherited annotations is needed", required = false) } override val pluginId: String = ANNOTATION_COLLECTOR_COMPILER_PLUGIN_ID - override val pluginOptions: Collection = listOf(ANNOTATION_FILTER_LIST_OPTION, OUTPUT_FILENAME_OPTION, STUBS_PATH_OPTION) + override val pluginOptions: Collection = + listOf(ANNOTATION_FILTER_LIST_OPTION, OUTPUT_FILENAME_OPTION, STUBS_PATH_OPTION, INHERITED_ANNOTATIONS_OPTION) override fun processOption(option: CliOption, value: String, configuration: CompilerConfiguration) { when (option) { @@ -79,6 +86,7 @@ public class AnnotationCollectorCommandLineProcessor : CommandLineProcessor { } OUTPUT_FILENAME_OPTION -> configuration.put(AnnotationCollectorConfigurationKeys.OUTPUT_FILENAME, value) STUBS_PATH_OPTION -> configuration.put(AnnotationCollectorConfigurationKeys.STUBS_PATH, value) + INHERITED_ANNOTATIONS_OPTION -> configuration.put(AnnotationCollectorConfigurationKeys.INHERITED, value) else -> throw CliOptionProcessingException("Unknown option: ${option.name}") } } @@ -86,10 +94,12 @@ public class AnnotationCollectorCommandLineProcessor : CommandLineProcessor { public class AnnotationCollectorComponentRegistrar : ComponentRegistrar { public override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) { + val supportInheritedAnnotations = "true" == (configuration.get(AnnotationCollectorConfigurationKeys.INHERITED) ?: "true") + val annotationFilterList = configuration.get(AnnotationCollectorConfigurationKeys.ANNOTATION_FILTER_LIST) val outputFilename = configuration.get(AnnotationCollectorConfigurationKeys.OUTPUT_FILENAME) if (outputFilename != null) { - val collectorExtension = AnnotationCollectorExtension(annotationFilterList, outputFilename) + val collectorExtension = AnnotationCollectorExtension(annotationFilterList, outputFilename, supportInheritedAnnotations) ClassBuilderInterceptorExtension.registerExtension(project, collectorExtension) } diff --git a/plugins/annotation-collector/test/org/jetbrains/kotlin/annotation/AbstractAnnotationProcessorBoxTest.kt b/plugins/annotation-collector/test/org/jetbrains/kotlin/annotation/AbstractAnnotationProcessorBoxTest.kt index 8c6acf8fb14..f24f713cf10 100644 --- a/plugins/annotation-collector/test/org/jetbrains/kotlin/annotation/AbstractAnnotationProcessorBoxTest.kt +++ b/plugins/annotation-collector/test/org/jetbrains/kotlin/annotation/AbstractAnnotationProcessorBoxTest.kt @@ -55,7 +55,7 @@ public abstract class AbstractAnnotationProcessorBoxTest : CodegenTestCase() { val environment = KotlinCoreEnvironment.createForTests(getTestRootDisposable()!!, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) val project = environment.project - val collectorExtension = AnnotationCollectorExtensionForTests() + val collectorExtension = AnnotationCollectorExtensionForTests(false) ClassBuilderInterceptorExtension.registerExtension(project, collectorExtension) myEnvironment = environment @@ -63,7 +63,9 @@ public abstract class AbstractAnnotationProcessorBoxTest : CodegenTestCase() { return collectorExtension } - private class AnnotationCollectorExtensionForTests : AnnotationCollectorExtensionBase() { + private class AnnotationCollectorExtensionForTests( + supportInheritedAnnotations: Boolean + ) : AnnotationCollectorExtensionBase(supportInheritedAnnotations) { val stringWriter = StringWriter() override fun getWriter(diagnostic: DiagnosticSink) = stringWriter