diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java index 6f4e8edad8d..5fee263c9c5 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java @@ -634,7 +634,7 @@ public class KotlinTypeMapper { } @NotNull - private static Variance getVarianceForWildcard( + public static Variance getVarianceForWildcard( @NotNull TypeParameterDescriptor parameter, @NotNull TypeProjection projection, @NotNull TypeMappingMode mode diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/typeMappingUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/typeMappingUtil.kt index 86ca83c9a2c..8b422e980d8 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/typeMappingUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/typeMappingUtil.kt @@ -75,7 +75,7 @@ private val METHODS_WITH_DECLARATION_SITE_WILDCARDS = setOf( BUILTIN_NAMES.mutableMap.child("putAll") ) -internal fun TypeMappingMode.updateArgumentModeFromAnnotations(type: KotlinType): TypeMappingMode { +fun TypeMappingMode.updateArgumentModeFromAnnotations(type: KotlinType): TypeMappingMode { type.suppressWildcardsMode()?.let { return TypeMappingMode.createWithConstantDeclarationSiteWildcardsMode( skipDeclarationSiteWildcards = it, isForAnnotationParameter = isForAnnotationParameter) diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/errorTypeConversion.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/errorTypeConversion.kt index 373a13350ea..dbd5a03f40a 100644 --- a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/errorTypeConversion.kt +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/errorTypeConversion.kt @@ -19,11 +19,16 @@ package org.jetbrains.kotlin.kapt3.stubs import com.sun.tools.javac.code.BoundKind import com.sun.tools.javac.tree.JCTree import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter +import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper +import org.jetbrains.kotlin.codegen.state.updateArgumentModeFromAnnotations +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.kapt3.mapJList +import org.jetbrains.kotlin.kapt3.mapJListIndexed import org.jetbrains.kotlin.load.kotlin.TypeMappingMode import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.Variance internal fun convertKtType( reference: KtTypeReference?, @@ -46,7 +51,7 @@ internal fun convertKtType( } return when (type) { - is KtUserType -> convertUserType(type, converter) + is KtUserType -> convertUserType(type, converter, reference) is KtNullableType -> { // Prevent infinite recursion val innerType = type.innerType ?: return getDefaultTypeForUnknownType(converter) @@ -59,13 +64,20 @@ internal fun convertKtType( private fun getDefaultTypeForUnknownType(converter: ClassFileToSourceStubConverter) = converter.treeMaker.FqName("error.NonExistentClass") -private fun convertUserType(type: KtUserType, converter: ClassFileToSourceStubConverter): JCTree.JCExpression { - val qualifierExpression = type.qualifier?.let { convertUserType(it, converter) } +private fun convertUserType(type: KtUserType, converter: ClassFileToSourceStubConverter, reference: KtTypeReference?): JCTree.JCExpression { + val qualifierExpression = type.qualifier?.let { convertUserType(it, converter, null) } val referencedName = type.referencedName ?: "error" val treeMaker = converter.treeMaker val baseExpression = if (qualifierExpression == null) { - treeMaker.SimpleName(referencedName) + // This could be List or similar. List should be converted to java.util.List in this case. + val referenceTarget = converter.kaptContext.bindingContext[BindingContext.REFERENCE_TARGET, type.referenceExpression] + if (referenceTarget is ClassDescriptor) { + treeMaker.FqName(converter.typeMapper.mapType(referenceTarget.defaultType).className) + } + else { + treeMaker.SimpleName(referencedName) + } } else { treeMaker.Select(qualifierExpression, treeMaker.name(referencedName)) } @@ -75,20 +87,41 @@ private fun convertUserType(type: KtUserType, converter: ClassFileToSourceStubCo return baseExpression } - return treeMaker.TypeApply(baseExpression, mapJList(arguments) { convertTypeProjection(it, converter) }) + val baseType = reference?.let { converter.kaptContext.bindingContext[BindingContext.TYPE, it] } + + return treeMaker.TypeApply(baseExpression, mapJListIndexed(arguments) { index, projection -> + val argumentType = projection.typeReference?.let { converter.kaptContext.bindingContext[BindingContext.TYPE, it] } + val typeParameter = argumentType?.constructor?.parameters?.getOrNull(index) + val argument = baseType?.arguments?.getOrNull(index) + + val variance = if (argument != null && typeParameter != null) { + val argumentMode = TypeMappingMode.GENERIC_ARGUMENT.updateArgumentModeFromAnnotations(argument.type) + KotlinTypeMapper.getVarianceForWildcard(typeParameter, argument, argumentMode) + } + else { + null + } + + convertTypeProjection(projection, variance, converter) + }) } -private fun convertTypeProjection(type: KtTypeProjection, converter: ClassFileToSourceStubConverter): JCTree.JCExpression { +private fun convertTypeProjection(type: KtTypeProjection, variance: Variance?, converter: ClassFileToSourceStubConverter): JCTree.JCExpression { val reference = type.typeReference val treeMaker = converter.treeMaker + val projectionKind = type.projectionKind - return when (type.projectionKind) { - KtProjectionKind.IN -> treeMaker.Wildcard(treeMaker.TypeBoundKind(BoundKind.SUPER), - convertKtType(reference, converter, shouldBeBoxed = true)) - KtProjectionKind.OUT -> treeMaker.Wildcard(treeMaker.TypeBoundKind(BoundKind.EXTENDS), - convertKtType(reference, converter, shouldBeBoxed = true)) - KtProjectionKind.STAR -> treeMaker.Wildcard(treeMaker.TypeBoundKind(BoundKind.UNBOUND), null) - KtProjectionKind.NONE -> return convertKtType(reference, converter, shouldBeBoxed = true) + if (variance === Variance.INVARIANT) { + return convertKtType(reference, converter, shouldBeBoxed = true) + } + + return when { + projectionKind === KtProjectionKind.STAR -> treeMaker.Wildcard(treeMaker.TypeBoundKind(BoundKind.UNBOUND), null) + projectionKind === KtProjectionKind.IN || variance === Variance.IN_VARIANCE -> + treeMaker.Wildcard(treeMaker.TypeBoundKind(BoundKind.SUPER), convertKtType(reference, converter, shouldBeBoxed = true)) + projectionKind === KtProjectionKind.OUT || variance === Variance.OUT_VARIANCE -> + treeMaker.Wildcard(treeMaker.TypeBoundKind(BoundKind.EXTENDS), convertKtType(reference, converter, shouldBeBoxed = true)) + else -> convertKtType(reference, converter, shouldBeBoxed = true) // invariant } } diff --git a/plugins/kapt3/testData/converter/nonExistentClass.txt b/plugins/kapt3/testData/converter/nonExistentClass.txt index b0c42bb9494..374735408c3 100644 --- a/plugins/kapt3/testData/converter/nonExistentClass.txt +++ b/plugins/kapt3/testData/converter/nonExistentClass.txt @@ -1,16 +1,16 @@ @kotlin.Suppress(names = {"UNRESOLVED_REFERENCE"}) public final class NonExistentType { private static final ABCDEF a = null; - private static final List b = null; + private static final java.util.List b = null; private static final Function1 c = null; - private static final ABCDEF, kotlin.Unit>> d = null; + private static final ABCDEF, kotlin.Unit>> d = null; public static final NonExistentType INSTANCE = null; public final ABCDEF getA() { return null; } - public final List getB() { + public final java.util.List getB() { return null; } @@ -18,7 +18,7 @@ public final class NonExistentType { return null; } - public final ABCDEF, kotlin.Unit>> getD() { + public final ABCDEF, kotlin.Unit>> getD() { return null; } diff --git a/plugins/kapt3/testData/converter/nonExistentClassTypesConversion.kt b/plugins/kapt3/testData/converter/nonExistentClassTypesConversion.kt index c2ac8f30d60..46e2a675ed6 100644 --- a/plugins/kapt3/testData/converter/nonExistentClassTypesConversion.kt +++ b/plugins/kapt3/testData/converter/nonExistentClassTypesConversion.kt @@ -1,6 +1,8 @@ // NON_EXISTENT_CLASS // NO_VALIDATION +import java.util.Calendar + @Suppress("UNRESOLVED_REFERENCE") class Test { lateinit var a: ABC @@ -23,6 +25,8 @@ class Test { lateinit var o11: List>>>>>>>>> lateinit var o10: List>>>>>>>> + lateinit var p: Calendar.Builder + fun f1(a: ABC): BCD? { return null } diff --git a/plugins/kapt3/testData/converter/nonExistentClassTypesConversion.txt b/plugins/kapt3/testData/converter/nonExistentClassTypesConversion.txt index f4835116d5e..4611c33cf35 100644 --- a/plugins/kapt3/testData/converter/nonExistentClassTypesConversion.txt +++ b/plugins/kapt3/testData/converter/nonExistentClassTypesConversion.txt @@ -12,20 +12,21 @@ public final class MyType { public final class Test { public ABC a; private final ABC b = null; - private final List c = null; - private final List>>> d = null; - public List> e; + private final java.util.List c = null; + private final java.util.List>>> d = null; + public java.util.List> e; public ABC f; public java.util.List g; public ABC h; - public Function2, CDE> i; + public Function2, CDE> i; public Function0 j; - public Function2, CDE> k; + public Function2, CDE> k; public ABC.BCD.EFG l; private final error.NonExistentClass m = null; private final java.lang.String n = ""; public java.util.List>>>>>>>>> o11; - public List>>>>>>>> o10; + public java.util.List>>>>>>>> o10; + public java.util.Calendar.Builder p; public final ABC getA() { return null; @@ -38,19 +39,19 @@ public final class Test { return null; } - public final List getC() { + public final java.util.List getC() { return null; } - public final List>>> getD() { + public final java.util.List>>> getD() { return null; } - public final List> getE() { + public final java.util.List> getE() { return null; } - public final void setE(List> p0) { + public final void setE(java.util.List> p0) { } public final ABC getF() { @@ -74,11 +75,11 @@ public final class Test { public final void setH(ABC p0) { } - public final Function2, CDE> getI() { + public final Function2, CDE> getI() { return null; } - public final void setI(Function2, CDE> p0) { + public final void setI(Function2, CDE> p0) { } public final Function0 getJ() { @@ -88,11 +89,11 @@ public final class Test { public final void setJ(Function0 p0) { } - public final Function2, CDE> getK() { + public final Function2, CDE> getK() { return null; } - public final void setK(Function2, CDE> p0) { + public final void setK(Function2, CDE> p0) { } public final ABC.BCD.EFG getL() { @@ -117,11 +118,18 @@ public final class Test { public final void setO11(java.util.List>>>>>>>>> p0) { } - public final List>>>>>>>> getO10() { + public final java.util.List>>>>>>>> getO10() { return null; } - public final void setO10(List>>>>>>>> p0) { + public final void setO10(java.util.List>>>>>>>> p0) { + } + + public final java.util.Calendar.Builder getP() { + return null; + } + + public final void setP(java.util.Calendar.Builder p0) { } public final BCD f1(ABC a) {