Kapt: typeElement.asType() should preserve type parameters and propagate it to its supertypes (KT-13865)

(cherry picked from commit 92c9cea)
This commit is contained in:
Yan Zhulanow
2016-09-21 23:26:58 +03:00
committed by Yan Zhulanow
parent a22721fbd8
commit f83e7509b2
10 changed files with 54 additions and 40 deletions
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.java.model.elements.JeAnnotationMirror
import org.jetbrains.kotlin.java.model.elements.JeMethodExecutableElement import org.jetbrains.kotlin.java.model.elements.JeMethodExecutableElement
import org.jetbrains.kotlin.java.model.elements.JePackageElement import org.jetbrains.kotlin.java.model.elements.JePackageElement
import org.jetbrains.kotlin.java.model.elements.JeTypeElement import org.jetbrains.kotlin.java.model.elements.JeTypeElement
import org.jetbrains.kotlin.java.model.internal.getTypeWithTypeParameters
import java.io.PrintWriter import java.io.PrintWriter
import java.io.Writer import java.io.Writer
import javax.lang.model.element.* import javax.lang.model.element.*
@@ -48,7 +49,7 @@ class KotlinElements(
val hiderMethodClass = hiderMethod.containingClass ?: return false val hiderMethodClass = hiderMethod.containingClass ?: return false
val hiddenMethodClass = hiddenMethod.containingClass ?: return false val hiddenMethodClass = hiddenMethod.containingClass ?: return false
if (PsiTypesUtil.getClassType(hiddenMethodClass) !in hiderMethodClass.superTypes) return false if (hiddenMethodClass.getTypeWithTypeParameters() !in hiderMethodClass.superTypes) return false
return isSubSignature(hiderMethod, hiddenMethod) return isSubSignature(hiderMethod, hiddenMethod)
} }
@@ -148,7 +149,7 @@ class KotlinElements(
private fun PsiClass.isSubclassOf(other: PsiClass?): Boolean { private fun PsiClass.isSubclassOf(other: PsiClass?): Boolean {
if (other == null) return false if (other == null) return false
return TypeConversionUtil.isAssignable(PsiTypesUtil.getClassType(other), PsiTypesUtil.getClassType(this), false) return TypeConversionUtil.isAssignable(other.getTypeWithTypeParameters(), this.getTypeWithTypeParameters(), false)
} }
private fun isSubSignature(childMethod: PsiMethod, superMethod: PsiMethod): Boolean { private fun isSubSignature(childMethod: PsiMethod, superMethod: PsiMethod): Boolean {
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.annotation.processing.impl
import com.intellij.openapi.Disposable import com.intellij.openapi.Disposable
import com.intellij.psi.* import com.intellij.psi.*
import com.intellij.psi.impl.source.PsiImmediateClassType
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.* import com.intellij.psi.util.*
import org.jetbrains.kotlin.java.model.JeElement import org.jetbrains.kotlin.java.model.JeElement
@@ -135,10 +134,6 @@ class KotlinTypes(
override fun directSupertypes(t: TypeMirror): List<TypeMirror> { override fun directSupertypes(t: TypeMirror): List<TypeMirror> {
if (t is NoType || t is ExecutableType) throw IllegalArgumentException("Invalid type: $t") if (t is NoType || t is ExecutableType) throw IllegalArgumentException("Invalid type: $t")
if (t is JeDeclaredType && t.psiType is PsiImmediateClassType) {
return t.psiClass.superTypes.map { it.toJeType(psiManager()) }
}
val psiType = (t as? JePsiType)?.psiType as? PsiClassType ?: return emptyList() val psiType = (t as? JePsiType)?.psiType as? PsiClassType ?: return emptyList()
return psiType.superTypes.map { it.toJeType(psiManager()) } return psiType.superTypes.map { it.toJeType(psiManager()) }
} }
@@ -197,7 +192,7 @@ class KotlinTypes(
i, t -> (t as? JePsiType)?.psiType ?: throw IllegalArgumentException("Invalid type argument #$i: $t") i, t -> (t as? JePsiType)?.psiType ?: throw IllegalArgumentException("Invalid type argument #$i: $t")
} }
val psiType = createDeclaredType(psiClass, typeArgs) ?: val psiType = createImmediateClassType(psiClass, typeArgs) ?:
throw IllegalStateException("Can't create declared type ($psiClass, $typeArgs)") throw IllegalStateException("Can't create declared type ($psiClass, $typeArgs)")
return JeDeclaredType(psiType, psiClass) return JeDeclaredType(psiType, psiClass)
} }
@@ -229,7 +224,7 @@ class KotlinTypes(
i, t -> (t as? JePsiType)?.psiType ?: throw IllegalArgumentException("Invalid type argument #$i: $t") i, t -> (t as? JePsiType)?.psiType ?: throw IllegalArgumentException("Invalid type argument #$i: $t")
} }
val psiType = createDeclaredType(psiClass, typeArgs) ?: val psiType = createImmediateClassType(psiClass, typeArgs) ?:
throw IllegalStateException("Can't create declared type ($psiClass, $typeArgs)") throw IllegalStateException("Can't create declared type ($psiClass, $typeArgs)")
return JeDeclaredType(psiType, psiClass, containing) return JeDeclaredType(psiType, psiClass, containing)
} }
@@ -11,4 +11,7 @@ class C<T : CharSequence> : A<T>()
interface I2<X> interface I2<X>
open class B2<X> open class B2<X>
class A2<T : CharSequence> : B2<T>(), I2<T> class A2<T : CharSequence> : B2<T>(), I2<T>
interface I3<T>
class A3<T> : I3<List<T>>
@@ -17,7 +17,7 @@
package org.jetbrains.kotlin.java.model.elements package org.jetbrains.kotlin.java.model.elements
import com.intellij.psi.* import com.intellij.psi.*
import com.intellij.psi.util.PsiTypesUtil import org.jetbrains.kotlin.java.model.internal.getTypeWithTypeParameters
import org.jetbrains.kotlin.java.model.types.JeDeclaredErrorType import org.jetbrains.kotlin.java.model.types.JeDeclaredErrorType
import org.jetbrains.kotlin.java.model.types.JeDeclaredType import org.jetbrains.kotlin.java.model.types.JeDeclaredType
import javax.lang.model.element.AnnotationMirror import javax.lang.model.element.AnnotationMirror
@@ -28,7 +28,7 @@ import javax.lang.model.type.DeclaredType
class JeAnnotationMirror(val psi: PsiAnnotation) : AnnotationMirror { class JeAnnotationMirror(val psi: PsiAnnotation) : AnnotationMirror {
override fun getAnnotationType(): DeclaredType? { override fun getAnnotationType(): DeclaredType? {
val psiClass = resolveAnnotationClass() ?: return JeDeclaredErrorType val psiClass = resolveAnnotationClass() ?: return JeDeclaredErrorType
return JeDeclaredType(PsiTypesUtil.getClassType(psiClass), psiClass) return JeDeclaredType(psiClass.getTypeWithTypeParameters(), psiClass)
} }
override fun getElementValues(): Map<out ExecutableElement, AnnotationValue> = getElementValues(false) override fun getElementValues(): Map<out ExecutableElement, AnnotationValue> = getElementValues(false)
@@ -17,8 +17,8 @@
package org.jetbrains.kotlin.java.model.elements package org.jetbrains.kotlin.java.model.elements
import com.intellij.psi.* import com.intellij.psi.*
import com.intellij.psi.util.PsiTypesUtil
import org.jetbrains.kotlin.java.model.* import org.jetbrains.kotlin.java.model.*
import org.jetbrains.kotlin.java.model.internal.getTypeWithTypeParameters
import org.jetbrains.kotlin.java.model.internal.isStatic import org.jetbrains.kotlin.java.model.internal.isStatic
import org.jetbrains.kotlin.java.model.types.JeMethodExecutableTypeMirror import org.jetbrains.kotlin.java.model.types.JeMethodExecutableTypeMirror
import org.jetbrains.kotlin.java.model.types.JeNoneType import org.jetbrains.kotlin.java.model.types.JeNoneType
@@ -84,7 +84,7 @@ fun PsiMethod.getReceiverTypeMirror(): TypeMirror {
val containingClass = containingClass val containingClass = containingClass
if (containingClass != null && !containingClass.isStatic) { if (containingClass != null && !containingClass.isStatic) {
containingClass.containingClass?.let { containingClass.containingClass?.let {
return PsiTypesUtil.getClassType(it).toJeType(manager) return it.getTypeWithTypeParameters().toJeType(manager)
} }
} }
@@ -92,6 +92,6 @@ fun PsiMethod.getReceiverTypeMirror(): TypeMirror {
} }
val containingClass = containingClass ?: return JeNoneType val containingClass = containingClass ?: return JeNoneType
return PsiTypesUtil.getClassType(containingClass).toJeType(manager) return containingClass.getTypeWithTypeParameters().toJeType(manager)
} }
@@ -19,10 +19,10 @@ package org.jetbrains.kotlin.java.model.elements
import com.intellij.psi.* import com.intellij.psi.*
import com.intellij.psi.impl.source.PsiClassReferenceType import com.intellij.psi.impl.source.PsiClassReferenceType
import com.intellij.psi.util.ClassUtil import com.intellij.psi.util.ClassUtil
import com.intellij.psi.util.PsiTypesUtil
import org.jetbrains.kotlin.asJava.elements.LightParameter import org.jetbrains.kotlin.asJava.elements.LightParameter
import org.jetbrains.kotlin.java.model.* import org.jetbrains.kotlin.java.model.*
import org.jetbrains.kotlin.java.model.internal.DefaultConstructorPsiMethod import org.jetbrains.kotlin.java.model.internal.DefaultConstructorPsiMethod
import org.jetbrains.kotlin.java.model.internal.getTypeWithTypeParameters
import org.jetbrains.kotlin.java.model.types.JeNoneType import org.jetbrains.kotlin.java.model.types.JeNoneType
import org.jetbrains.kotlin.java.model.types.toJeType import org.jetbrains.kotlin.java.model.types.toJeType
import javax.lang.model.element.* import javax.lang.model.element.*
@@ -41,7 +41,7 @@ class JeTypeElement(override val psi: PsiClass) : JeElement, TypeElement, JeAnno
private fun getSuperType(superTypes: Array<PsiClassType>, superClass: PsiClass): PsiClassType { private fun getSuperType(superTypes: Array<PsiClassType>, superClass: PsiClass): PsiClassType {
return superTypes.firstOrNull { it is PsiClassReferenceType && it.resolve() == superClass } return superTypes.firstOrNull { it is PsiClassReferenceType && it.resolve() == superClass }
?: PsiTypesUtil.getClassType(superClass) ?: superClass.getTypeWithTypeParameters()
} }
override fun getSuperclass(): TypeMirror { override fun getSuperclass(): TypeMirror {
@@ -94,7 +94,7 @@ class JeTypeElement(override val psi: PsiClass) : JeElement, TypeElement, JeAnno
declarations += JeMethodExecutableElement(DefaultConstructorPsiMethod(psi, psi.language).apply { declarations += JeMethodExecutableElement(DefaultConstructorPsiMethod(psi, psi.language).apply {
val containingClass = psi.containingClass val containingClass = psi.containingClass
if (containingClass != null && !psi.hasModifierProperty(PsiModifier.STATIC)) { if (containingClass != null && !psi.hasModifierProperty(PsiModifier.STATIC)) {
addParameter(LightParameter("\$instance", PsiTypesUtil.getClassType(containingClass), this, psi.language)) addParameter(LightParameter("\$instance", containingClass.getTypeWithTypeParameters(), this, psi.language))
} }
}) })
} }
@@ -125,7 +125,7 @@ class JeTypeElement(override val psi: PsiClass) : JeElement, TypeElement, JeAnno
else -> ElementKind.CLASS else -> ElementKind.CLASS
} }
override fun asType() = PsiTypesUtil.getClassType(psi).toJeType(psi.manager) override fun asType() = psi.getTypeWithTypeParameters().toJeType(psi.manager)
override fun <R : Any?, P : Any?> accept(v: ElementVisitor<R, P>, p: P) = v.visitType(this, p) override fun <R : Any?, P : Any?> accept(v: ElementVisitor<R, P>, p: P) = v.visitType(this, p)
@@ -16,14 +16,9 @@
package org.jetbrains.kotlin.java.model.elements 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.PsiTypeParameter
import com.intellij.psi.util.PsiTypesUtil import org.jetbrains.kotlin.java.model.*
import org.jetbrains.kotlin.java.model.JeAnnotationOwner import org.jetbrains.kotlin.java.model.internal.getTypeWithTypeParameters
import org.jetbrains.kotlin.java.model.JeElement
import org.jetbrains.kotlin.java.model.JeModifierListOwner
import org.jetbrains.kotlin.java.model.JeName
import org.jetbrains.kotlin.java.model.types.toJeType import org.jetbrains.kotlin.java.model.types.toJeType
import javax.lang.model.element.Element import javax.lang.model.element.Element
import javax.lang.model.element.ElementKind import javax.lang.model.element.ElementKind
@@ -40,7 +35,7 @@ class JeTypeParameterElement(
override fun getKind() = ElementKind.TYPE_PARAMETER override fun getKind() = ElementKind.TYPE_PARAMETER
override fun asType() = PsiTypesUtil.getClassType(psi).toJeType(psi.manager) override fun asType() = psi.getTypeWithTypeParameters().toJeType(psi.manager)
override fun <R : Any?, P : Any?> accept(v: ElementVisitor<R, P>, p: P) = v.visitTypeParameter(this, p) override fun <R : Any?, P : Any?> accept(v: ElementVisitor<R, P>, p: P) = v.visitTypeParameter(this, p)
@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.java.model.internal
import com.intellij.psi.* import com.intellij.psi.*
import com.intellij.psi.PsiModifier.* import com.intellij.psi.PsiModifier.*
import com.intellij.psi.impl.PsiSubstitutorImpl
import com.intellij.psi.util.PsiTypesUtil
import org.jetbrains.kotlin.asJava.elements.KtLightAnnotation import org.jetbrains.kotlin.asJava.elements.KtLightAnnotation
import javax.lang.model.element.Modifier import javax.lang.model.element.Modifier
@@ -91,6 +93,13 @@ fun PsiModifierListOwner.getAnnotationsWithInherited(): List<PsiAnnotation> {
return annotations return annotations
} }
fun PsiClass.getTypeWithTypeParameters(): PsiClassType {
val elementFactory = JavaPsiFacade.getElementFactory(project)
val params = mutableMapOf<PsiTypeParameter, PsiType>()
typeParameters.forEach { params.put(it, PsiTypesUtil.getClassType(it)) }
return elementFactory.createType(this, PsiSubstitutorImpl.createSubstitutor(params))
}
private fun PsiAnnotation.isInherited(): Boolean { private fun PsiAnnotation.isInherited(): Boolean {
val annotationClass = nameReferenceElement?.resolve() as? PsiClass ?: return false val annotationClass = nameReferenceElement?.resolve() as? PsiClass ?: return false
val annotations = annotationClass.modifierList?.annotations ?: return false val annotations = annotationClass.modifierList?.annotations ?: return false
@@ -18,22 +18,24 @@ package org.jetbrains.kotlin.java.model.types
import com.intellij.pom.java.LanguageLevel import com.intellij.pom.java.LanguageLevel
import com.intellij.psi.* import com.intellij.psi.*
import com.intellij.psi.impl.light.LightClassReferenceExpression import com.intellij.psi.impl.PsiSubstitutorImpl
import com.intellij.psi.impl.source.PsiClassReferenceType import com.intellij.psi.impl.source.PsiClassReferenceType
import com.intellij.psi.util.PsiTypesUtil import com.intellij.psi.impl.source.PsiImmediateClassType
import org.jetbrains.kotlin.java.model.elements.JeTypeElement import org.jetbrains.kotlin.java.model.elements.JeTypeElement
import org.jetbrains.kotlin.java.model.internal.getTypeWithTypeParameters
import org.jetbrains.kotlin.java.model.internal.isStatic import org.jetbrains.kotlin.java.model.internal.isStatic
import javax.lang.model.type.DeclaredType import javax.lang.model.type.DeclaredType
import javax.lang.model.type.TypeKind import javax.lang.model.type.TypeKind
import javax.lang.model.type.TypeMirror import javax.lang.model.type.TypeMirror
import javax.lang.model.type.TypeVisitor import javax.lang.model.type.TypeVisitor
fun createDeclaredType(psiClass: PsiClass, typeArgs: List<PsiType>): PsiClassReferenceType? { fun createImmediateClassType(psiClass: PsiClass, typeArgs: List<PsiType>): PsiImmediateClassType? {
val args = typeArgs.toTypedArray() val typeParameters = psiClass.typeParameters
val text = (psiClass.name ?: return null) + typeArgs.joinToString(prefix = "<", postfix = ">") { it.canonicalText } assert(typeParameters.size == typeArgs.size) { "Type parameters size: ${typeParameters.size}, type args size: ${typeArgs.size}" }
return PsiClassReferenceType(object : LightClassReferenceExpression(psiClass.manager, text, psiClass) {
override fun getTypeParameters() = args val parametersMap = typeParameters.zip(typeArgs).toMap()
}, LanguageLevel.JDK_1_8) val substitutor = PsiSubstitutorImpl.createSubstitutor(parametersMap)
return PsiImmediateClassType(psiClass, substitutor, LanguageLevel.JDK_1_8)
} }
class JeDeclaredType( class JeDeclaredType(
@@ -64,7 +66,7 @@ class JeDeclaredType(
if (substitutedParameter != null) if (substitutedParameter != null)
args += substitutedParameter.toJeType(psiManager) args += substitutedParameter.toJeType(psiManager)
else else
args += JeTypeVariableType(PsiTypesUtil.getClassType(typeParameter), typeParameter) args += JeTypeVariableType(typeParameter.getTypeWithTypeParameters(), typeParameter)
} }
args args
@@ -81,7 +83,7 @@ class JeDeclaredType(
if (enclosingDeclaredType != null) return enclosingDeclaredType if (enclosingDeclaredType != null) return enclosingDeclaredType
val psiClass = psiClass.containingClass ?: return JeNoneType val psiClass = psiClass.containingClass ?: return JeNoneType
return PsiTypesUtil.getClassType(psiClass).toJeType(psiManager) return psiClass.getTypeWithTypeParameters().toJeType(psiManager)
} }
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
@@ -16,6 +16,9 @@
package org.jetbrains.kotlin.annotation.processing.test.processor package org.jetbrains.kotlin.annotation.processing.test.processor
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.impl.PsiSubstitutorImpl
import com.intellij.psi.util.PsiTypesUtil
import org.intellij.lang.annotations.Language import org.intellij.lang.annotations.Language
import org.jetbrains.kotlin.annotation.processing.impl.DisposableRef import org.jetbrains.kotlin.annotation.processing.impl.DisposableRef
import org.jetbrains.kotlin.annotation.processing.impl.KotlinProcessingEnvironment import org.jetbrains.kotlin.annotation.processing.impl.KotlinProcessingEnvironment
@@ -148,11 +151,11 @@ class ProcessorTests : AbstractProcessorTest() {
assertEquals(2, bASuperTypes.size) // Object and I assertEquals(2, bASuperTypes.size) // Object and I
fun List<TypeMirror>.iInterface() = first { it.toString().matches("I(<.*>)?".toRegex()) } as DeclaredType fun List<TypeMirror>.iInterface() = first { it.toString().matches("I(<.*>)?".toRegex()) } as DeclaredType
val bai = bASuperTypes.iInterface() val bai = bASuperTypes.iInterface()
assertEquals(1, bai.typeArguments.size) assertEquals(1, bai.typeArguments.size)
assertEquals("java.lang.String", bai.typeArguments.first().toString()) assertEquals("java.lang.String", bai.typeArguments.first().toString())
val c = env.findClass("C") val c = env.findClass("C")
val cSuperTypes = env.typeUtils.directSupertypes(c.asType()) val cSuperTypes = env.typeUtils.directSupertypes(c.asType())
assertEquals(1, cSuperTypes.size) assertEquals(1, cSuperTypes.size)
@@ -164,6 +167,12 @@ class ProcessorTests : AbstractProcessorTest() {
val a2 = env.findClass("A2") val a2 = env.findClass("A2")
val i2 = env.typeUtils.directSupertypes(a2.asType()).first { it.toString().matches("I2(<.*>)?".toRegex()) } as JeDeclaredType val i2 = env.typeUtils.directSupertypes(a2.asType()).first { it.toString().matches("I2(<.*>)?".toRegex()) } as JeDeclaredType
assertEquals("I2<T>", i2.toString()) assertEquals("I2<T>", i2.toString())
val stringType = env.elementUtils.getTypeElement("java.lang.String").asType()
val a3 = env.findClass("A3")
val resolvedA3 = env.typeUtils.getDeclaredType(a3, stringType)
val i3 = env.typeUtils.directSupertypes(resolvedA3).first { it.toString().matches("I3(<.*>)?".toRegex()) } as JeDeclaredType
assertEquals("I3<java.util.List<? extends java.lang.String>>", i3.toString())
} }
fun testErasureSimple() = test("ErasureSimple", "*") { set, roundEnv, env -> fun testErasureSimple() = test("ErasureSimple", "*") { set, roundEnv, env ->