diff --git a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinTypes.kt b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinTypes.kt index 5148fb61470..74bf530867d 100644 --- a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinTypes.kt +++ b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinTypes.kt @@ -60,7 +60,7 @@ class KotlinTypes(val javaPsiFacade: JavaPsiFacade, val psiManager: PsiManager, if (componentType is ExecutableType || componentType is NoType) error(componentType) assertJeType(componentType); componentType as JePsiType - return JeArrayType(PsiArrayType(componentType.psiType), psiManager) + return JeArrayType(PsiArrayType(componentType.psiType), psiManager, isRaw = false) } override fun isAssignable(t1: TypeMirror, t2: TypeMirror): Boolean { @@ -88,7 +88,7 @@ class KotlinTypes(val javaPsiFacade: JavaPsiFacade, val psiManager: PsiManager, PsiWildcardType.createSuper(psiManager, (superBound as JePsiType).psiType) } else { PsiWildcardType.createUnbounded(psiManager) - }) + }, isRaw = false) } override fun unboxedType(t: TypeMirror): PrimitiveType? { @@ -103,8 +103,8 @@ class KotlinTypes(val javaPsiFacade: JavaPsiFacade, val psiManager: PsiManager, override fun erasure(t: TypeMirror): TypeMirror { if (t.kind == TypeKind.PACKAGE) throw IllegalArgumentException("Invalid type: $t") return when (t) { - is JeTypeVariableType -> TypeConversionUtil.typeParameterErasure(t.parameter).toJeType(t.psiManager) - is JePsiType -> TypeConversionUtil.erasure(t.psiType).toJeType(psiManager) + is JeTypeVariableType -> TypeConversionUtil.typeParameterErasure(t.parameter).toJeType(t.psiManager, isRaw = true) + is JePsiType -> TypeConversionUtil.erasure(t.psiType).toJeType(psiManager, isRaw = true) is JeMethodExecutableTypeMirror -> { val oldSignature = t.signature val parameterTypes = oldSignature?.parameterTypes?.toList() ?: t.psi.parameterList.parameters.map { it.type } @@ -114,7 +114,9 @@ class KotlinTypes(val javaPsiFacade: JavaPsiFacade, val psiManager: PsiManager, emptyArray(), PsiSubstitutor.EMPTY, oldSignature?.isConstructor ?: t.psi.isConstructor) - JeMethodExecutableTypeMirror(t.psi, newSignature, TypeConversionUtil.erasure(t.returnType ?: t.psi.returnType)) + JeMethodExecutableTypeMirror( + t.psi, newSignature, + TypeConversionUtil.erasure(t.returnType ?: t.psi.returnType), isRaw = true) } else -> t } diff --git a/plugins/annotation-processing/testData/processors/Erasure2.kt b/plugins/annotation-processing/testData/processors/Erasure2.kt index ba1e6dccbb7..296817b98e1 100644 --- a/plugins/annotation-processing/testData/processors/Erasure2.kt +++ b/plugins/annotation-processing/testData/processors/Erasure2.kt @@ -13,4 +13,11 @@ class Test : Base() { fun e(item: D): D = item fun f(items: List>, i: Int) {} fun g(item: D) {} + fun h(): Array> = null!! + fun i(): T where T : CharSequence, T : Appendable = null!! +} + +class Test2, out B : List> { + fun a(items: A) {} + fun b(): B = null!! } \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeArrayType.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeArrayType.kt index cf7b3395d81..9a3c0570c91 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeArrayType.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeArrayType.kt @@ -22,18 +22,29 @@ import javax.lang.model.type.ArrayType import javax.lang.model.type.TypeKind import javax.lang.model.type.TypeVisitor -class JeArrayType(override val psiType: PsiArrayType, override val psiManager: PsiManager) : JePsiType(), JeTypeWithManager, ArrayType { +class JeArrayType( + override val psiType: PsiArrayType, + override val psiManager: PsiManager, + private val isRaw: Boolean +) : JePsiType(), JeTypeWithManager, ArrayType { override fun getKind() = TypeKind.ARRAY override fun accept(v: TypeVisitor, p: P) = v.visitArray(this, p) - override fun getComponentType() = psiType.componentType.toJeType(psiManager) + override fun getComponentType() = psiType.componentType.toJeType(psiManager, isRaw = isRaw) override fun toString() = psiType.getCanonicalText(false) - - override fun equals(other: Any?): Boolean{ + + override fun equals(other: Any?): Boolean { if (this === other) return true if (other?.javaClass != javaClass) return false - return componentType == (other as? JeArrayType)?.componentType + other as? JeArrayType ?: return false + + return componentType == other.componentType + && isRaw == other.isRaw } - override fun hashCode() = componentType.hashCode() + override fun hashCode(): Int { + var result = componentType.hashCode() + result = 31 * result + isRaw.hashCode() + return result + } } \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeDeclaredType.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeDeclaredType.kt index 6ac6bb5aff6..f046a2d3b74 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeDeclaredType.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeDeclaredType.kt @@ -39,7 +39,8 @@ fun createDeclaredType(psiClass: PsiClass, typeArgs: List): PsiClassRef class JeDeclaredType( override val psiType: PsiClassType, val psiClass: PsiClass, - val enclosingDeclaredType: DeclaredType? = null + val enclosingDeclaredType: DeclaredType? = null, + val isRaw: Boolean = false ) : JePsiType(), JeTypeWithManager, DeclaredType { override fun getKind() = TypeKind.DECLARED @@ -52,6 +53,8 @@ class JeDeclaredType( return when (psiType) { is PsiClassReferenceType -> psiType.parameters.map { it.toJeType(psiManager) } is PsiClassType -> { + if (isRaw) return emptyList() + val substitutor = psiType.resolveGenerics().substitutor val psiClass = psiType.resolve() ?: return psiType.parameters.map { it.toJeType(psiManager) } @@ -89,14 +92,24 @@ class JeDeclaredType( return enclosingType == other.enclosingType && psiClass == other.psiClass && typeArguments == other.typeArguments + && isRaw == other.isRaw } override fun hashCode(): Int { var result = enclosingType.hashCode() result = 31 * result + psiClass.hashCode() result = 31 * result + typeArguments.hashCode() + result = 31 * result + isRaw.hashCode() return result } - override fun toString() = psiType.getCanonicalText(false) + override fun toString() = buildString { + append(psiClass.qualifiedName ?: psiClass.name) + val typeArgs = typeArguments + if (typeArgs.isNotEmpty()) { + append('<') + append(typeArguments.joinToString(",")) + append('>') + } + } } \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeIntersectionType.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeIntersectionType.kt index 4336ff12154..1d1e4c2f9cd 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeIntersectionType.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeIntersectionType.kt @@ -24,18 +24,28 @@ import javax.lang.model.type.TypeVisitor class JeIntersectionType( override val psiType: PsiIntersectionType, - override val psiManager: PsiManager + override val psiManager: PsiManager, + private val isRaw: Boolean ) : JePsiType(), JeTypeWithManager, IntersectionType { override fun getKind() = TypeKind.INTERSECTION override fun accept(v: TypeVisitor, p: P) = v.visitIntersection(this, p) - override fun getBounds() = psiType.superTypes.map { it.toJeType(psiManager) } + override fun getBounds() = psiType.superTypes.map { it.toJeType(psiManager, isRaw = isRaw) } override fun equals(other: Any?): Boolean { if (this === other) return true if (other?.javaClass != javaClass) return false - return bounds == (other as? JeIntersectionType)?.bounds + other as? JeIntersectionType ?: return false + + return bounds == other.bounds + && isRaw == other.isRaw } - override fun hashCode() = bounds.hashCode() + override fun hashCode(): Int { + var result = bounds.hashCode() + result = 31 * result + isRaw.hashCode() + return result + } + + override fun toString() = bounds.joinToString("&") } \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeMethodExecutableTypeMirror.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeMethodExecutableTypeMirror.kt index 699b682b496..a5336912adb 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeMethodExecutableTypeMirror.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeMethodExecutableTypeMirror.kt @@ -30,27 +30,29 @@ import javax.lang.model.type.TypeVisitor class JeMethodExecutableTypeMirror( val psi: PsiMethod, val signature: MethodSignature? = null, - val returnType: PsiType? = null + val returnType: PsiType? = null, + val isRaw: Boolean = false ) : JeTypeMirror, JeTypeWithManager, ExecutableType { override fun getKind() = TypeKind.EXECUTABLE override fun accept(v: TypeVisitor, p: P) = v.visitExecutable(this, p) - override fun getReturnType() = (returnType ?: psi.returnType)?.let { it.toJeType(psi.manager) } ?: JeVoidType + override fun getReturnType() = (returnType ?: psi.returnType)?.let { it.toJeType(psi.manager, isRaw = isRaw) } ?: JeVoidType override fun getReceiverType() = psi.getReceiverTypeMirror() - override fun getThrownTypes() = psi.throwsList.referencedTypes.map { it.toJeType(psi.manager) } + override fun getThrownTypes() = psi.throwsList.referencedTypes.map { it.toJeType(psi.manager, isRaw = isRaw) } override val psiManager: PsiManager get() = psi.manager override fun getParameterTypes(): List { - signature?.parameterTypes?.let { types -> return types.map { it.toJeType(psi.manager) } } - return psi.parameterList.parameters.map { it.type.toJeType(psi.manager) } + signature?.parameterTypes?.let { types -> return types.map { it.toJeType(psi.manager, isRaw = isRaw) } } + return psi.parameterList.parameters.map { it.type.toJeType(psi.manager, isRaw = isRaw) } } override fun getTypeVariables(): List { + if (isRaw) return emptyList() val typeParameters = signature?.typeParameters ?: psi.typeParameters return typeParameters.map { JeTypeVariableType(PsiTypesUtil.getClassType(it), it) } } diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeWildcardType.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeWildcardType.kt index 717f3db09e8..030ae51facf 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeWildcardType.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeWildcardType.kt @@ -23,40 +23,74 @@ import javax.lang.model.type.TypeKind import javax.lang.model.type.TypeVisitor import javax.lang.model.type.WildcardType -class JeWildcardType(override val psiType: PsiWildcardType) : JePsiType(), JeTypeWithManager, WildcardType { +class JeWildcardType( + override val psiType: PsiWildcardType, + private val isRaw: Boolean +) : JePsiType(), JeTypeWithManager, WildcardType { override fun getKind() = TypeKind.WILDCARD override fun accept(v: TypeVisitor, p: P) = v.visitWildcard(this, p) - override fun getSuperBound() = psiType.superBound.toJeType(psiManager) - override fun getExtendsBound() = psiType.extendsBound.toJeType(psiManager) + override fun getSuperBound() = psiType.superBound.toJeType(psiManager, isRaw = isRaw) + override fun getExtendsBound() = psiType.extendsBound.toJeType(psiManager, isRaw = isRaw) override val psiManager: PsiManager get() = psiType.manager - override fun equals(other: Any?): Boolean{ + override fun equals(other: Any?): Boolean { if (this === other) return true if (other?.javaClass != javaClass) return false - return psiType == (other as? JeWildcardType)?.psiType + other as? JeWildcardType ?: return false + + return superBound == other.superBound + && extendsBound == other.extendsBound + && isRaw == other.isRaw } - override fun hashCode() = psiType.hashCode() + override fun hashCode(): Int { + var result = superBound.hashCode() + result = 31 * result + extendsBound.hashCode() + result = 31 * result + isRaw.hashCode() + return result + } + + override fun toString() = when { + psiType.isExtends -> "? extends $extendsBound" + psiType.isSuper -> "? super $superBound" + else -> "?" + } } class JeCapturedWildcardType( override val psiType: PsiCapturedWildcardType, - override val psiManager: PsiManager + override val psiManager: PsiManager, + private val isRaw: Boolean ) : JePsiType(), JeTypeWithManager, WildcardType { override fun getKind() = TypeKind.WILDCARD override fun accept(v: TypeVisitor, p: P) = v.visitWildcard(this, p) - override fun getSuperBound() = psiType.lowerBound.toJeType(psiManager) - override fun getExtendsBound() = psiType.upperBound.toJeType(psiManager) + override fun getSuperBound() = psiType.lowerBound.toJeType(psiManager, isRaw = isRaw) + override fun getExtendsBound() = psiType.upperBound.toJeType(psiManager, isRaw = isRaw) override fun equals(other: Any?): Boolean { if (this === other) return true if (other?.javaClass != javaClass) return false - return psiType == (other as? JeWildcardType)?.psiType + other as? JeCapturedWildcardType ?: return false + + return superBound == other.superBound + && extendsBound == other.extendsBound + && isRaw == other.isRaw } - override fun hashCode() = psiType.hashCode() + override fun hashCode(): Int { + var result = superBound.hashCode() + result = 31 * result + extendsBound.hashCode() + result = 31 * result + isRaw.hashCode() + return result + } + + override fun toString() = when { + psiType.wildcard.isSuper -> "? extends $extendsBound" + psiType.wildcard.isExtends -> "? super $superBound" + else -> "?" + } } \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/types.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/types.kt index 35f533a50b4..a19f4276a55 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/types.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/types.kt @@ -42,22 +42,21 @@ fun TypeKind?.toJePrimitiveType() = PSI_PRIMITIVES_MAP[TYPE_KIND_TO_PSI_PRIMITIV fun PsiType.toJePrimitiveType() = PSI_PRIMITIVES_MAP[this] -fun PsiType.toJeType(manager: PsiManager): TypeMirror = when (this) { +fun PsiType.toJeType(manager: PsiManager, isRaw: Boolean = false): TypeMirror = when (this) { PsiType.VOID -> JeVoidType PsiType.NULL -> JeNullType is PsiPrimitiveType -> PSI_PRIMITIVES_MAP[this] ?: JeErrorType - is PsiArrayType -> JeArrayType(this, manager) - is PsiWildcardType -> JeWildcardType(this) - is PsiCapturedWildcardType -> JeCapturedWildcardType(this, manager) + is PsiArrayType -> JeArrayType(this, manager, isRaw) + is PsiWildcardType -> JeWildcardType(this, isRaw) + is PsiCapturedWildcardType -> JeCapturedWildcardType(this, manager, isRaw) is PsiClassType -> { val resolvedClass = this.resolve() when (resolvedClass) { is PsiTypeParameter -> JeTypeVariableType(this, resolvedClass) - is PsiClass -> JeDeclaredType(this, resolvedClass) + is PsiClass -> JeDeclaredType(this, resolvedClass, isRaw = isRaw) else -> JeErrorType } } - is PsiIntersectionType -> JeIntersectionType(this, manager) + is PsiIntersectionType -> JeIntersectionType(this, manager, isRaw) else -> JeErrorType -} - +} \ No newline at end of file diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/ProcessorTests.kt b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/ProcessorTests.kt index 786c89c4a5f..e9593a62694 100644 --- a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/ProcessorTests.kt +++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/ProcessorTests.kt @@ -167,25 +167,47 @@ class ProcessorTests : AbstractProcessorTest() { } fun testErasure2() = test("Erasure2", "*") { set, roundEnv, env -> - val test = env.findClass("Test") - val erasure = fun (t: JeMethodExecutableTypeMirror) = env.typeUtils.erasure(t) - fun check(methodName: String, toString: String, transform: (JeMethodExecutableTypeMirror) -> TypeMirror = { it }) { - val method = test.enclosedElements.first { it is JeMethodExecutableElement && it.simpleName.toString() == methodName } + fun JeTypeElement.check(methodName: String, toString: String, transform: (JeMethodExecutableTypeMirror) -> TypeMirror = { it }) { + val method = enclosedElements.first { it is JeMethodExecutableElement && it.simpleName.toString() == methodName } assertEquals(toString, transform((method as JeMethodExecutableElement).asType()).toString()) } + + with (env.findClass("Test")) { + val classType = asType() as DeclaredType + assertEquals(1, classType.typeArguments.size) + assertEquals("Test", classType.toString()) + + val erasedType = env.typeUtils.erasure(asType()) as DeclaredType + assertEquals(0, erasedType.typeArguments.size) + assertEquals("Test", erasedType.toString()) + + check("a", "()java.lang.String") + check("b", "(java.lang.String,java.lang.CharSequence)void") + check("c", "()int") + + check("d", "()T") + check("e", "(D)D") + check("e", "(java.lang.Object)java.lang.Object", erasure) + check("f", "(java.util.List>,int)void") + check("f", "(java.util.List,int)void", erasure) + check("g", "(D)void") + check("g", "(java.lang.String)void", erasure) + check("h", "()java.util.List[]") + check("h", "()java.util.List[]", erasure) + check("i", "()T") + check("i", "()java.lang.CharSequence", erasure) + } - check("a", "()java.lang.String") - check("b", "(java.lang.String,java.lang.CharSequence)void") - check("c", "()int") - - check("d", "()T") - check("e", "(D)D") - check("e", "(java.lang.Object)java.lang.Object", erasure) - check("f", "(java.util.List>,int)void") - check("f", "(java.util.List,int)void", erasure) - check("g", "(D)void") - check("g", "(java.lang.String)void", erasure) + with (env.findClass("Test2")) { + assertEquals("Test2", asType().toString()) + assertEquals("Test2", env.typeUtils.erasure(asType()).toString()) + + check("a", "(A)void") + check("a", "(java.util.List)void", erasure) + check("b", "()B") + check("b", "()java.util.List", erasure) + } } fun testIncrementalDataSimple() = incrementalDataTest(