Refactoring: introduce CopyBuilder for CallableMemberDescriptor and PropertyDescriptor.

Allow providing new dispatchReceiverParameter via CopyBuilder
(required for proper dispatch receiver for delegates).
This commit is contained in:
Dmitry Petrov
2017-03-01 15:32:57 +03:00
parent 9baaf607a3
commit c92f118e5e
4 changed files with 156 additions and 26 deletions
@@ -17,6 +17,8 @@
package org.jetbrains.kotlin.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.types.TypeSubstitution;
import java.util.Collection;
@@ -51,4 +53,33 @@ public interface CallableMemberDescriptor extends CallableDescriptor, MemberDesc
@NotNull
CallableMemberDescriptor copy(DeclarationDescriptor newOwner, Modality modality, Visibility visibility, Kind kind, boolean copyOverrides);
@NotNull
CopyBuilder<? extends CallableMemberDescriptor> newCopyBuilder();
interface CopyBuilder<D extends CallableMemberDescriptor> {
@NotNull
CopyBuilder<D> setOwner(@NotNull DeclarationDescriptor owner);
@NotNull
CopyBuilder<D> setModality(@NotNull Modality modality);
@NotNull
CopyBuilder<D> setVisibility(@NotNull Visibility visibility);
@NotNull
CopyBuilder<D> setKind(@NotNull Kind kind);
@NotNull
CopyBuilder<D> setDispatchReceiverParameter(@Nullable ReceiverParameterDescriptor dispatchReceiverParameter);
@NotNull
CopyBuilder<D> setSubstitution(@NotNull TypeSubstitution substitution);
@NotNull
CopyBuilder<D> setCopyOverrides(boolean copyOverrides);
@Nullable
D build();
}
}
@@ -86,22 +86,28 @@ public interface FunctionDescriptor extends CallableMemberDescriptor {
<V> V getUserData(UserDataKey<V> key);
@NotNull
@Override
CopyBuilder<? extends FunctionDescriptor> newCopyBuilder();
interface CopyBuilder<D extends FunctionDescriptor> {
interface CopyBuilder<D extends FunctionDescriptor> extends CallableMemberDescriptor.CopyBuilder<D> {
@NotNull
@Override
CopyBuilder<D> setOwner(@NotNull DeclarationDescriptor owner);
@NotNull
@Override
CopyBuilder<D> setModality(@NotNull Modality modality);
@NotNull
@Override
CopyBuilder<D> setVisibility(@NotNull Visibility visibility);
@NotNull
@Override
CopyBuilder<D> setKind(@NotNull Kind kind);
@NotNull
@Override
CopyBuilder<D> setCopyOverrides(boolean copyOverrides);
@NotNull
@@ -120,6 +126,7 @@ public interface FunctionDescriptor extends CallableMemberDescriptor {
CopyBuilder<D> setExtensionReceiverType(@Nullable KotlinType type);
@NotNull
@Override
CopyBuilder<D> setDispatchReceiverParameter(@Nullable ReceiverParameterDescriptor dispatchReceiverParameter);
@NotNull
@@ -147,12 +154,14 @@ public interface FunctionDescriptor extends CallableMemberDescriptor {
CopyBuilder<D> setAdditionalAnnotations(@NotNull Annotations additionalAnnotations);
@NotNull
@Override
CopyBuilder<D> setSubstitution(@NotNull TypeSubstitution substitution);
@NotNull
<V> CopyBuilder<D> putUserData(@NotNull UserDataKey<V> userDataKey, V value);
@Nullable
@Override
D build();
}
}
@@ -18,6 +18,7 @@ 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;
@@ -57,4 +58,8 @@ public interface PropertyDescriptor extends VariableDescriptorWithAccessors, Cal
PropertyDescriptor substitute(@NotNull TypeSubstitutor substitutor);
boolean isLateInit();
@NotNull
@Override
CopyBuilder<? extends PropertyDescriptor> newCopyBuilder();
}
@@ -23,10 +23,7 @@ import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.resolve.DescriptorFactory;
import org.jetbrains.kotlin.types.DescriptorSubstitutor;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.TypeSubstitutor;
import org.jetbrains.kotlin.types.Variance;
import org.jetbrains.kotlin.types.*;
import org.jetbrains.kotlin.utils.SmartSet;
import java.util.ArrayList;
@@ -236,25 +233,106 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
if (originalSubstitutor.isEmpty()) {
return this;
}
return doSubstitute(originalSubstitutor, getContainingDeclaration(), modality, visibility, getOriginal(), true, getKind());
return newCopyBuilder()
.setSubstitution(originalSubstitutor.getSubstitution())
.setOwner(getContainingDeclaration())
.setModality(modality)
.setVisibility(visibility)
.setOriginal(getOriginal())
.setCopyOverrides(true)
.setKind(getKind())
.build();
}
public class CopyConfiguration implements PropertyDescriptor.CopyBuilder<PropertyDescriptor> {
private DeclarationDescriptor owner;
private Modality modality;
private Visibility visibility;
private PropertyDescriptor original = null;
private Kind kind;
private TypeSubstitution substitution = TypeSubstitution.EMPTY;
private boolean copyOverrides = true;
private ReceiverParameterDescriptor dispatchReceiverParameter = PropertyDescriptorImpl.this.dispatchReceiverParameter;
@NotNull
@Override
public CopyConfiguration setOwner(@NotNull DeclarationDescriptor owner) {
this.owner = owner;
return this;
}
@NotNull
public CopyConfiguration setOriginal(@Nullable PropertyDescriptor original) {
this.original = original;
return this;
}
@NotNull
@Override
public CopyConfiguration setModality(@NotNull Modality modality) {
this.modality = modality;
return this;
}
@NotNull
@Override
public CopyConfiguration setVisibility(@NotNull Visibility visibility) {
this.visibility = visibility;
return this;
}
@NotNull
@Override
public CopyConfiguration setKind(@NotNull Kind kind) {
this.kind = kind;
return this;
}
@NotNull
@Override
public CopyConfiguration setDispatchReceiverParameter(@Nullable ReceiverParameterDescriptor dispatchReceiverParameter) {
this.dispatchReceiverParameter = dispatchReceiverParameter;
return this;
}
@NotNull
@Override
public CopyConfiguration setSubstitution(@NotNull TypeSubstitution substitution) {
this.substitution = substitution;
return this;
}
@NotNull
@Override
public CopyConfiguration setCopyOverrides(boolean copyOverrides) {
this.copyOverrides = copyOverrides;
return this;
}
@Nullable
@Override
public PropertyDescriptor build() {
return doSubstitute(this);
}
}
@NotNull
@Override
public CopyConfiguration newCopyBuilder() {
return new CopyConfiguration();
}
@Nullable
protected PropertyDescriptor doSubstitute(
@NotNull TypeSubstitutor originalSubstitutor,
@NotNull DeclarationDescriptor newOwner,
@NotNull Modality newModality,
@NotNull Visibility newVisibility,
@Nullable PropertyDescriptor original,
boolean copyOverrides,
@NotNull Kind kind
) {
PropertyDescriptorImpl substitutedDescriptor = createSubstitutedCopy(newOwner, newModality, newVisibility, original, kind);
protected PropertyDescriptor doSubstitute(@NotNull CopyConfiguration copyConfiguration) {
PropertyDescriptorImpl substitutedDescriptor = createSubstitutedCopy(
copyConfiguration.owner, copyConfiguration.modality, copyConfiguration.visibility,
copyConfiguration.original, copyConfiguration.kind);
List<TypeParameterDescriptor> originalTypeParameters = getTypeParameters();
List<TypeParameterDescriptor> substitutedTypeParameters = new ArrayList<TypeParameterDescriptor>(originalTypeParameters.size());
TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters(
originalTypeParameters, originalSubstitutor.getSubstitution(), substitutedDescriptor, substitutedTypeParameters
originalTypeParameters, copyConfiguration.substitution, substitutedDescriptor, substitutedTypeParameters
);
KotlinType originalOutType = getType();
@@ -263,9 +341,8 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
return null; // TODO : tell the user that the property was projected out
}
ReceiverParameterDescriptor substitutedDispatchReceiver;
ReceiverParameterDescriptor dispatchReceiver = getDispatchReceiverParameter();
ReceiverParameterDescriptor dispatchReceiver = copyConfiguration.dispatchReceiverParameter;
if (dispatchReceiver != null) {
substitutedDispatchReceiver = dispatchReceiver.substitute(substitutor);
if (substitutedDispatchReceiver == null) return null;
@@ -286,8 +363,8 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
substitutedDescriptor.setType(outType, substitutedTypeParameters, substitutedDispatchReceiver, substitutedReceiverType);
PropertyGetterDescriptorImpl newGetter = getter == null ? null : new PropertyGetterDescriptorImpl(
substitutedDescriptor, getter.getAnnotations(), newModality, normalizeVisibility(getter.getVisibility(), kind),
getter.isDefault(), getter.isExternal(), getter.isInline(), kind, original == null ? null : original.getGetter(),
substitutedDescriptor, getter.getAnnotations(), copyConfiguration.modality, normalizeVisibility(getter.getVisibility(), copyConfiguration.kind),
getter.isDefault(), getter.isExternal(), getter.isInline(), copyConfiguration.kind, copyConfiguration.original == null ? null : copyConfiguration.original.getGetter(),
SourceElement.NO_SOURCE
);
if (newGetter != null) {
@@ -296,8 +373,8 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
newGetter.initialize(returnType != null ? substitutor.substitute(returnType, Variance.OUT_VARIANCE) : null);
}
PropertySetterDescriptorImpl newSetter = setter == null ? null : new PropertySetterDescriptorImpl(
substitutedDescriptor, setter.getAnnotations(), newModality, normalizeVisibility(setter.getVisibility(), kind),
setter.isDefault(), setter.isExternal(), setter.isInline(), kind, original == null ? null : original.getSetter(),
substitutedDescriptor, setter.getAnnotations(), copyConfiguration.modality, normalizeVisibility(setter.getVisibility(), copyConfiguration.kind),
setter.isDefault(), setter.isExternal(), setter.isInline(), copyConfiguration.kind, copyConfiguration.original == null ? null : copyConfiguration.original.getSetter(),
SourceElement.NO_SOURCE
);
if (newSetter != null) {
@@ -313,7 +390,7 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
// it can not be assigned to because of the projection
substitutedDescriptor.setSetterProjectedOut(true);
substitutedValueParameters = Collections.<ValueParameterDescriptor>singletonList(
PropertySetterDescriptorImpl.createSetterParameter(newSetter, getBuiltIns(newOwner).getNothingType())
PropertySetterDescriptorImpl.createSetterParameter(newSetter, getBuiltIns(copyConfiguration.owner).getNothingType())
);
}
if (substitutedValueParameters.size() != 1) {
@@ -325,7 +402,7 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
substitutedDescriptor.initialize(newGetter, newSetter);
if (copyOverrides) {
if (copyConfiguration.copyOverrides) {
Collection<CallableMemberDescriptor> overridden = SmartSet.create();
for (PropertyDescriptor propertyDescriptor : getOverriddenDescriptors()) {
overridden.add(propertyDescriptor.substitute(substitutor));
@@ -412,6 +489,14 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
@NotNull
@Override
public PropertyDescriptor copy(DeclarationDescriptor newOwner, Modality modality, Visibility visibility, Kind kind, boolean copyOverrides) {
return doSubstitute(TypeSubstitutor.EMPTY, newOwner, modality, visibility, null, copyOverrides, kind);
//noinspection ConstantConditions
return newCopyBuilder()
.setOwner(newOwner)
.setOriginal(null)
.setModality(modality)
.setVisibility(visibility)
.setKind(kind)
.setCopyOverrides(copyOverrides)
.build();
}
}