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.JePackageElement
import org.jetbrains.kotlin.java.model.elements.JeTypeElement
import org.jetbrains.kotlin.java.model.internal.getTypeWithTypeParameters
import java.io.PrintWriter
import java.io.Writer
import javax.lang.model.element.*
@@ -48,7 +49,7 @@ class KotlinElements(
val hiderMethodClass = hiderMethod.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)
}
@@ -148,7 +149,7 @@ class KotlinElements(
private fun PsiClass.isSubclassOf(other: PsiClass?): Boolean {
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 {
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.annotation.processing.impl
import com.intellij.openapi.Disposable
import com.intellij.psi.*
import com.intellij.psi.impl.source.PsiImmediateClassType
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.*
import org.jetbrains.kotlin.java.model.JeElement
@@ -135,10 +134,6 @@ class KotlinTypes(
override fun directSupertypes(t: TypeMirror): List<TypeMirror> {
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()
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")
}
val psiType = createDeclaredType(psiClass, typeArgs) ?:
val psiType = createImmediateClassType(psiClass, typeArgs) ?:
throw IllegalStateException("Can't create declared type ($psiClass, $typeArgs)")
return JeDeclaredType(psiType, psiClass)
}
@@ -229,7 +224,7 @@ class KotlinTypes(
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)")
return JeDeclaredType(psiType, psiClass, containing)
}
@@ -11,4 +11,7 @@ class C<T : CharSequence> : A<T>()
interface I2<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
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.JeDeclaredType
import javax.lang.model.element.AnnotationMirror
@@ -28,7 +28,7 @@ import javax.lang.model.type.DeclaredType
class JeAnnotationMirror(val psi: PsiAnnotation) : AnnotationMirror {
override fun getAnnotationType(): DeclaredType? {
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)
@@ -17,8 +17,8 @@
package org.jetbrains.kotlin.java.model.elements
import com.intellij.psi.*
import com.intellij.psi.util.PsiTypesUtil
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.types.JeMethodExecutableTypeMirror
import org.jetbrains.kotlin.java.model.types.JeNoneType
@@ -84,7 +84,7 @@ fun PsiMethod.getReceiverTypeMirror(): TypeMirror {
val containingClass = containingClass
if (containingClass != null && !containingClass.isStatic) {
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
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.impl.source.PsiClassReferenceType
import com.intellij.psi.util.ClassUtil
import com.intellij.psi.util.PsiTypesUtil
import org.jetbrains.kotlin.asJava.elements.LightParameter
import org.jetbrains.kotlin.java.model.*
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.toJeType
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 {
return superTypes.firstOrNull { it is PsiClassReferenceType && it.resolve() == superClass }
?: PsiTypesUtil.getClassType(superClass)
?: superClass.getTypeWithTypeParameters()
}
override fun getSuperclass(): TypeMirror {
@@ -94,7 +94,7 @@ class JeTypeElement(override val psi: PsiClass) : JeElement, TypeElement, JeAnno
declarations += JeMethodExecutableElement(DefaultConstructorPsiMethod(psi, psi.language).apply {
val containingClass = psi.containingClass
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
}
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)
@@ -16,14 +16,9 @@
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
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.*
import org.jetbrains.kotlin.java.model.internal.getTypeWithTypeParameters
import org.jetbrains.kotlin.java.model.types.toJeType
import javax.lang.model.element.Element
import javax.lang.model.element.ElementKind
@@ -40,7 +35,7 @@ class JeTypeParameterElement(
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)
@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.java.model.internal
import com.intellij.psi.*
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 javax.lang.model.element.Modifier
@@ -91,6 +93,13 @@ fun PsiModifierListOwner.getAnnotationsWithInherited(): List<PsiAnnotation> {
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 {
val annotationClass = nameReferenceElement?.resolve() as? PsiClass ?: 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.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.util.PsiTypesUtil
import com.intellij.psi.impl.source.PsiImmediateClassType
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 javax.lang.model.type.DeclaredType
import javax.lang.model.type.TypeKind
import javax.lang.model.type.TypeMirror
import javax.lang.model.type.TypeVisitor
fun createDeclaredType(psiClass: PsiClass, typeArgs: List<PsiType>): PsiClassReferenceType? {
val args = typeArgs.toTypedArray()
val text = (psiClass.name ?: return null) + typeArgs.joinToString(prefix = "<", postfix = ">") { it.canonicalText }
return PsiClassReferenceType(object : LightClassReferenceExpression(psiClass.manager, text, psiClass) {
override fun getTypeParameters() = args
}, LanguageLevel.JDK_1_8)
fun createImmediateClassType(psiClass: PsiClass, typeArgs: List<PsiType>): PsiImmediateClassType? {
val typeParameters = psiClass.typeParameters
assert(typeParameters.size == typeArgs.size) { "Type parameters size: ${typeParameters.size}, type args size: ${typeArgs.size}" }
val parametersMap = typeParameters.zip(typeArgs).toMap()
val substitutor = PsiSubstitutorImpl.createSubstitutor(parametersMap)
return PsiImmediateClassType(psiClass, substitutor, LanguageLevel.JDK_1_8)
}
class JeDeclaredType(
@@ -64,7 +66,7 @@ class JeDeclaredType(
if (substitutedParameter != null)
args += substitutedParameter.toJeType(psiManager)
else
args += JeTypeVariableType(PsiTypesUtil.getClassType(typeParameter), typeParameter)
args += JeTypeVariableType(typeParameter.getTypeWithTypeParameters(), typeParameter)
}
args
@@ -81,7 +83,7 @@ class JeDeclaredType(
if (enclosingDeclaredType != null) return enclosingDeclaredType
val psiClass = psiClass.containingClass ?: return JeNoneType
return PsiTypesUtil.getClassType(psiClass).toJeType(psiManager)
return psiClass.getTypeWithTypeParameters().toJeType(psiManager)
}
override fun equals(other: Any?): Boolean {
@@ -16,6 +16,9 @@
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.jetbrains.kotlin.annotation.processing.impl.DisposableRef
import org.jetbrains.kotlin.annotation.processing.impl.KotlinProcessingEnvironment
@@ -148,11 +151,11 @@ class ProcessorTests : AbstractProcessorTest() {
assertEquals(2, bASuperTypes.size) // Object and I
fun List<TypeMirror>.iInterface() = first { it.toString().matches("I(<.*>)?".toRegex()) } as DeclaredType
val bai = bASuperTypes.iInterface()
assertEquals(1, bai.typeArguments.size)
assertEquals("java.lang.String", bai.typeArguments.first().toString())
val c = env.findClass("C")
val cSuperTypes = env.typeUtils.directSupertypes(c.asType())
assertEquals(1, cSuperTypes.size)
@@ -164,6 +167,12 @@ class ProcessorTests : AbstractProcessorTest() {
val a2 = env.findClass("A2")
val i2 = env.typeUtils.directSupertypes(a2.asType()).first { it.toString().matches("I2(<.*>)?".toRegex()) } as JeDeclaredType
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 ->