Java declaration annotations are treated as type annotations

This is needed, for example, to approximate flexible types correctly when rendering them in the code
This commit is contained in:
Andrey Breslav
2014-09-17 14:25:00 +04:00
parent bd21e487fc
commit 91b0b83ec3
33 changed files with 119 additions and 64 deletions
@@ -4,7 +4,7 @@ public/*package*/ /*synthesized*/ fun A(/*0*/ function: (kotlin.String) -> kotli
public/*package*/ trait A { public/*package*/ trait A {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract fun foo(/*0*/ kotlinSignatureName: kotlin.String): kotlin.Unit public abstract fun foo(/*0*/ kotlinSignatureName: kotlin.String!): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
} }
@@ -9,6 +9,6 @@ public trait InheritNullability {
public trait Super { public trait Super {
public abstract fun dummy(): kotlin.Unit public abstract fun dummy(): kotlin.Unit
public abstract fun foo(/*0*/ p0: kotlin.String!): kotlin.Unit public abstract fun foo(/*0*/ org.jetbrains.annotations.NotNull() p0: kotlin.String!): kotlin.Unit
} }
} }
@@ -4,7 +4,7 @@ public trait Kt3302 {
public trait BSONObject { public trait BSONObject {
public abstract fun dummy(): kotlin.Unit public abstract fun dummy(): kotlin.Unit
public abstract fun put(/*0*/ p0: kotlin.String!, /*1*/ p1: kotlin.Any!): kotlin.Any! public abstract fun put(/*0*/ org.jetbrains.annotations.NotNull() p0: kotlin.String!, /*1*/ org.jetbrains.annotations.NotNull() p1: kotlin.Any!): kotlin.Any!
} }
public trait BasicBSONObject : test.Kt3302.LinkedHashMap<kotlin.String!, kotlin.Any!>, test.Kt3302.BSONObject { public trait BasicBSONObject : test.Kt3302.LinkedHashMap<kotlin.String!, kotlin.Any!>, test.Kt3302.BSONObject {
@@ -9,6 +9,6 @@ public trait NotNullToNullable {
public trait Super { public trait Super {
public abstract fun dummy(): kotlin.Unit public abstract fun dummy(): kotlin.Unit
public abstract fun foo(/*0*/ p0: kotlin.String!): kotlin.Unit public abstract fun foo(/*0*/ org.jetbrains.annotations.NotNull() p0: kotlin.String!): kotlin.Unit
} }
} }
@@ -4,7 +4,7 @@ public trait NullableToNotNull {
public trait Sub : test.NullableToNotNull.Super { public trait Sub : test.NullableToNotNull.Super {
public abstract override /*1*/ /*fake_override*/ fun dummy(): kotlin.Unit public abstract override /*1*/ /*fake_override*/ fun dummy(): kotlin.Unit
public abstract override /*1*/ fun foo(/*0*/ p0: kotlin.String!): kotlin.Unit public abstract override /*1*/ fun foo(/*0*/ org.jetbrains.annotations.NotNull() p0: kotlin.String!): kotlin.Unit
} }
public trait Super { public trait Super {
@@ -9,7 +9,7 @@ public trait SubclassFromGenericAndNot {
public trait NonGeneric { public trait NonGeneric {
public abstract fun dummy(): kotlin.Unit public abstract fun dummy(): kotlin.Unit
public abstract fun foo(/*0*/ p0: kotlin.String!): kotlin.Unit public abstract fun foo(/*0*/ org.jetbrains.annotations.NotNull() p0: kotlin.String!): kotlin.Unit
} }
public trait Sub : test.SubclassFromGenericAndNot.NonGeneric, test.SubclassFromGenericAndNot.Generic<kotlin.String!> { public trait Sub : test.SubclassFromGenericAndNot.NonGeneric, test.SubclassFromGenericAndNot.Generic<kotlin.String!> {
@@ -4,7 +4,7 @@ public trait AddNotNullJavaSubtype {
public trait Sub : test.AddNotNullJavaSubtype.Super { public trait Sub : test.AddNotNullJavaSubtype.Super {
public abstract override /*1*/ /*fake_override*/ fun dummy(): kotlin.Unit public abstract override /*1*/ /*fake_override*/ fun dummy(): kotlin.Unit
public abstract override /*1*/ fun foo(): kotlin.String! org.jetbrains.annotations.NotNull() public abstract override /*1*/ fun foo(): kotlin.String!
} }
public trait Super { public trait Super {
@@ -4,7 +4,7 @@ public trait AddNotNullSameJavaType {
public trait Sub : test.AddNotNullSameJavaType.Super { public trait Sub : test.AddNotNullSameJavaType.Super {
public abstract override /*1*/ /*fake_override*/ fun dummy(): kotlin.Unit public abstract override /*1*/ /*fake_override*/ fun dummy(): kotlin.Unit
public abstract override /*1*/ fun foo(): kotlin.CharSequence! org.jetbrains.annotations.NotNull() public abstract override /*1*/ fun foo(): kotlin.CharSequence!
} }
public trait Super { public trait Super {
@@ -9,6 +9,6 @@ public trait AddNullabilityJavaSubtype {
public trait Super { public trait Super {
public abstract fun dummy(): kotlin.Unit public abstract fun dummy(): kotlin.Unit
public abstract fun foo(): kotlin.CharSequence! org.jetbrains.annotations.NotNull() public abstract fun foo(): kotlin.CharSequence!
} }
} }
@@ -9,6 +9,6 @@ public trait AddNullabilitySameJavaType {
public trait Super { public trait Super {
public abstract fun dummy(): kotlin.Unit public abstract fun dummy(): kotlin.Unit
public abstract fun foo(): kotlin.CharSequence! org.jetbrains.annotations.NotNull() public abstract fun foo(): kotlin.CharSequence!
} }
} }
@@ -9,6 +9,6 @@ public trait InheritNullabilityJavaSubtype {
public trait Super { public trait Super {
public abstract fun dummy(): kotlin.Unit public abstract fun dummy(): kotlin.Unit
public abstract fun foo(): kotlin.CharSequence! org.jetbrains.annotations.NotNull() public abstract fun foo(): kotlin.CharSequence!
} }
} }
@@ -9,6 +9,6 @@ public trait InheritNullabilitySameJavaType {
public trait Super { public trait Super {
public abstract fun dummy(): kotlin.Unit public abstract fun dummy(): kotlin.Unit
public abstract fun foo(): kotlin.CharSequence! org.jetbrains.annotations.NotNull() public abstract fun foo(): kotlin.CharSequence!
} }
} }
@@ -14,6 +14,6 @@ public trait TwoSuperclassesReturnJavaSubtype {
public trait Super2 { public trait Super2 {
public abstract fun dummy(): kotlin.Unit public abstract fun dummy(): kotlin.Unit
public abstract fun foo(): kotlin.CharSequence! org.jetbrains.annotations.NotNull() public abstract fun foo(): kotlin.CharSequence!
} }
} }
@@ -14,6 +14,6 @@ public trait TwoSuperclassesReturnSameJavaType {
public trait Super2 { public trait Super2 {
public abstract fun dummy(): kotlin.Unit public abstract fun dummy(): kotlin.Unit
public abstract fun foo(): kotlin.CharSequence! org.jetbrains.annotations.NotNull() public abstract fun foo(): kotlin.CharSequence!
} }
} }
@@ -9,6 +9,6 @@ public trait TypeParamOfClass {
public trait Super</*0*/ T> { public trait Super</*0*/ T> {
public abstract fun dummy(): kotlin.Unit public abstract fun dummy(): kotlin.Unit
public abstract fun foo(): T! org.jetbrains.annotations.NotNull() public abstract fun foo(): T!
} }
} }
@@ -9,6 +9,6 @@ public trait TypeParamOfClassSubstituted {
public trait Super</*0*/ T> { public trait Super</*0*/ T> {
public abstract fun dummy(): kotlin.Unit public abstract fun dummy(): kotlin.Unit
public abstract fun foo(): T! org.jetbrains.annotations.NotNull() public abstract fun foo(): T!
} }
} }
@@ -9,6 +9,6 @@ public trait TypeParamOfFun {
public trait Super { public trait Super {
public abstract fun dummy(): kotlin.Unit public abstract fun dummy(): kotlin.Unit
public abstract fun </*0*/ T> foo(): T! org.jetbrains.annotations.NotNull() public abstract fun </*0*/ T> foo(): T!
} }
} }
@@ -10,7 +10,7 @@ public open class ModalityOfFakeOverrides : java.util.AbstractList<kotlin.String
public open override /*1*/ /*fake_override*/ fun clear(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun clear(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun contains(/*0*/ o: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun contains(/*0*/ o: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun containsAll(/*0*/ c: kotlin.Collection<kotlin.Any?>): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun containsAll(/*0*/ c: kotlin.Collection<kotlin.Any?>): kotlin.Boolean
public open override /*1*/ fun get(/*0*/ index: kotlin.Int): kotlin.String! org.jetbrains.annotations.NotNull() public open override /*1*/ fun get(/*0*/ index: kotlin.Int): kotlin.String!
public open override /*1*/ /*fake_override*/ fun indexOf(/*0*/ o: kotlin.Any!): kotlin.Int public open override /*1*/ /*fake_override*/ fun indexOf(/*0*/ o: kotlin.Any!): kotlin.Int
public open override /*1*/ /*fake_override*/ fun isEmpty(): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun isEmpty(): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun iterator(): kotlin.(Mutable)Iterator<kotlin.String!>! public open override /*1*/ /*fake_override*/ fun iterator(): kotlin.(Mutable)Iterator<kotlin.String!>!
@@ -1,8 +1,8 @@
package test package test
public trait LoadIterableWithNullability</*0*/ T> { public trait LoadIterableWithNullability</*0*/ T> {
org.jetbrains.annotations.Mutable() public abstract fun getIterable(): kotlin.(Mutable)Iterable<T!>! org.jetbrains.annotations.NotNull() org.jetbrains.annotations.Mutable() public abstract fun getIterable(): kotlin.(Mutable)Iterable<T!>!
org.jetbrains.annotations.ReadOnly() public abstract fun getReadOnlyIterable(): kotlin.(Mutable)Iterable<T!>! org.jetbrains.annotations.NotNull() org.jetbrains.annotations.ReadOnly() public abstract fun getReadOnlyIterable(): kotlin.(Mutable)Iterable<T!>!
public abstract fun setIterable(/*0*/ org.jetbrains.annotations.Mutable() p0: kotlin.(Mutable)Iterable<T!>!): kotlin.Unit public abstract fun setIterable(/*0*/ org.jetbrains.annotations.Mutable() org.jetbrains.annotations.NotNull() p0: kotlin.(Mutable)Iterable<T!>!): kotlin.Unit
public abstract fun setReadOnlyIterable(/*0*/ org.jetbrains.annotations.ReadOnly() p0: kotlin.(Mutable)Iterable<T!>!): kotlin.Unit public abstract fun setReadOnlyIterable(/*0*/ org.jetbrains.annotations.ReadOnly() org.jetbrains.annotations.NotNull() p0: kotlin.(Mutable)Iterable<T!>!): kotlin.Unit
} }
@@ -2,5 +2,5 @@ package test
public open class NotNullField { public open class NotNullField {
public constructor NotNullField() public constructor NotNullField()
public final var hi: kotlin.String! org.jetbrains.annotations.NotNull() public final var hi: kotlin.String!
} }
@@ -2,5 +2,5 @@ package test
public open class NotNullIntArray { public open class NotNullIntArray {
public constructor NotNullIntArray() public constructor NotNullIntArray()
public open fun hi(): kotlin.IntArray! org.jetbrains.annotations.NotNull() public open fun hi(): kotlin.IntArray!
} }
@@ -2,5 +2,5 @@ package test
public open class NotNullMethod { public open class NotNullMethod {
public constructor NotNullMethod() public constructor NotNullMethod()
public open fun hi(): kotlin.String! org.jetbrains.annotations.NotNull() public open fun hi(): kotlin.String!
} }
@@ -2,5 +2,5 @@ package test
public open class NotNullObjectArray { public open class NotNullObjectArray {
public constructor NotNullObjectArray() public constructor NotNullObjectArray()
public open fun hi(): kotlin.Array<(out) kotlin.Any!>! org.jetbrains.annotations.NotNull() public open fun hi(): kotlin.Array<(out) kotlin.Any!>!
} }
@@ -2,5 +2,5 @@ package test
public open class NotNullParameter { public open class NotNullParameter {
public constructor NotNullParameter() public constructor NotNullParameter()
public open fun hi(/*0*/ p0: kotlin.String!): kotlin.Unit public open fun hi(/*0*/ org.jetbrains.annotations.NotNull() p0: kotlin.String!): kotlin.Unit
} }
@@ -98,17 +98,23 @@ public final class JvmAnnotationNames {
public static final FqName OLD_KOTLIN_TRAIT_IMPL = new FqName("jet.KotlinTraitImpl"); public static final FqName OLD_KOTLIN_TRAIT_IMPL = new FqName("jet.KotlinTraitImpl");
private static final Set<JvmClassName> SPECIAL_ANNOTATIONS = new HashSet<JvmClassName>(); private static final Set<JvmClassName> SPECIAL_ANNOTATIONS = new HashSet<JvmClassName>();
private static final Set<JvmClassName> NULLABILITY_ANNOTATIONS = new HashSet<JvmClassName>();
static { static {
for (FqName fqName : Arrays.asList(KOTLIN_CLASS, KOTLIN_PACKAGE, KOTLIN_SIGNATURE, JETBRAINS_NOT_NULL_ANNOTATION, for (FqName fqName : Arrays.asList(KOTLIN_CLASS, KOTLIN_PACKAGE, KOTLIN_SIGNATURE)) {
JETBRAINS_NULLABLE_ANNOTATION)) {
SPECIAL_ANNOTATIONS.add(JvmClassName.byFqNameWithoutInnerClasses(fqName)); SPECIAL_ANNOTATIONS.add(JvmClassName.byFqNameWithoutInnerClasses(fqName));
} }
SPECIAL_ANNOTATIONS.add(KotlinSyntheticClass.CLASS_NAME); SPECIAL_ANNOTATIONS.add(KotlinSyntheticClass.CLASS_NAME);
for (FqName fqName : Arrays.asList(JETBRAINS_NOT_NULL_ANNOTATION, JETBRAINS_NULLABLE_ANNOTATION)) {
NULLABILITY_ANNOTATIONS.add(JvmClassName.byFqNameWithoutInnerClasses(fqName));
}
} }
public static boolean isSpecialAnnotation(@NotNull ClassId classId) { public static boolean isSpecialAnnotation(@NotNull ClassId classId, boolean javaSpecificAnnotationsAreSpecial) {
JvmClassName className = JvmClassName.byClassId(classId); JvmClassName className = JvmClassName.byClassId(classId);
return SPECIAL_ANNOTATIONS.contains(className) || className.getInternalName().startsWith("jet/runtime/typeinfo/"); return (javaSpecificAnnotationsAreSpecial && NULLABILITY_ANNOTATIONS.contains(className))
|| SPECIAL_ANNOTATIONS.contains(className)
|| className.getInternalName().startsWith("jet/runtime/typeinfo/");
} }
private JvmAnnotationNames() { private JvmAnnotationNames() {
@@ -24,14 +24,18 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames
import org.jetbrains.jet.lang.resolve.java.lazy.descriptors.resolveAnnotation import org.jetbrains.jet.lang.resolve.java.lazy.descriptors.resolveAnnotation
class LazyJavaAnnotations(c: LazyJavaResolverContextWithTypes, val annotationOwner: JavaAnnotationOwner) : Annotations { class LazyJavaAnnotations(
c: LazyJavaResolverContextWithTypes,
val annotationOwner: JavaAnnotationOwner,
private val extraLookup: (FqName) -> JavaAnnotation? = { null }
) : Annotations {
private val annotationDescriptors = c.storageManager.createMemoizedFunctionWithNullableValues { private val annotationDescriptors = c.storageManager.createMemoizedFunctionWithNullableValues {
(annotation: JavaAnnotation) -> (annotation: JavaAnnotation) ->
c.resolveAnnotation(annotation) c.resolveAnnotation(annotation)
} }
override fun findAnnotation(fqName: FqName): AnnotationDescriptor? { override fun findAnnotation(fqName: FqName): AnnotationDescriptor? {
val jAnnotation = annotationOwner.findAnnotation(fqName) val jAnnotation = annotationOwner.findAnnotation(fqName) ?: extraLookup(fqName)
if (jAnnotation == null) return null if (jAnnotation == null) return null
return annotationDescriptors(jAnnotation) return annotationDescriptors(jAnnotation)
@@ -45,7 +49,7 @@ class LazyJavaAnnotations(c: LazyJavaResolverContextWithTypes, val annotationOwn
} }
fun LazyJavaResolverContextWithTypes.resolveAnnotations(annotationsOwner: JavaAnnotationOwner): Annotations fun LazyJavaResolverContextWithTypes.resolveAnnotations(annotationsOwner: JavaAnnotationOwner): Annotations
= LazyJavaAnnotations(this, annotationsOwner) = LazyJavaAnnotations(this, annotationsOwner) { fqName -> externalAnnotationResolver.findExternalAnnotation(annotationsOwner, fqName) }
private fun GlobalJavaResolverContext.hasAnnotation(owner: JavaAnnotationOwner, annotationFqName: FqName): Boolean private fun GlobalJavaResolverContext.hasAnnotation(owner: JavaAnnotationOwner, annotationFqName: FqName): Boolean
= owner.findAnnotation(annotationFqName) != null || externalAnnotationResolver.findExternalAnnotation(owner, annotationFqName) != null = owner.findAnnotation(annotationFqName) != null || externalAnnotationResolver.findExternalAnnotation(owner, annotationFqName) != null
@@ -37,6 +37,7 @@ import org.jetbrains.jet.renderer.DescriptorRenderer
import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap
import org.jetbrains.jet.lang.resolve.resolveTopLevelClass import org.jetbrains.jet.lang.resolve.resolveTopLevelClass
import org.jetbrains.jet.lang.resolve.kotlin.DeserializedResolverUtils.kotlinFqNameToJavaFqName import org.jetbrains.jet.lang.resolve.kotlin.DeserializedResolverUtils.kotlinFqNameToJavaFqName
import org.jetbrains.jet.lang.resolve.java.PLATFORM_TYPES
private object DEPRECATED_IN_JAVA : JavaLiteralAnnotationArgument { private object DEPRECATED_IN_JAVA : JavaLiteralAnnotationArgument {
override val name: Name? = null override val name: Name? = null
@@ -45,7 +46,7 @@ private object DEPRECATED_IN_JAVA : JavaLiteralAnnotationArgument {
fun LazyJavaResolverContextWithTypes.resolveAnnotation(annotation: JavaAnnotation): LazyJavaAnnotationDescriptor? { fun LazyJavaResolverContextWithTypes.resolveAnnotation(annotation: JavaAnnotation): LazyJavaAnnotationDescriptor? {
val classId = annotation.getClassId() val classId = annotation.getClassId()
if (classId == null || JvmAnnotationNames.isSpecialAnnotation(classId)) return null if (classId == null || JvmAnnotationNames.isSpecialAnnotation(classId, !PLATFORM_TYPES)) return null
return LazyJavaAnnotationDescriptor(this, annotation) return LazyJavaAnnotationDescriptor(this, annotation)
} }
@@ -34,8 +34,6 @@ import org.jetbrains.jet.lang.types.TypeUtils
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
import org.jetbrains.jet.lang.resolve.java.lazy.hasNotNullAnnotation import org.jetbrains.jet.lang.resolve.java.lazy.hasNotNullAnnotation
import org.jetbrains.jet.lang.resolve.java.lazy.types.LazyJavaTypeAttributes import org.jetbrains.jet.lang.resolve.java.lazy.types.LazyJavaTypeAttributes
import org.jetbrains.jet.lang.resolve.java.lazy.hasMutableAnnotation
import org.jetbrains.jet.lang.resolve.java.lazy.hasReadOnlyAnnotation
import org.jetbrains.jet.lang.resolve.java.structure.JavaValueParameter import org.jetbrains.jet.lang.resolve.java.structure.JavaValueParameter
import java.util.ArrayList import java.util.ArrayList
import java.util.LinkedHashSet import java.util.LinkedHashSet
@@ -46,7 +44,7 @@ import org.jetbrains.jet.lang.resolve.java.resolver.ExternalSignatureResolver
import org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils import org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils
import org.jetbrains.jet.utils.* import org.jetbrains.jet.utils.*
import org.jetbrains.jet.lang.resolve.java.PLATFORM_TYPES import org.jetbrains.jet.lang.resolve.java.PLATFORM_TYPES
import org.jetbrains.jet.lang.types.lowerIfFlexible import org.jetbrains.jet.lang.descriptors.annotations.Annotations
public abstract class LazyJavaMemberScope( public abstract class LazyJavaMemberScope(
protected val c: LazyJavaResolverContextWithTypes, protected val c: LazyJavaResolverContextWithTypes,
@@ -116,8 +114,9 @@ public abstract class LazyJavaMemberScope(
fun resolveMethodToFunctionDescriptor(method: JavaMethod, record: Boolean = true): JavaMethodDescriptor { fun resolveMethodToFunctionDescriptor(method: JavaMethod, record: Boolean = true): JavaMethodDescriptor {
val annotations = c.resolveAnnotations(method)
val functionDescriptorImpl = JavaMethodDescriptor.createJavaMethod( val functionDescriptorImpl = JavaMethodDescriptor.createJavaMethod(
_containingDeclaration, c.resolveAnnotations(method), method.getName(), c.sourceElementFactory.source(method) _containingDeclaration, annotations, method.getName(), c.sourceElementFactory.source(method)
) )
val c = c.child(functionDescriptorImpl, method.getTypeParameters().toSet()) val c = c.child(functionDescriptorImpl, method.getTypeParameters().toSet())
@@ -126,13 +125,7 @@ public abstract class LazyJavaMemberScope(
val valueParameters = resolveValueParameters(c, functionDescriptorImpl, method.getValueParameters()) val valueParameters = resolveValueParameters(c, functionDescriptorImpl, method.getValueParameters())
val annotationMethod = method.getContainingClass().isAnnotationType() val annotationMethod = method.getContainingClass().isAnnotationType()
val returnTypeAttrs = LazyJavaTypeAttributes(c, method, TypeUsage.MEMBER_SIGNATURE_COVARIANT, allowFlexible = !annotationMethod) { val returnTypeAttrs = LazyJavaTypeAttributes(c, method, TypeUsage.MEMBER_SIGNATURE_COVARIANT, annotations, allowFlexible = !annotationMethod)
if (c.hasReadOnlyAnnotation(method) && !c.hasMutableAnnotation(method))
TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT
else
TypeUsage.MEMBER_SIGNATURE_COVARIANT
}
val returnJavaType = method.getReturnType() ?: throw IllegalStateException("Constructor passed as method: $method") val returnJavaType = method.getReturnType() ?: throw IllegalStateException("Constructor passed as method: $method")
// Annotation arguments are never null in Java // Annotation arguments are never null in Java
val returnType = c.typeResolver.transformJavaType(returnJavaType, returnTypeAttrs).let { val returnType = c.typeResolver.transformJavaType(returnJavaType, returnTypeAttrs).let {
@@ -174,10 +167,8 @@ public abstract class LazyJavaMemberScope(
pair -> pair ->
val (index, javaParameter) = pair val (index, javaParameter) = pair
val typeUsage = LazyJavaTypeAttributes(c, javaParameter, TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT) { val annotations = c.resolveAnnotations(javaParameter)
if (c.hasMutableAnnotation(javaParameter)) TypeUsage.MEMBER_SIGNATURE_COVARIANT else TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT val typeUsage = LazyJavaTypeAttributes(c, javaParameter, TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT, annotations)
}
val (outType, varargElementType) = val (outType, varargElementType) =
if (javaParameter.isVararg()) { if (javaParameter.isVararg()) {
val paramType = javaParameter.getType() val paramType = javaParameter.getType()
@@ -213,7 +204,7 @@ public abstract class LazyJavaMemberScope(
function, function,
null, null,
index, index,
c.resolveAnnotations(javaParameter), annotations,
name, name,
outType, outType,
false, false,
@@ -254,7 +245,7 @@ public abstract class LazyJavaMemberScope(
val propertyDescriptor = createPropertyDescriptor(field) val propertyDescriptor = createPropertyDescriptor(field)
propertyDescriptor.initialize(null, null) propertyDescriptor.initialize(null, null)
val propertyType = getPropertyType(field) val propertyType = getPropertyType(field, propertyDescriptor.getAnnotations())
val effectiveSignature = c.externalSignatureResolver.resolveAlternativeFieldSignature(field, propertyType, isVar) val effectiveSignature = c.externalSignatureResolver.resolveAlternativeFieldSignature(field, propertyType, isVar)
val signatureErrors = effectiveSignature.getErrors() val signatureErrors = effectiveSignature.getErrors()
if (!signatureErrors.isEmpty()) { if (!signatureErrors.isEmpty()) {
@@ -285,7 +276,7 @@ public abstract class LazyJavaMemberScope(
c.sourceElementFactory.source(field)) c.sourceElementFactory.source(field))
} }
private fun getPropertyType(field: JavaField): JetType { private fun getPropertyType(field: JavaField, annotations: Annotations): JetType {
// Fields do not have their own generic parameters // Fields do not have their own generic parameters
val finalStatic = field.isFinal() && field.isStatic() val finalStatic = field.isFinal() && field.isStatic()
@@ -293,7 +284,7 @@ public abstract class LazyJavaMemberScope(
val allowFlexible = PLATFORM_TYPES && !(finalStatic && c.javaPropertyInitializerEvaluator.isNotNullCompileTimeConstant(field)) val allowFlexible = PLATFORM_TYPES && !(finalStatic && c.javaPropertyInitializerEvaluator.isNotNullCompileTimeConstant(field))
val propertyType = c.typeResolver.transformJavaType( val propertyType = c.typeResolver.transformJavaType(
field.getType(), field.getType(),
LazyJavaTypeAttributes(c, field, TypeUsage.MEMBER_SIGNATURE_INVARIANT, allowFlexible) LazyJavaTypeAttributes(c, field, TypeUsage.MEMBER_SIGNATURE_INVARIANT, annotations, allowFlexible)
) )
if ((!allowFlexible || !PLATFORM_TYPES) && finalStatic) { if ((!allowFlexible || !PLATFORM_TYPES) && finalStatic) {
return TypeUtils.makeNotNullable(propertyType) return TypeUtils.makeNotNullable(propertyType)
@@ -33,6 +33,10 @@ import java.util.HashSet
import org.jetbrains.jet.lang.types.checker.JetTypeChecker import org.jetbrains.jet.lang.types.checker.JetTypeChecker
import org.jetbrains.jet.lang.resolve.java.PLATFORM_TYPES import org.jetbrains.jet.lang.resolve.java.PLATFORM_TYPES
import org.jetbrains.jet.lang.resolve.java.lazy.types.Flexibility.* import org.jetbrains.jet.lang.resolve.java.lazy.types.Flexibility.*
import org.jetbrains.jet.lang.descriptors.annotations.Annotations
import org.jetbrains.jet.lang.resolve.name.FqName
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames
class LazyJavaTypeResolver( class LazyJavaTypeResolver(
private val c: LazyJavaResolverContext, private val c: LazyJavaResolverContext,
@@ -262,6 +266,8 @@ class LazyJavaTypeResolver(
} }
} }
override fun isNullable(): Boolean = _nullable() override fun isNullable(): Boolean = _nullable()
override fun getAnnotations() = attr.annotations
} }
public open class FlexibleJavaClassifierType protected ( public open class FlexibleJavaClassifierType protected (
@@ -312,6 +318,7 @@ trait JavaTypeAttributes {
get() = INFLEXIBLE get() = INFLEXIBLE
val allowFlexible: Boolean val allowFlexible: Boolean
get() = true get() = true
val annotations: Annotations
} }
fun JavaTypeAttributes.isFlexible() = flexibility != INFLEXIBLE fun JavaTypeAttributes.isFlexible() = flexibility != INFLEXIBLE
@@ -326,23 +333,32 @@ class LazyJavaTypeAttributes(
c: LazyJavaResolverContext, c: LazyJavaResolverContext,
val annotationOwner: JavaAnnotationOwner, val annotationOwner: JavaAnnotationOwner,
override val howThisTypeIsUsed: TypeUsage, override val howThisTypeIsUsed: TypeUsage,
override val allowFlexible: Boolean = true, override val annotations: Annotations,
computeHowThisTypeIsUsedAccordingToAnnotations: () -> TypeUsage = {howThisTypeIsUsed} override val allowFlexible: Boolean = true
): JavaTypeAttributes { ): JavaTypeAttributes {
override val howThisTypeIsUsedAccordingToAnnotations: TypeUsage by c.storageManager.createLazyValue( override val howThisTypeIsUsedAccordingToAnnotations: TypeUsage by c.storageManager.createLazyValue {
computeHowThisTypeIsUsedAccordingToAnnotations if (annotations.isMarkedReadOnly() && !annotations.isMarkedMutable())
) TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT
else
TypeUsage.MEMBER_SIGNATURE_COVARIANT
}
override val isMarkedNotNull: Boolean by c.storageManager.createLazyValue { c.hasNotNullAnnotation(annotationOwner) } override val isMarkedNotNull: Boolean by c.storageManager.createLazyValue { c.hasNotNullAnnotation(annotationOwner) }
} }
private fun Annotations.isMarkedReadOnly() = findAnnotation(JvmAnnotationNames.JETBRAINS_READONLY_ANNOTATION) != null
private fun Annotations.isMarkedMutable() = findAnnotation(JvmAnnotationNames.JETBRAINS_MUTABLE_ANNOTATION) != null
private fun Annotations.isMarkedNotNull() = findAnnotation(JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION) != null
fun TypeUsage.toAttributes(allowFlexible: Boolean = true) = object : JavaTypeAttributes { fun TypeUsage.toAttributes(allowFlexible: Boolean = true) = object : JavaTypeAttributes {
override val howThisTypeIsUsed: TypeUsage = this@toAttributes override val howThisTypeIsUsed: TypeUsage = this@toAttributes
override val howThisTypeIsUsedAccordingToAnnotations: TypeUsage override val howThisTypeIsUsedAccordingToAnnotations: TypeUsage
get() = howThisTypeIsUsed get() = howThisTypeIsUsed
override val isMarkedNotNull: Boolean = false override val isMarkedNotNull: Boolean = false
override val allowFlexible: Boolean = allowFlexible override val allowFlexible: Boolean = allowFlexible
override val annotations: Annotations = Annotations.EMPTY
} }
fun JavaTypeAttributes.toFlexible(flexibility: Flexibility) = fun JavaTypeAttributes.toFlexible(flexibility: Flexibility) =
@@ -119,7 +119,7 @@ public class AnnotationDescriptorLoader extends BaseDescriptorLoader implements
@NotNull final List<AnnotationDescriptor> result, @NotNull final List<AnnotationDescriptor> result,
@NotNull final ModuleDescriptor moduleDescriptor @NotNull final ModuleDescriptor moduleDescriptor
) { ) {
if (JvmAnnotationNames.isSpecialAnnotation(classId)) return null; if (JvmAnnotationNames.isSpecialAnnotation(classId, true)) return null;
final ClassDescriptor annotationClass = resolveClass(classId, moduleDescriptor); final ClassDescriptor annotationClass = resolveClass(classId, moduleDescriptor);
@@ -42,6 +42,7 @@ import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.plugin.JetBundle; import org.jetbrains.jet.plugin.JetBundle;
import org.jetbrains.jet.plugin.caches.resolve.ResolvePackage; import org.jetbrains.jet.plugin.caches.resolve.ResolvePackage;
import org.jetbrains.jet.plugin.codeInsight.ShortenReferences; import org.jetbrains.jet.plugin.codeInsight.ShortenReferences;
import org.jetbrains.jet.plugin.util.UtilPackage;
import org.jetbrains.jet.renderer.DescriptorRenderer; import org.jetbrains.jet.renderer.DescriptorRenderer;
import java.util.ArrayList; import java.util.ArrayList;
@@ -172,12 +173,12 @@ public class SpecifyTypeExplicitlyAction extends PsiElementBaseIntentionAction {
) { ) {
@Override @Override
protected String getLookupString(JetType element) { protected String getLookupString(JetType element) {
return DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(element); return DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(UtilPackage.approximateFlexibleTypes(element, true));
} }
@Override @Override
protected String getResult(JetType element) { protected String getResult(JetType element) {
return DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(element); return DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(UtilPackage.approximateFlexibleTypes(element, true));
} }
}; };
@@ -63,6 +63,7 @@ import org.jetbrains.jet.plugin.caches.resolve.ResolvePackage;
import org.jetbrains.jet.plugin.codeInsight.ShortenReferences; import org.jetbrains.jet.plugin.codeInsight.ShortenReferences;
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache;
import org.jetbrains.jet.plugin.project.ResolveSessionForBodies; import org.jetbrains.jet.plugin.project.ResolveSessionForBodies;
import org.jetbrains.jet.plugin.util.UtilPackage;
import org.jetbrains.jet.renderer.DescriptorRenderer; import org.jetbrains.jet.renderer.DescriptorRenderer;
import java.util.List; import java.util.List;
@@ -356,7 +357,7 @@ public class KotlinInlineValHandler extends InlineActionHandler {
return StringUtil.join(typeArguments, new Function<JetType, String>() { return StringUtil.join(typeArguments, new Function<JetType, String>() {
@Override @Override
public String fun(JetType type) { public String fun(JetType type) {
return DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(type); return DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(UtilPackage.approximateFlexibleTypes(type, true));
} }
}, ", "); }, ", ");
} }
@@ -19,6 +19,13 @@ package org.jetbrains.jet.plugin.util
import org.jetbrains.jet.lang.types.JetType import org.jetbrains.jet.lang.types.JetType
import org.jetbrains.jet.lang.types.TypeUtils import org.jetbrains.jet.lang.types.TypeUtils
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
import org.jetbrains.jet.lang.types.JetTypeImpl
import org.jetbrains.jet.lang.types.TypeProjectionImpl
import org.jetbrains.jet.lang.types.ErrorUtils
import org.jetbrains.jet.lang.resolve.java.kotlinSignature.CollectionClassMapping
import org.jetbrains.jet.lang.descriptors.ClassDescriptor
import org.jetbrains.jet.lang.types.FlexibleType
import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames
fun JetType.makeNullable() = TypeUtils.makeNullable(this) fun JetType.makeNullable() = TypeUtils.makeNullable(this)
fun JetType.makeNotNullable() = TypeUtils.makeNotNullable(this) fun JetType.makeNotNullable() = TypeUtils.makeNotNullable(this)
@@ -26,3 +33,31 @@ fun JetType.makeNotNullable() = TypeUtils.makeNotNullable(this)
fun JetType.supertypes(): Set<JetType> = TypeUtils.getAllSupertypes(this) fun JetType.supertypes(): Set<JetType> = TypeUtils.getAllSupertypes(this)
fun JetType.isUnit(): Boolean = KotlinBuiltIns.getInstance().isUnit(this) fun JetType.isUnit(): Boolean = KotlinBuiltIns.getInstance().isUnit(this)
public fun approximateFlexibleTypes(jetType: JetType, outermost: Boolean = true): JetType {
if (jetType is FlexibleType) {
val lowerClass = jetType.lowerBound.getConstructor().getDeclarationDescriptor() as? ClassDescriptor?
val isCollection = lowerClass != null && CollectionClassMapping.getInstance().isMutableCollection(lowerClass)
// (Mutable)Collection<T>! -> MutableCollection<T>?
// Foo<(Mutable)Collection<T>!>! -> Foo<Collection<T>>?
// Foo! -> Foo?
// Foo<Bar!>! -> Foo<Bar>?
val approximation =
if (isCollection)
TypeUtils.makeNullableAsSpecified(if (jetType.isMarkedReadOnly()) jetType.upperBound else jetType.lowerBound, outermost)
else
if (outermost) jetType.upperBound else jetType.lowerBound
val approximated = approximateFlexibleTypes(approximation)
return if (jetType.isMarkedNotNull()) approximated.makeNotNullable() else approximated
}
return JetTypeImpl(
jetType.getAnnotations(),
jetType.getConstructor(),
jetType.isNullable(),
jetType.getArguments().map { TypeProjectionImpl(it.getProjectionKind(), approximateFlexibleTypes(it.getType(), false)) },
ErrorUtils.createErrorScope("This type is not supposed to be used in member resolution", true)
)
}
private fun JetType.isMarkedReadOnly() = getAnnotations().findAnnotation(JvmAnnotationNames.JETBRAINS_READONLY_ANNOTATION) != null
private fun JetType.isMarkedNotNull() = getAnnotations().findAnnotation(JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION) != null