Merge use-site targeted annotations into corresponding Annotations

Add PropertyDescriptor.backingField/delegateField to store annotations
on the field directly in an otherwise almost empty descriptor instance,
instead of storing them with use-sites in the corresponding property
descriptor. Instead of AnnotationWithTarget, create AnnotationDescriptor
instances in AnnotationSplitter. Change DescriptorRenderer to render
annotations on "related" declarations when needed, with the explicit
use-site target if applicable.

Most changes in diagnostic test data are related to the fact that
annotations which are known to have an incompatible use-site to the
declaration they're applied at (such as `@param:`-annotation on a
function), are now not loaded at all. It's fine because the code is
erroneous, so it doesn't really matter how do we load annotations with
invalid targets (some of this logic is also changed freely in subsequent
commits). Some changes are also explained by the fact that for example
an annotation on the property which is only applicable to FIELD is now
rendered with an explicit use-site target `@field:`, regardless of
whether it did have that use-site target syntactically or not.

Basically, after this change there's no point in calling
Annotations.getUseSiteTargetedAnnotations/getAllAnnotations anymore
because it's easier and more intuitive to just use Annotations of the
corresponding descriptor -- the backing / delegate field (introduced in
this commit) or the extension receiver / setter parameter (related
behavior was fixed in previous commits). Usages of
use-site-target-related methods will be refactored out in subsequent
commits
This commit is contained in:
Alexander Udalov
2018-08-14 16:45:11 +02:00
parent 8c21e86ded
commit fc87043cb3
68 changed files with 436 additions and 386 deletions
@@ -7,19 +7,12 @@ package org.jetbrains.kotlin.load.java;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.builtins.CompanionObjectMapping;
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget;
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.name.ClassId;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.util.capitalizeDecapitalize.CapitalizeDecapitalizeKt;
import java.util.List;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isClassOrEnumClass;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject;
@@ -120,12 +113,10 @@ public final class JvmAbi {
}
public static boolean hasJvmFieldAnnotation(@NotNull CallableMemberDescriptor memberDescriptor) {
List<AnnotationWithTarget> annotations = memberDescriptor.getAnnotations().getUseSiteTargetedAnnotations();
for (AnnotationWithTarget annotationWithTarget : annotations) {
if (AnnotationUseSiteTarget.FIELD.equals(annotationWithTarget.getTarget()) &&
JVM_FIELD_ANNOTATION_FQ_NAME.equals(annotationWithTarget.getAnnotation().getFqName())) {
return true;
}
// TODO: deduplicate this with org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmFieldAnnotation
if (memberDescriptor instanceof PropertyDescriptor) {
FieldDescriptor field = ((PropertyDescriptor) memberDescriptor).getBackingField();
if (field != null && field.getAnnotations().hasAnnotation(JVM_FIELD_ANNOTATION_FQ_NAME)) return true;
}
return memberDescriptor.getAnnotations().hasAnnotation(JVM_FIELD_ANNOTATION_FQ_NAME);
}
@@ -131,7 +131,7 @@ public class JavaPropertyDescriptor extends PropertyDescriptorImpl implements Ja
newSetter.initialize(setter.getValueParameters().get(0));
}
enhanced.initialize(newGetter, newSetter);
enhanced.initialize(newGetter, newSetter, getBackingField(), getDelegateField());
enhanced.setSetterProjectedOut(isSetterProjectedOut());
if (compileTimeInitializer != null) {
enhanced.setCompileTimeInitializer(compileTimeInitializer);
@@ -271,7 +271,8 @@ abstract class LazyJavaScope(protected val c: LazyJavaResolverContext) : MemberS
private fun resolveProperty(field: JavaField): PropertyDescriptor {
val propertyDescriptor = createPropertyDescriptor(field)
propertyDescriptor.initialize(null, null)
// Annotations on Java fields are loaded as property annotations, therefore backingField = null below
propertyDescriptor.initialize(null, null, null, null)
val propertyType = getPropertyType(field)
@@ -0,0 +1,12 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.descriptors
import org.jetbrains.kotlin.descriptors.annotations.Annotated
interface FieldDescriptor : Annotated {
val correspondingProperty: PropertyDescriptor
}
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.types.TypeSubstitution;
import org.jetbrains.kotlin.types.TypeSubstitutor;
import java.util.Collection;
@@ -54,6 +53,12 @@ public interface PropertyDescriptor extends VariableDescriptorWithAccessors, Cal
@Override
Collection<? extends PropertyDescriptor> getOverriddenDescriptors();
@Nullable
FieldDescriptor getBackingField();
@Nullable
FieldDescriptor getDelegateField();
@Override
PropertyDescriptor substitute(@NotNull TypeSubstitutor substitutor);
@@ -0,0 +1,16 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.descriptors.impl
import org.jetbrains.kotlin.descriptors.FieldDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotatedImpl
import org.jetbrains.kotlin.descriptors.annotations.Annotations
class FieldDescriptorImpl(
annotations: Annotations,
override val correspondingProperty: PropertyDescriptor
) : FieldDescriptor, AnnotatedImpl(annotations)
@@ -53,6 +53,8 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
private PropertyGetterDescriptorImpl getter;
private PropertySetterDescriptor setter;
private boolean setterProjectedOut;
private FieldDescriptor backingField;
private FieldDescriptor delegateField;
protected PropertyDescriptorImpl(
@NotNull DeclarationDescriptor containingDeclaration,
@@ -120,9 +122,23 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
this.dispatchReceiverParameter = dispatchReceiverParameter;
}
public void initialize(@Nullable PropertyGetterDescriptorImpl getter, @Nullable PropertySetterDescriptor setter) {
public void initialize(
@Nullable PropertyGetterDescriptorImpl getter,
@Nullable PropertySetterDescriptor setter
) {
initialize(getter, setter, null, null);
}
public void initialize(
@Nullable PropertyGetterDescriptorImpl getter,
@Nullable PropertySetterDescriptor setter,
@Nullable FieldDescriptor backingField,
@Nullable FieldDescriptor delegateField
) {
this.getter = getter;
this.setter = setter;
this.backingField = backingField;
this.delegateField = delegateField;
}
public void setSetterProjectedOut(boolean setterProjectedOut) {
@@ -413,7 +429,12 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
newSetter.initialize(substitutedValueParameters.get(0));
}
substitutedDescriptor.initialize(newGetter, newSetter);
substitutedDescriptor.initialize(
newGetter,
newSetter,
backingField == null ? null : new FieldDescriptorImpl(backingField.getAnnotations(), substitutedDescriptor),
delegateField == null ? null : new FieldDescriptorImpl(delegateField.getAnnotations(), substitutedDescriptor)
);
if (copyConfiguration.copyOverrides) {
Collection<CallableMemberDescriptor> overridden = SmartSet.create();
@@ -488,6 +509,18 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
return isActual;
}
@Override
@Nullable
public FieldDescriptor getBackingField() {
return backingField;
}
@Override
@Nullable
public FieldDescriptor getDelegateField() {
return delegateField;
}
@Override
public void setOverriddenDescriptors(@NotNull Collection<? extends CallableMemberDescriptor> overriddenDescriptors) {
//noinspection unchecked
@@ -399,13 +399,13 @@ internal class DescriptorRendererImpl(
}
}
private fun StringBuilder.renderAnnotations(annotated: Annotated) {
private fun StringBuilder.renderAnnotations(annotated: Annotated, target: AnnotationUseSiteTarget? = null) {
if (DescriptorRendererModifier.ANNOTATIONS !in modifiers) return
val excluded = if (annotated is KotlinType) excludedTypeAnnotationClasses else excludedAnnotationClasses
val annotationFilter = annotationFilter
for ((annotation, target) in annotated.annotations.getAllAnnotations()) {
for (annotation in annotated.annotations) {
if (annotation.fqName !in excluded && (annotationFilter == null || annotationFilter(annotation))) {
append(renderAnnotation(annotation, target))
if (eachAnnotationOnNewLine) {
@@ -685,6 +685,8 @@ internal class DescriptorRendererImpl(
private fun renderReceiver(callableDescriptor: CallableDescriptor, builder: StringBuilder) {
val receiver = callableDescriptor.extensionReceiverParameter
if (receiver != null) {
builder.renderAnnotations(receiver, AnnotationUseSiteTarget.RECEIVER)
val type = receiver.type
var result = renderType(type)
if (shouldRenderAsPrettyFunctionType(type) && !TypeUtils.isNullableType(type)) {
@@ -817,7 +819,7 @@ internal class DescriptorRendererImpl(
private fun renderProperty(property: PropertyDescriptor, builder: StringBuilder) {
if (!startFromName) {
if (!startFromDeclarationKeyword) {
builder.renderAnnotations(property)
renderPropertyAnnotations(property, builder)
renderVisibility(property.visibility, builder)
renderModifier(builder, property.isConst, "const")
renderMemberModifiers(property, builder)
@@ -841,6 +843,21 @@ internal class DescriptorRendererImpl(
renderWhereSuffix(property.typeParameters, builder)
}
private fun renderPropertyAnnotations(property: PropertyDescriptor, builder: StringBuilder) {
if (DescriptorRendererModifier.ANNOTATIONS !in modifiers) return
builder.renderAnnotations(property)
property.backingField?.let { builder.renderAnnotations(it, AnnotationUseSiteTarget.FIELD) }
property.delegateField?.let { builder.renderAnnotations(it, AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD) }
if (propertyAccessorRenderingPolicy == PropertyAccessorRenderingPolicy.NONE) {
property.setter?.valueParameters?.single()?.let {
builder.renderAnnotations(it, AnnotationUseSiteTarget.SETTER_PARAMETER)
}
}
}
private fun renderInitializer(variable: VariableDescriptor, builder: StringBuilder) {
if (includePropertyConstant) {
variable.compileTimeInitializer?.let { constant ->
@@ -7,8 +7,10 @@ package org.jetbrains.kotlin.serialization.deserialization
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl
import org.jetbrains.kotlin.descriptors.impl.FieldDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
@@ -29,9 +31,11 @@ class MemberDeserializer(private val c: DeserializationContext) {
fun loadProperty(proto: ProtoBuf.Property): PropertyDescriptor {
val flags = if (proto.hasFlags()) proto.flags else loadOldFlags(proto.oldFlags)
val propertyAnnotations = getAnnotations(proto, flags, AnnotatedCallableKind.PROPERTY)
val property = DeserializedPropertyDescriptor(
c.containingDeclaration, null,
getAnnotations(proto, flags, AnnotatedCallableKind.PROPERTY),
propertyAnnotations,
ProtoEnumFlags.modality(Flags.MODALITY.get(flags)),
ProtoEnumFlags.visibility(Flags.VISIBILITY.get(flags)),
Flags.IS_VAR.get(flags),
@@ -134,7 +138,19 @@ class MemberDeserializer(private val c: DeserializationContext) {
)
}
property.initialize(getter, setter, property.checkExperimentalCoroutine(local.typeDeserializer))
// TODO: add needed methods to AnnotationAndConstantLoader
val fieldAnnotations = DeserializedAnnotations(c.storageManager) {
propertyAnnotations.getUseSiteTargetedAnnotations()
.filter { it.target == AnnotationUseSiteTarget.FIELD }.map { it.annotation }
}
val delegateAnnotations = DeserializedAnnotations(c.storageManager) {
propertyAnnotations.getUseSiteTargetedAnnotations()
.filter { it.target == AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD }.map { it.annotation }
}
property.initialize(
getter, setter, FieldDescriptorImpl(fieldAnnotations, property), FieldDescriptorImpl(delegateAnnotations, property),
property.checkExperimentalCoroutine(local.typeDeserializer)
)
return property
}
@@ -146,9 +146,11 @@ class DeserializedPropertyDescriptor(
fun initialize(
getter: PropertyGetterDescriptorImpl?,
setter: PropertySetterDescriptor?,
backingField: FieldDescriptor?,
delegateField: FieldDescriptor?,
isExperimentalCoroutineInReleaseEnvironment: DeserializedMemberDescriptor.CoroutinesCompatibilityMode
) {
super.initialize(getter, setter)
super.initialize(getter, setter, backingField, delegateField)
.also { this.coroutinesExperimentalCompatibilityMode = isExperimentalCoroutineInReleaseEnvironment }
}