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();
|
SimpleFunctionDescriptor original = ((SimpleFunctionDescriptor) fun).getOriginal();
|
||||||
if (original.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED) {
|
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) {
|
if (original.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
|
||||||
for (FunctionDescriptor overridden : original.getOverriddenDescriptors()) {
|
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.google.common.collect.Lists;
|
||||||
import com.intellij.psi.*;
|
import com.intellij.psi.*;
|
||||||
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
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.kotlinSignature.AlternativeMethodSignatureData;
|
||||||
import org.jetbrains.jet.lang.resolve.java.kt.JetConstructorAnnotation;
|
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.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.java.wrapper.PsiMethodWrapper;
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
@@ -149,6 +151,7 @@ public final class JavaConstructorResolver {
|
|||||||
ConstructorDescriptor constructor = resolveConstructor(psiClass, isStatic, psiConstructor, containingClass);
|
ConstructorDescriptor constructor = resolveConstructor(psiClass, isStatic, psiConstructor, containingClass);
|
||||||
if (constructor != null) {
|
if (constructor != null) {
|
||||||
constructors.add(constructor);
|
constructors.add(constructor);
|
||||||
|
ContainerUtil.addIfNotNull(constructors, resolveSamAdapter(constructor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -218,4 +221,16 @@ public final class JavaConstructorResolver {
|
|||||||
trace.record(BindingContext.CONSTRUCTOR, psiConstructor, constructorDescriptor);
|
trace.record(BindingContext.CONSTRUCTOR, psiConstructor, constructorDescriptor);
|
||||||
return 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.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
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.SimpleFunctionDescriptorImpl;
|
||||||
import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl;
|
import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl;
|
||||||
import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl;
|
import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl;
|
||||||
@@ -174,7 +175,7 @@ public class SingleAbstractMethodUtils {
|
|||||||
return getFunctionTypeForSamType(type) != null;
|
return getFunctionTypeForSamType(type) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isSamAdapterNecessary(@NotNull SimpleFunctionDescriptor fun) {
|
public static boolean isSamAdapterNecessary(@NotNull FunctionDescriptor fun) {
|
||||||
for (ValueParameterDescriptor param : fun.getValueParameters()) {
|
for (ValueParameterDescriptor param : fun.getValueParameters()) {
|
||||||
if (isSamType(param.getType())) {
|
if (isSamType(param.getType())) {
|
||||||
return true;
|
return true;
|
||||||
@@ -184,20 +185,77 @@ public class SingleAbstractMethodUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static SimpleFunctionDescriptor createSamAdapterFunction(@NotNull SimpleFunctionDescriptor original) {
|
public static SimpleFunctionDescriptor createSamAdapterFunction(@NotNull final SimpleFunctionDescriptor original) {
|
||||||
SimpleFunctionDescriptorImpl result = new SimpleFunctionDescriptorImpl(
|
final SimpleFunctionDescriptorImpl result = new SimpleFunctionDescriptorImpl(
|
||||||
original.getContainingDeclaration(),
|
original.getContainingDeclaration(),
|
||||||
original.getAnnotations(),
|
original.getAnnotations(),
|
||||||
original.getName(),
|
original.getName(),
|
||||||
CallableMemberDescriptor.Kind.SYNTHESIZED
|
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();
|
JetType returnTypeUnsubstituted = original.getReturnType();
|
||||||
assert returnTypeUnsubstituted != null : original;
|
JetType returnType;
|
||||||
JetType returnType = typeParameters.substitutor.substitute(returnTypeUnsubstituted, Variance.OUT_VARIANCE);
|
if (returnTypeUnsubstituted == null) { // return type may be null for not yet initialized constructors
|
||||||
assert returnType != null : "couldn't substitute type: " + returnType + ", substitutor = " + typeParameters.substitutor;
|
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();
|
List<ValueParameterDescriptor> valueParameters = Lists.newArrayList();
|
||||||
for (ValueParameterDescriptor originalParam : original.getValueParameters()) {
|
for (ValueParameterDescriptor originalParam : original.getValueParameters()) {
|
||||||
@@ -208,22 +266,12 @@ public class SingleAbstractMethodUtils {
|
|||||||
assert newType != null : "couldn't substitute type: " + newTypeUnsubstituted + ", substitutor = " + typeParameters.substitutor;
|
assert newType != null : "couldn't substitute type: " + newTypeUnsubstituted + ", substitutor = " + typeParameters.substitutor;
|
||||||
|
|
||||||
ValueParameterDescriptor newParam = new ValueParameterDescriptorImpl(
|
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);
|
valueParameters.add(newParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
result.initialize(
|
initializer.initialize(typeParameters.descriptors, valueParameters, returnType);
|
||||||
null,
|
return adapter;
|
||||||
original.getExpectedThisObject(),
|
|
||||||
typeParameters.descriptors,
|
|
||||||
valueParameters,
|
|
||||||
returnType,
|
|
||||||
original.getModality(),
|
|
||||||
original.getVisibility(),
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -273,4 +321,12 @@ public class SingleAbstractMethodUtils {
|
|||||||
this.substitutor = substitutor;
|
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.descriptors.annotations.AnnotationDescriptor;
|
||||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -36,7 +37,11 @@ public class ConstructorDescriptorImpl extends FunctionDescriptorImpl implements
|
|||||||
private static final Name NAME = Name.special("<init>");
|
private static final Name NAME = Name.special("<init>");
|
||||||
|
|
||||||
public ConstructorDescriptorImpl(@NotNull ClassDescriptor containingDeclaration, @NotNull List<AnnotationDescriptor> annotations, boolean isPrimary) {
|
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;
|
this.isPrimary = isPrimary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -265,7 +265,7 @@ public interface BindingContext {
|
|||||||
|
|
||||||
WritableSlice<CallableDescriptor, Boolean> IS_DECLARED_IN_JAVA = Slices.createSimpleSlice();
|
WritableSlice<CallableDescriptor, Boolean> IS_DECLARED_IN_JAVA = Slices.createSimpleSlice();
|
||||||
WritableSlice<SimpleFunctionDescriptor, ClassDescriptor> SAM_CONSTRUCTOR_TO_INTERFACE = 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();
|
WritableSlice<CallableMemberDescriptor, DeclarationDescriptor> SOURCE_DESCRIPTOR_FOR_SYNTHESIZED = Slices.createSimpleSlice();
|
||||||
|
|
||||||
@SuppressWarnings("UnusedDeclaration")
|
@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");
|
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")
|
@TestMetadata("DeepSamLoop.java")
|
||||||
public void testDeepSamLoop() throws Exception {
|
public void testDeepSamLoop() throws Exception {
|
||||||
doTestCompiledJava("compiler/testData/loadJava/compiledJava/singleAbstractMethod/adapter/DeepSamLoop.java");
|
doTestCompiledJava("compiler/testData/loadJava/compiledJava/singleAbstractMethod/adapter/DeepSamLoop.java");
|
||||||
|
|||||||
Reference in New Issue
Block a user