diff --git a/libraries/tools/kotlin-annotation-processing/src/main/kotlin/org/jetbrains/kotlin/annotation/AnnotationProcessorWrapper.kt b/libraries/tools/kotlin-annotation-processing/src/main/kotlin/org/jetbrains/kotlin/annotation/AnnotationProcessorWrapper.kt index dec2c68a12c..4f38d40eb30 100644 --- a/libraries/tools/kotlin-annotation-processing/src/main/kotlin/org/jetbrains/kotlin/annotation/AnnotationProcessorWrapper.kt +++ b/libraries/tools/kotlin-annotation-processing/src/main/kotlin/org/jetbrains/kotlin/annotation/AnnotationProcessorWrapper.kt @@ -108,8 +108,8 @@ public abstract class AnnotationProcessorWrapper( override fun process(annotations: MutableSet?, roundEnv: RoundEnvironment): Boolean { roundCounter += 1 - val annotatedKotlinElements = kotlinAnnotationsProvider.annotatedKotlinElements - val roundEnvironmentWrapper = RoundEnvironmentWrapper(processingEnv, roundEnv, roundCounter, annotatedKotlinElements) + val roundEnvironmentWrapper = RoundEnvironmentWrapper( + processingEnv, roundEnv, roundCounter, kotlinAnnotationsProvider) processor.process(annotations, roundEnvironmentWrapper) return false } diff --git a/libraries/tools/kotlin-annotation-processing/src/main/kotlin/org/jetbrains/kotlin/annotation/KotlinAnnotationProvider.kt b/libraries/tools/kotlin-annotation-processing/src/main/kotlin/org/jetbrains/kotlin/annotation/KotlinAnnotationProvider.kt index d4b44b19089..bd7fe065133 100644 --- a/libraries/tools/kotlin-annotation-processing/src/main/kotlin/org/jetbrains/kotlin/annotation/KotlinAnnotationProvider.kt +++ b/libraries/tools/kotlin-annotation-processing/src/main/kotlin/org/jetbrains/kotlin/annotation/KotlinAnnotationProvider.kt @@ -20,7 +20,6 @@ import java.io.File import java.io.Reader import java.io.StringReader import javax.tools.FileObject -import kotlin.properties.Delegates public abstract class KotlinAnnotationProvider { @@ -31,12 +30,22 @@ public abstract class KotlinAnnotationProvider { val SHORTENED_ANNOTATION = "a" val SHORTENED_PACKAGE_NAME = "p" + + val CLASS_DECLARATION = "d" } - public val annotatedKotlinElements: Map> by Delegates.lazy { + public val annotatedKotlinElements: Map> by lazy { readAnnotations() } + private val kotlinClassesInternal = hashSetOf() + + public val kotlinClasses: Set + get() = kotlinClassesInternal + + public val supportInheritedAnnotations: Boolean + get() = kotlinClassesInternal.isNotEmpty() + protected abstract val serializedAnnotations: Reader private fun readAnnotations(): MutableMap> { @@ -65,6 +74,10 @@ public abstract class KotlinAnnotationProvider { when (type) { SHORTENED_ANNOTATION -> handleShortenedName(shortenedAnnotationCache, lineParts) SHORTENED_PACKAGE_NAME -> handleShortenedName(shortenedPackageNameCache, lineParts) + CLASS_DECLARATION -> { + val classFqName = expandClassName(lineParts[1]).replace('$', '.') + kotlinClassesInternal.add(classFqName) + } ANNOTATED_CLASS, ANNOTATED_FIELD, ANNOTATED_METHOD -> { val annotationName = expandAnnotation(lineParts[1]) diff --git a/libraries/tools/kotlin-annotation-processing/src/main/kotlin/org/jetbrains/kotlin/annotation/RoundEnvironmentWrapper.kt b/libraries/tools/kotlin-annotation-processing/src/main/kotlin/org/jetbrains/kotlin/annotation/RoundEnvironmentWrapper.kt index c6571d1dc52..3c02d7d1325 100644 --- a/libraries/tools/kotlin-annotation-processing/src/main/kotlin/org/jetbrains/kotlin/annotation/RoundEnvironmentWrapper.kt +++ b/libraries/tools/kotlin-annotation-processing/src/main/kotlin/org/jetbrains/kotlin/annotation/RoundEnvironmentWrapper.kt @@ -1,16 +1,19 @@ package org.jetbrains.kotlin.annotation +import java.lang.annotation.Inherited import javax.annotation.processing.ProcessingEnvironment import javax.annotation.processing.RoundEnvironment import javax.lang.model.element.Element import javax.lang.model.element.ElementKind import javax.lang.model.element.TypeElement +import javax.lang.model.type.NoType +import javax.lang.model.type.TypeVisitor private class RoundEnvironmentWrapper( val processingEnv: ProcessingEnvironment, val parent: RoundEnvironment, val roundNumber: Int, - val annotatedElementDescriptors: Map> + val kotlinAnnotationsProvider: KotlinAnnotationProvider ) : RoundEnvironment { override fun getRootElements(): MutableSet? { @@ -45,11 +48,23 @@ private class RoundEnvironmentWrapper( return getAnnotationMirrors().any { annotationFqName == it.getAnnotationType().asElement().toString() } } + private fun TypeElement.hasInheritedAnnotation(annotationFqName: String): Boolean { + if (hasAnnotation(annotationFqName)) return true + + val superclassMirror = getSuperclass() + if (superclassMirror is NoType) return false + + val superClass = processingEnv.getTypeUtils().asElement(superclassMirror) + if (superClass !is TypeElement) return false + + return superClass.hasInheritedAnnotation(annotationFqName) + } + private fun resolveKotlinElements(annotationFqName: String): Set { if (roundNumber > 1) return setOf() - val descriptors = annotatedElementDescriptors.get(annotationFqName) ?: setOf() - return descriptors.fold(hashSetOf()) { set, descriptor -> + val descriptors = kotlinAnnotationsProvider.annotatedKotlinElements.get(annotationFqName) ?: setOf() + val descriptorsWithKotlin = descriptors.fold(hashSetOf()) { set, descriptor -> val clazz = processingEnv.getElementUtils().getTypeElement(descriptor.classFqName) ?: return@fold set when (descriptor) { is AnnotatedClassDescriptor -> set.add(clazz) @@ -68,5 +83,21 @@ private class RoundEnvironmentWrapper( } set } + + if (kotlinAnnotationsProvider.supportInheritedAnnotations) { + val isInherited = processingEnv.getElementUtils().getTypeElement(annotationFqName) + ?.hasAnnotation(javaClass().getCanonicalName()) ?: false + + if (isInherited) { + kotlinAnnotationsProvider.kotlinClasses.forEach { classFqName -> + val clazz = processingEnv.getElementUtils().getTypeElement(classFqName) ?: return@forEach + if (clazz.hasInheritedAnnotation(annotationFqName)) { + descriptorsWithKotlin.add(clazz) + } + } + } + } + + return descriptorsWithKotlin } }