Kapt: Support inherited annotations

(cherry picked from commit 02a3e6b)
This commit is contained in:
Yan Zhulanow
2016-08-09 21:24:52 +03:00
committed by Yan Zhulanow
parent 9d340e1b83
commit 8c4fb0a709
14 changed files with 105 additions and 46 deletions
@@ -16,18 +16,19 @@
package org.jetbrains.kotlin.java.model
import com.intellij.psi.PsiAnnotationOwner
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiModifierListOwner
import org.jetbrains.kotlin.java.model.elements.JeAnnotationMirror
import org.jetbrains.kotlin.java.model.internal.KotlinAnnotationProxyMaker
import org.jetbrains.kotlin.java.model.internal.getAnnotationsWithInherited
import javax.lang.model.element.AnnotationMirror
import javax.lang.model.element.Element
import java.lang.reflect.Array as RArray
interface JeAnnotationOwner : Element {
val annotationOwner: PsiAnnotationOwner?
interface JeAnnotationOwner : JeElement {
override val psi: PsiModifierListOwner
override fun getAnnotationMirrors() = annotationOwner?.annotations?.map { JeAnnotationMirror(it) } ?: emptyList()
override fun getAnnotationMirrors() = psi.getAnnotationsWithInherited().map(::JeAnnotationMirror)
override fun <A : Annotation> getAnnotation(annotationClass: Class<A>): A? {
return getAnnotationsByType(annotationClass, onlyFirst = true).firstOrNull()
@@ -49,11 +50,11 @@ interface JeAnnotationOwner : Element {
val annotationFqName = annotationClass.canonicalName
val allAnnotations = annotationOwner?.annotations?.filter { it.qualifiedName == annotationFqName } ?: return emptyList()
val allAnnotations = psi.getAnnotationsWithInherited().filter { it.qualifiedName == annotationFqName }
if (allAnnotations.isEmpty()) return emptyList()
val annotations = if (onlyFirst) listOf(allAnnotations.first()) else allAnnotations
val annotationDeclarations = annotations.map { it to it.nameReferenceElement?.resolve() as? PsiClass }.filter { it.second != null }
@Suppress("UNCHECKED_CAST")
@@ -19,6 +19,6 @@ package org.jetbrains.kotlin.java.model
import com.intellij.psi.PsiElement
import javax.lang.model.element.Element
abstract class JeElement : Element {
abstract val psi: PsiElement
interface JeElement : Element {
val psi: PsiElement
}
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.java.model.types.JeNoneType
import javax.lang.model.element.*
import javax.lang.model.type.TypeMirror
class JeClassInitializerExecutableElement(override val psi: PsiClassInitializer) : JeElement(),
class JeClassInitializerExecutableElement(override val psi: PsiClassInitializer) : JeElement,
ExecutableElement, JeNoAnnotations, JeModifierListOwner
{
val isStaticInitializer = psi.isStatic
@@ -16,10 +16,7 @@
package org.jetbrains.kotlin.java.model.elements
import com.intellij.psi.PsiAnnotationMethod
import com.intellij.psi.PsiAnnotationOwner
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiModifier
import com.intellij.psi.*
import com.intellij.psi.util.PsiTypesUtil
import org.jetbrains.kotlin.java.model.*
import org.jetbrains.kotlin.java.model.internal.isStatic
@@ -29,8 +26,8 @@ import org.jetbrains.kotlin.java.model.types.toJeType
import javax.lang.model.element.*
import javax.lang.model.type.TypeMirror
class JeMethodExecutableElement(override val psi: PsiMethod) : JeElement(), ExecutableElement, JeModifierListOwner, JeAnnotationOwner {
override fun getEnclosingElement() = psi.containingClass?.let { JeTypeElement(it) }
class JeMethodExecutableElement(override val psi: PsiMethod) : JeElement, ExecutableElement, JeModifierListOwner, JeAnnotationOwner {
override fun getEnclosingElement() = psi.containingClass?.let(::JeTypeElement)
override fun getSimpleName(): JeName {
if (psi.isConstructor) return JeName.INIT
@@ -41,7 +38,7 @@ class JeMethodExecutableElement(override val psi: PsiMethod) : JeElement(), Exec
override fun getTypeParameters() = psi.typeParameters.map { JeTypeParameterElement(it, this) }
override fun getParameters() = psi.parameterList.parameters.map { JeVariableElement(it) }
override fun getParameters() = psi.parameterList.parameters.map(::JeVariableElement)
override fun getDefaultValue(): AnnotationValue? {
val annotationMethod = psi as? PsiAnnotationMethod ?: return null
@@ -68,9 +65,6 @@ class JeMethodExecutableElement(override val psi: PsiMethod) : JeElement(), Exec
override fun getEnclosedElements() = emptyList<Element>()
override val annotationOwner: PsiAnnotationOwner?
get() = psi.modifierList
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
@@ -26,7 +26,7 @@ import javax.lang.model.element.ElementKind
import javax.lang.model.element.ElementVisitor
import javax.lang.model.element.PackageElement
class JePackageElement(override val psi: PsiPackage) : JeElement(), PackageElement, JeModifierListOwner, JeNoAnnotations {
class JePackageElement(override val psi: PsiPackage) : JeElement, PackageElement, JeModifierListOwner, JeNoAnnotations {
override fun getEnclosingElement() = null
override fun getSimpleName() = JeName(psi.name)
@@ -39,7 +39,7 @@ class JePackageElement(override val psi: PsiPackage) : JeElement(), PackageEleme
override fun getQualifiedName() = JeName(psi.qualifiedName)
override fun getEnclosedElements() = psi.classes.map { JeTypeElement(it) }
override fun getEnclosedElements() = psi.classes.map(::JeTypeElement)
override fun asType() = JePackageTypeMirror
@@ -25,16 +25,13 @@ import org.jetbrains.kotlin.java.model.types.toJeType
import javax.lang.model.element.*
import javax.lang.model.type.TypeMirror
class JeTypeElement(override val psi: PsiClass) : JeElement(), TypeElement, JeAnnotationOwner, JeModifierListOwner {
class JeTypeElement(override val psi: PsiClass) : JeElement, TypeElement, JeAnnotationOwner, JeModifierListOwner {
override fun getEnclosingElement(): Element? {
psi.containingClass?.let { return JeTypeElement(it) }
val javaFile = psi.containingFile as? PsiJavaFile ?: return null
return JavaPsiFacade.getInstance(psi.project).findPackage(javaFile.packageName)?.let { JePackageElement(it) }
return JavaPsiFacade.getInstance(psi.project).findPackage(javaFile.packageName)?.let(::JePackageElement)
}
override val annotationOwner: PsiAnnotationOwner?
get() = psi.modifierList
override fun getSimpleName() = JeName(psi.name)
override fun getQualifiedName() = JeName(psi.qualifiedName)
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.java.model.elements
import com.intellij.psi.PsiAnnotationOwner
import com.intellij.psi.PsiModifierListOwner
import com.intellij.psi.PsiTypeParameter
import com.intellij.psi.util.PsiTypesUtil
import org.jetbrains.kotlin.java.model.JeAnnotationOwner
@@ -32,7 +33,7 @@ import javax.lang.model.element.TypeParameterElement
class JeTypeParameterElement(
override val psi: PsiTypeParameter,
val parent: JeElement?
) : JeElement(), TypeParameterElement, JeAnnotationOwner, JeModifierListOwner {
) : JeElement, TypeParameterElement, JeAnnotationOwner, JeModifierListOwner {
override fun getSimpleName() = JeName(psi.name)
override fun getEnclosingElement() = parent
@@ -49,9 +50,6 @@ class JeTypeParameterElement(
override fun getGenericElement() = parent
override val annotationOwner: PsiAnnotationOwner?
get() = psi.modifierList
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
@@ -26,7 +26,7 @@ import javax.lang.model.element.ElementKind
import javax.lang.model.element.ElementVisitor
import javax.lang.model.element.VariableElement
class JeVariableElement(override val psi: PsiVariable) : JeElement(), VariableElement, JeModifierListOwner, JeAnnotationOwner {
class JeVariableElement(override val psi: PsiVariable) : JeElement, VariableElement, JeModifierListOwner, JeAnnotationOwner {
override fun getSimpleName() = JeName(psi.name)
override fun getEnclosingElement(): JeElement? {
@@ -35,7 +35,7 @@ class JeVariableElement(override val psi: PsiVariable) : JeElement(), VariableEl
}
val containingClass = (psi as? PsiMember)?.containingClass ?: PsiTreeUtil.getParentOfType(psi, PsiClass::class.java)
return containingClass?.let { JeTypeElement(it) }
return containingClass?.let(::JeTypeElement)
}
override fun getConstantValue() = psi.initializer?.calcConstantValue()
@@ -52,9 +52,6 @@ class JeVariableElement(override val psi: PsiVariable) : JeElement(), VariableEl
override fun getEnclosedElements() = emptyList<Element>()
override val annotationOwner: PsiAnnotationOwner?
get() = psi.modifierList
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
@@ -66,4 +66,33 @@ internal val PsiModifierListOwner.isStatic: Boolean
internal val PsiModifierListOwner.isFinal: Boolean
get() = hasModifierProperty(PsiModifier.FINAL)
fun PsiModifierListOwner.getJavaModifiers() = modifierList?.getJavaModifiers() ?: emptySet()
fun PsiModifierListOwner.getJavaModifiers() = modifierList?.getJavaModifiers() ?: emptySet()
fun PsiModifierListOwner.getAnnotationsWithInherited(): List<PsiAnnotation> {
val annotations = modifierList?.annotations?.toMutableList() ?: mutableListOf()
if (this is PsiClass) {
var superClass = superClass
while (superClass != null) {
superClass.modifierList?.annotations?.let { superClassAnnotations ->
for (annotation in superClassAnnotations) {
// Do not add the inherited annotation from the superclass
// if the current class has an annotation with the same qualified name
if (!annotation.isInherited()
|| annotations.any { it.qualifiedName == annotation.qualifiedName }) continue
annotations += annotation
}
}
superClass = superClass.superClass
}
}
return annotations
}
private fun PsiAnnotation.isInherited(): Boolean {
val annotationClass = nameReferenceElement?.resolve() as? PsiClass ?: return false
val annotations = annotationClass.modifierList?.annotations ?: return false
return annotations.any { it.qualifiedName == "java.lang.annotation.Inherited" }
}