Loading SAM adapters for constructors.

This commit is contained in:
Evgeny Gerashchenko
2013-06-06 23:30:03 +04:00
parent 50eb14c525
commit 5e2c3fcb50
8 changed files with 116 additions and 23 deletions
@@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.resolve.java.resolver;
import com.google.common.collect.Lists;
import com.intellij.psi.*;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
@@ -31,6 +32,7 @@ import org.jetbrains.jet.lang.resolve.java.*;
import org.jetbrains.jet.lang.resolve.java.kotlinSignature.AlternativeMethodSignatureData;
import org.jetbrains.jet.lang.resolve.java.kt.JetConstructorAnnotation;
import org.jetbrains.jet.lang.resolve.java.provider.ClassPsiDeclarationProvider;
import org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils;
import org.jetbrains.jet.lang.resolve.java.wrapper.PsiMethodWrapper;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.JetType;
@@ -149,6 +151,7 @@ public final class JavaConstructorResolver {
ConstructorDescriptor constructor = resolveConstructor(psiClass, isStatic, psiConstructor, containingClass);
if (constructor != null) {
constructors.add(constructor);
ContainerUtil.addIfNotNull(constructors, resolveSamAdapter(constructor));
}
}
}
@@ -218,4 +221,16 @@ public final class JavaConstructorResolver {
trace.record(BindingContext.CONSTRUCTOR, psiConstructor, constructorDescriptor);
return constructorDescriptor;
}
@Nullable
private ConstructorDescriptor resolveSamAdapter(@NotNull ConstructorDescriptor original) {
if (SingleAbstractMethodUtils.isSamAdapterNecessary(original)) {
ConstructorDescriptor adapterFunction = SingleAbstractMethodUtils.createSamAdapterConstructor(original);
trace.record(BindingContext.SAM_ADAPTER_FUNCTION_TO_ORIGINAL, adapterFunction, original);
trace.record(BindingContext.SOURCE_DESCRIPTOR_FOR_SYNTHESIZED, adapterFunction, original);
return adapterFunction;
}
return null;
}
}
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.ConstructorDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl;
@@ -174,7 +175,7 @@ public class SingleAbstractMethodUtils {
return getFunctionTypeForSamType(type) != null;
}
public static boolean isSamAdapterNecessary(@NotNull SimpleFunctionDescriptor fun) {
public static boolean isSamAdapterNecessary(@NotNull FunctionDescriptor fun) {
for (ValueParameterDescriptor param : fun.getValueParameters()) {
if (isSamType(param.getType())) {
return true;
@@ -184,20 +185,77 @@ public class SingleAbstractMethodUtils {
}
@NotNull
public static SimpleFunctionDescriptor createSamAdapterFunction(@NotNull SimpleFunctionDescriptor original) {
SimpleFunctionDescriptorImpl result = new SimpleFunctionDescriptorImpl(
public static SimpleFunctionDescriptor createSamAdapterFunction(@NotNull final SimpleFunctionDescriptor original) {
final SimpleFunctionDescriptorImpl result = new SimpleFunctionDescriptorImpl(
original.getContainingDeclaration(),
original.getAnnotations(),
original.getName(),
CallableMemberDescriptor.Kind.SYNTHESIZED
);
FunctionInitializer initializer = new FunctionInitializer() {
@Override
public void initialize(
@NotNull List<TypeParameterDescriptor> typeParameters,
@NotNull List<ValueParameterDescriptor> valueParameters,
@Nullable JetType returnType
) {
result.initialize(
null,
original.getExpectedThisObject(),
typeParameters,
valueParameters,
returnType,
original.getModality(),
original.getVisibility(),
false
);
}
};
return initSamAdapter(original, result, initializer);
}
TypeParameters typeParameters = recreateAndInitializeTypeParameters(original.getTypeParameters(), result);
@NotNull
public static ConstructorDescriptor createSamAdapterConstructor(@NotNull final ConstructorDescriptor original) {
final ConstructorDescriptorImpl result = new ConstructorDescriptorImpl(
original.getContainingDeclaration(),
original.getAnnotations(),
original.isPrimary(),
CallableMemberDescriptor.Kind.SYNTHESIZED
);
FunctionInitializer initializer = new FunctionInitializer() {
@Override
public void initialize(
@NotNull List<TypeParameterDescriptor> typeParameters,
@NotNull List<ValueParameterDescriptor> valueParameters,
@Nullable JetType returnType
) {
result.initialize(
typeParameters,
valueParameters,
original.getVisibility(),
original.getExpectedThisObject() == ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER
);
}
};
return initSamAdapter(original, result, initializer);
}
private static <F extends FunctionDescriptor> F initSamAdapter(
@NotNull F original,
@NotNull F adapter,
@NotNull FunctionInitializer initializer
) {
TypeParameters typeParameters = recreateAndInitializeTypeParameters(original.getTypeParameters(), adapter);
JetType returnTypeUnsubstituted = original.getReturnType();
assert returnTypeUnsubstituted != null : original;
JetType returnType = typeParameters.substitutor.substitute(returnTypeUnsubstituted, Variance.OUT_VARIANCE);
assert returnType != null : "couldn't substitute type: " + returnType + ", substitutor = " + typeParameters.substitutor;
JetType returnType;
if (returnTypeUnsubstituted == null) { // return type may be null for not yet initialized constructors
returnType = null;
}
else {
returnType = typeParameters.substitutor.substitute(returnTypeUnsubstituted, Variance.OUT_VARIANCE);
assert returnType != null : "couldn't substitute type: " + returnType + ", substitutor = " + typeParameters.substitutor;
}
List<ValueParameterDescriptor> valueParameters = Lists.newArrayList();
for (ValueParameterDescriptor originalParam : original.getValueParameters()) {
@@ -208,22 +266,12 @@ public class SingleAbstractMethodUtils {
assert newType != null : "couldn't substitute type: " + newTypeUnsubstituted + ", substitutor = " + typeParameters.substitutor;
ValueParameterDescriptor newParam = new ValueParameterDescriptorImpl(
result, originalParam.getIndex(), originalParam.getAnnotations(), originalParam.getName(), newType, false, null);
adapter, originalParam.getIndex(), originalParam.getAnnotations(), originalParam.getName(), newType, false, null);
valueParameters.add(newParam);
}
result.initialize(
null,
original.getExpectedThisObject(),
typeParameters.descriptors,
valueParameters,
returnType,
original.getModality(),
original.getVisibility(),
false
);
return result;
initializer.initialize(typeParameters.descriptors, valueParameters, returnType);
return adapter;
}
@NotNull
@@ -273,4 +321,12 @@ public class SingleAbstractMethodUtils {
this.substitutor = substitutor;
}
}
private static abstract class FunctionInitializer {
public abstract void initialize(
@NotNull List<TypeParameterDescriptor> typeParameters,
@NotNull List<ValueParameterDescriptor> valueParameters,
@Nullable JetType returnType
);
}
}