kapt: Support inherited annotations in AP wrapper

This commit is contained in:
Yan Zhulanow
2015-06-23 18:14:27 +03:00
parent afa3ae4439
commit a90f175fc2
3 changed files with 51 additions and 7 deletions
@@ -108,8 +108,8 @@ public abstract class AnnotationProcessorWrapper(
override fun process(annotations: MutableSet<out TypeElement>?, 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
}
@@ -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<String, Set<AnnotatedElementDescriptor>> by Delegates.lazy {
public val annotatedKotlinElements: Map<String, Set<AnnotatedElementDescriptor>> by lazy {
readAnnotations()
}
private val kotlinClassesInternal = hashSetOf<String>()
public val kotlinClasses: Set<String>
get() = kotlinClassesInternal
public val supportInheritedAnnotations: Boolean
get() = kotlinClassesInternal.isNotEmpty()
protected abstract val serializedAnnotations: Reader
private fun readAnnotations(): MutableMap<String, MutableSet<AnnotatedElementDescriptor>> {
@@ -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])
@@ -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<String, Set<AnnotatedElementDescriptor>>
val kotlinAnnotationsProvider: KotlinAnnotationProvider
) : RoundEnvironment {
override fun getRootElements(): MutableSet<out Element>? {
@@ -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<Element> {
if (roundNumber > 1) return setOf()
val descriptors = annotatedElementDescriptors.get(annotationFqName) ?: setOf()
return descriptors.fold(hashSetOf<Element>()) { set, descriptor ->
val descriptors = kotlinAnnotationsProvider.annotatedKotlinElements.get(annotationFqName) ?: setOf()
val descriptorsWithKotlin = descriptors.fold(hashSetOf<Element>()) { 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<Inherited>().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
}
}