diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java index 99b75d91ffa..d8bcec9079a 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java @@ -24,6 +24,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.resolve.java.resolver.JavaAnnotationResolver; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.checker.JetTypeChecker; @@ -267,4 +268,18 @@ public class JavaTypeTransformer { return classType.isRaw() || argumentsExpected && classType.getParameterCount() == 0; } + public static TypeUsage adjustTypeUsageWithMutabilityAnnotations(PsiModifierListOwner owner, TypeUsage originalTypeUsage) { + EnumSet signatureTypeUsages = + EnumSet.of(TypeUsage.MEMBER_SIGNATURE_COVARIANT, TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT, TypeUsage.MEMBER_SIGNATURE_INVARIANT); + if (!signatureTypeUsages.contains(originalTypeUsage)) { + return originalTypeUsage; + } + if (JavaAnnotationResolver.findAnnotationWithExternal(owner, JvmAbi.JETBRAINS_MUTABLE_ANNOTATION.getFqName().getFqName()) != null) { + return TypeUsage.MEMBER_SIGNATURE_COVARIANT; + } + if (JavaAnnotationResolver.findAnnotationWithExternal(owner, JvmAbi.JETBRAINS_READONLY_ANNOTATION.getFqName().getFqName()) != null) { + return TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT; + } + return originalTypeUsage; + } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JvmAbi.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JvmAbi.java index 447c8696a6a..45cc7f668cf 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JvmAbi.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JvmAbi.java @@ -46,6 +46,11 @@ public class JvmAbi { public static final JvmClassName JETBRAINS_NOT_NULL_ANNOTATION = JvmClassName.byFqNameWithoutInnerClasses("org.jetbrains.annotations.NotNull"); + public static final JvmClassName JETBRAINS_MUTABLE_ANNOTATION = + JvmClassName.byFqNameWithoutInnerClasses("org.jetbrains.annotations.Mutable"); + public static final JvmClassName JETBRAINS_READONLY_ANNOTATION = + JvmClassName.byFqNameWithoutInnerClasses("org.jetbrains.annotations.ReadOnly"); + public static boolean isClassObjectFqName(@NotNull FqName fqName) { return fqName.lastSegmentIs(Name.identifier(CLASS_OBJECT_CLASS_NAME)); } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaFunctionResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaFunctionResolver.java index d7c0cb5b2ed..f04277d464c 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaFunctionResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaFunctionResolver.java @@ -21,6 +21,7 @@ import com.google.common.collect.Sets; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiModifierListOwner; import com.intellij.psi.PsiType; import com.intellij.psi.util.PsiFormatUtil; import org.jetbrains.annotations.NotNull; @@ -45,10 +46,7 @@ import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import javax.inject.Inject; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*; import static org.jetbrains.jet.lang.resolve.OverridingUtil.*; @@ -143,7 +141,6 @@ public final class JavaFunctionResolver { functionDescriptorImpl, context); - JavaDescriptorResolver.ValueParameterDescriptors valueParameterDescriptors = parameterResolver .resolveParameterDescriptors(functionDescriptorImpl, method.getParameters(), methodTypeVariableResolver); JetType returnType = makeReturnType(returnPsiType, method, methodTypeVariableResolver); @@ -414,8 +411,8 @@ public final class JavaFunctionResolver { transformedType = typeTransformer.transformToType(returnTypeFromAnnotation, typeVariableResolver); } else { - transformedType = typeTransformer.transformToType( - returnType, TypeUsage.MEMBER_SIGNATURE_COVARIANT, typeVariableResolver); + TypeUsage typeUsage = JavaTypeTransformer.adjustTypeUsageWithMutabilityAnnotations(method.getPsiMethod(), TypeUsage.MEMBER_SIGNATURE_COVARIANT); + transformedType = typeTransformer.transformToType(returnType, typeUsage, typeVariableResolver); } if (JavaAnnotationResolver.findAnnotationWithExternal(method.getPsiMethod(), JvmAbi.JETBRAINS_NOT_NULL_ANNOTATION.getFqName().getFqName()) != diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaValueParameterResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaValueParameterResolver.java index 5c337ef3449..baa581a7593 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaValueParameterResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaValueParameterResolver.java @@ -71,8 +71,8 @@ public final class JavaValueParameterResolver { outType = getTypeTransformer().transformToType(typeFromAnnotation, typeVariableResolver); } else { - outType = getTypeTransformer().transformToType(psiType, TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT, - typeVariableResolver); + TypeUsage typeUsage = JavaTypeTransformer.adjustTypeUsageWithMutabilityAnnotations(parameter.getPsiParameter(), TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT); + outType = getTypeTransformer().transformToType(psiType, typeUsage, typeVariableResolver); } JetType varargElementType;