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:
+10
-4
@@ -98,17 +98,23 @@ public final class JvmAnnotationNames {
|
||||
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> NULLABILITY_ANNOTATIONS = new HashSet<JvmClassName>();
|
||||
static {
|
||||
for (FqName fqName : Arrays.asList(KOTLIN_CLASS, KOTLIN_PACKAGE, KOTLIN_SIGNATURE, JETBRAINS_NOT_NULL_ANNOTATION,
|
||||
JETBRAINS_NULLABLE_ANNOTATION)) {
|
||||
for (FqName fqName : Arrays.asList(KOTLIN_CLASS, KOTLIN_PACKAGE, KOTLIN_SIGNATURE)) {
|
||||
SPECIAL_ANNOTATIONS.add(JvmClassName.byFqNameWithoutInnerClasses(fqName));
|
||||
}
|
||||
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);
|
||||
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() {
|
||||
|
||||
+7
-3
@@ -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.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 {
|
||||
(annotation: JavaAnnotation) ->
|
||||
c.resolveAnnotation(annotation)
|
||||
}
|
||||
|
||||
override fun findAnnotation(fqName: FqName): AnnotationDescriptor? {
|
||||
val jAnnotation = annotationOwner.findAnnotation(fqName)
|
||||
val jAnnotation = annotationOwner.findAnnotation(fqName) ?: extraLookup(fqName)
|
||||
if (jAnnotation == null) return null
|
||||
|
||||
return annotationDescriptors(jAnnotation)
|
||||
@@ -45,7 +49,7 @@ class LazyJavaAnnotations(c: LazyJavaResolverContextWithTypes, val annotationOwn
|
||||
}
|
||||
|
||||
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
|
||||
= owner.findAnnotation(annotationFqName) != null || externalAnnotationResolver.findExternalAnnotation(owner, annotationFqName) != null
|
||||
|
||||
+2
-1
@@ -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.resolveTopLevelClass
|
||||
import org.jetbrains.jet.lang.resolve.kotlin.DeserializedResolverUtils.kotlinFqNameToJavaFqName
|
||||
import org.jetbrains.jet.lang.resolve.java.PLATFORM_TYPES
|
||||
|
||||
private object DEPRECATED_IN_JAVA : JavaLiteralAnnotationArgument {
|
||||
override val name: Name? = null
|
||||
@@ -45,7 +46,7 @@ private object DEPRECATED_IN_JAVA : JavaLiteralAnnotationArgument {
|
||||
|
||||
fun LazyJavaResolverContextWithTypes.resolveAnnotation(annotation: JavaAnnotation): LazyJavaAnnotationDescriptor? {
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
+10
-19
@@ -34,8 +34,6 @@ import org.jetbrains.jet.lang.types.TypeUtils
|
||||
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.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 java.util.ArrayList
|
||||
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.utils.*
|
||||
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(
|
||||
protected val c: LazyJavaResolverContextWithTypes,
|
||||
@@ -116,8 +114,9 @@ public abstract class LazyJavaMemberScope(
|
||||
|
||||
fun resolveMethodToFunctionDescriptor(method: JavaMethod, record: Boolean = true): JavaMethodDescriptor {
|
||||
|
||||
val annotations = c.resolveAnnotations(method)
|
||||
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())
|
||||
@@ -126,13 +125,7 @@ public abstract class LazyJavaMemberScope(
|
||||
val valueParameters = resolveValueParameters(c, functionDescriptorImpl, method.getValueParameters())
|
||||
|
||||
val annotationMethod = method.getContainingClass().isAnnotationType()
|
||||
val returnTypeAttrs = LazyJavaTypeAttributes(c, method, TypeUsage.MEMBER_SIGNATURE_COVARIANT, allowFlexible = !annotationMethod) {
|
||||
if (c.hasReadOnlyAnnotation(method) && !c.hasMutableAnnotation(method))
|
||||
TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT
|
||||
else
|
||||
TypeUsage.MEMBER_SIGNATURE_COVARIANT
|
||||
}
|
||||
|
||||
val returnTypeAttrs = LazyJavaTypeAttributes(c, method, TypeUsage.MEMBER_SIGNATURE_COVARIANT, annotations, allowFlexible = !annotationMethod)
|
||||
val returnJavaType = method.getReturnType() ?: throw IllegalStateException("Constructor passed as method: $method")
|
||||
// Annotation arguments are never null in Java
|
||||
val returnType = c.typeResolver.transformJavaType(returnJavaType, returnTypeAttrs).let {
|
||||
@@ -174,10 +167,8 @@ public abstract class LazyJavaMemberScope(
|
||||
pair ->
|
||||
val (index, javaParameter) = pair
|
||||
|
||||
val typeUsage = LazyJavaTypeAttributes(c, javaParameter, TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT) {
|
||||
if (c.hasMutableAnnotation(javaParameter)) TypeUsage.MEMBER_SIGNATURE_COVARIANT else TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT
|
||||
}
|
||||
|
||||
val annotations = c.resolveAnnotations(javaParameter)
|
||||
val typeUsage = LazyJavaTypeAttributes(c, javaParameter, TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT, annotations)
|
||||
val (outType, varargElementType) =
|
||||
if (javaParameter.isVararg()) {
|
||||
val paramType = javaParameter.getType()
|
||||
@@ -213,7 +204,7 @@ public abstract class LazyJavaMemberScope(
|
||||
function,
|
||||
null,
|
||||
index,
|
||||
c.resolveAnnotations(javaParameter),
|
||||
annotations,
|
||||
name,
|
||||
outType,
|
||||
false,
|
||||
@@ -254,7 +245,7 @@ public abstract class LazyJavaMemberScope(
|
||||
val propertyDescriptor = createPropertyDescriptor(field)
|
||||
propertyDescriptor.initialize(null, null)
|
||||
|
||||
val propertyType = getPropertyType(field)
|
||||
val propertyType = getPropertyType(field, propertyDescriptor.getAnnotations())
|
||||
val effectiveSignature = c.externalSignatureResolver.resolveAlternativeFieldSignature(field, propertyType, isVar)
|
||||
val signatureErrors = effectiveSignature.getErrors()
|
||||
if (!signatureErrors.isEmpty()) {
|
||||
@@ -285,7 +276,7 @@ public abstract class LazyJavaMemberScope(
|
||||
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
|
||||
val finalStatic = field.isFinal() && field.isStatic()
|
||||
|
||||
@@ -293,7 +284,7 @@ public abstract class LazyJavaMemberScope(
|
||||
val allowFlexible = PLATFORM_TYPES && !(finalStatic && c.javaPropertyInitializerEvaluator.isNotNullCompileTimeConstant(field))
|
||||
val propertyType = c.typeResolver.transformJavaType(
|
||||
field.getType(),
|
||||
LazyJavaTypeAttributes(c, field, TypeUsage.MEMBER_SIGNATURE_INVARIANT, allowFlexible)
|
||||
LazyJavaTypeAttributes(c, field, TypeUsage.MEMBER_SIGNATURE_INVARIANT, annotations, allowFlexible)
|
||||
)
|
||||
if ((!allowFlexible || !PLATFORM_TYPES) && finalStatic) {
|
||||
return TypeUtils.makeNotNullable(propertyType)
|
||||
|
||||
+21
-5
@@ -33,6 +33,10 @@ import java.util.HashSet
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker
|
||||
import org.jetbrains.jet.lang.resolve.java.PLATFORM_TYPES
|
||||
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(
|
||||
private val c: LazyJavaResolverContext,
|
||||
@@ -262,6 +266,8 @@ class LazyJavaTypeResolver(
|
||||
}
|
||||
}
|
||||
override fun isNullable(): Boolean = _nullable()
|
||||
|
||||
override fun getAnnotations() = attr.annotations
|
||||
}
|
||||
|
||||
public open class FlexibleJavaClassifierType protected (
|
||||
@@ -312,6 +318,7 @@ trait JavaTypeAttributes {
|
||||
get() = INFLEXIBLE
|
||||
val allowFlexible: Boolean
|
||||
get() = true
|
||||
val annotations: Annotations
|
||||
}
|
||||
|
||||
fun JavaTypeAttributes.isFlexible() = flexibility != INFLEXIBLE
|
||||
@@ -326,23 +333,32 @@ class LazyJavaTypeAttributes(
|
||||
c: LazyJavaResolverContext,
|
||||
val annotationOwner: JavaAnnotationOwner,
|
||||
override val howThisTypeIsUsed: TypeUsage,
|
||||
override val allowFlexible: Boolean = true,
|
||||
computeHowThisTypeIsUsedAccordingToAnnotations: () -> TypeUsage = {howThisTypeIsUsed}
|
||||
override val annotations: Annotations,
|
||||
override val allowFlexible: Boolean = true
|
||||
): JavaTypeAttributes {
|
||||
|
||||
override val howThisTypeIsUsedAccordingToAnnotations: TypeUsage by c.storageManager.createLazyValue(
|
||||
computeHowThisTypeIsUsedAccordingToAnnotations
|
||||
)
|
||||
override val howThisTypeIsUsedAccordingToAnnotations: TypeUsage by c.storageManager.createLazyValue {
|
||||
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) }
|
||||
}
|
||||
|
||||
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 {
|
||||
override val howThisTypeIsUsed: TypeUsage = this@toAttributes
|
||||
override val howThisTypeIsUsedAccordingToAnnotations: TypeUsage
|
||||
get() = howThisTypeIsUsed
|
||||
override val isMarkedNotNull: Boolean = false
|
||||
override val allowFlexible: Boolean = allowFlexible
|
||||
|
||||
override val annotations: Annotations = Annotations.EMPTY
|
||||
}
|
||||
|
||||
fun JavaTypeAttributes.toFlexible(flexibility: Flexibility) =
|
||||
|
||||
+1
-1
@@ -119,7 +119,7 @@ public class AnnotationDescriptorLoader extends BaseDescriptorLoader implements
|
||||
@NotNull final List<AnnotationDescriptor> result,
|
||||
@NotNull final ModuleDescriptor moduleDescriptor
|
||||
) {
|
||||
if (JvmAnnotationNames.isSpecialAnnotation(classId)) return null;
|
||||
if (JvmAnnotationNames.isSpecialAnnotation(classId, true)) return null;
|
||||
|
||||
final ClassDescriptor annotationClass = resolveClass(classId, moduleDescriptor);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user