Loading SAM adapters for constructors.
This commit is contained in:
@@ -1897,7 +1897,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
}
|
||||
SimpleFunctionDescriptor original = ((SimpleFunctionDescriptor) fun).getOriginal();
|
||||
if (original.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED) {
|
||||
return bindingContext.get(SAM_ADAPTER_FUNCTION_TO_ORIGINAL, original);
|
||||
return (SimpleFunctionDescriptor) bindingContext.get(SAM_ADAPTER_FUNCTION_TO_ORIGINAL, original); // TODO support constructor
|
||||
}
|
||||
if (original.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
|
||||
for (FunctionDescriptor overridden : original.getOverriddenDescriptors()) {
|
||||
|
||||
+15
@@ -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;
|
||||
}
|
||||
}
|
||||
+76
-20
@@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-1
@@ -22,6 +22,7 @@ import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -36,7 +37,11 @@ public class ConstructorDescriptorImpl extends FunctionDescriptorImpl implements
|
||||
private static final Name NAME = Name.special("<init>");
|
||||
|
||||
public ConstructorDescriptorImpl(@NotNull ClassDescriptor containingDeclaration, @NotNull List<AnnotationDescriptor> annotations, boolean isPrimary) {
|
||||
super(containingDeclaration, annotations, NAME, Kind.DECLARATION);
|
||||
this(containingDeclaration, annotations, isPrimary, Kind.DECLARATION);
|
||||
}
|
||||
|
||||
public ConstructorDescriptorImpl(@NotNull ClassDescriptor containingDeclaration, @NotNull List<AnnotationDescriptor> annotations, boolean isPrimary, Kind kind) {
|
||||
super(containingDeclaration, annotations, NAME, kind);
|
||||
this.isPrimary = isPrimary;
|
||||
}
|
||||
|
||||
|
||||
@@ -265,7 +265,7 @@ public interface BindingContext {
|
||||
|
||||
WritableSlice<CallableDescriptor, Boolean> IS_DECLARED_IN_JAVA = Slices.createSimpleSlice();
|
||||
WritableSlice<SimpleFunctionDescriptor, ClassDescriptor> SAM_CONSTRUCTOR_TO_INTERFACE = Slices.createSimpleSlice();
|
||||
WritableSlice<SimpleFunctionDescriptor, SimpleFunctionDescriptor> SAM_ADAPTER_FUNCTION_TO_ORIGINAL = Slices.createSimpleSlice();
|
||||
WritableSlice<FunctionDescriptor, FunctionDescriptor> SAM_ADAPTER_FUNCTION_TO_ORIGINAL = Slices.createSimpleSlice();
|
||||
WritableSlice<CallableMemberDescriptor, DeclarationDescriptor> SOURCE_DESCRIPTOR_FOR_SYNTHESIZED = Slices.createSimpleSlice();
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package test;
|
||||
|
||||
public class Constructor {
|
||||
public Constructor(Runnable r) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package test
|
||||
|
||||
public open class Constructor : java.lang.Object {
|
||||
public /*synthesized*/ constructor Constructor(/*0*/ p0: (() -> jet.Unit)?)
|
||||
public constructor Constructor(/*0*/ p0: java.lang.Runnable?)
|
||||
}
|
||||
@@ -1239,6 +1239,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
|
||||
doTestCompiledJava("compiler/testData/loadJava/compiledJava/singleAbstractMethod/adapter/Basic.java");
|
||||
}
|
||||
|
||||
@TestMetadata("Constructor.java")
|
||||
public void testConstructor() throws Exception {
|
||||
doTestCompiledJava("compiler/testData/loadJava/compiledJava/singleAbstractMethod/adapter/Constructor.java");
|
||||
}
|
||||
|
||||
@TestMetadata("DeepSamLoop.java")
|
||||
public void testDeepSamLoop() throws Exception {
|
||||
doTestCompiledJava("compiler/testData/loadJava/compiledJava/singleAbstractMethod/adapter/DeepSamLoop.java");
|
||||
|
||||
Reference in New Issue
Block a user