Supported simplest cases of SAM adapter.
This commit is contained in:
+3
-1
@@ -268,7 +268,9 @@ public class SignaturesPropagationData {
|
|||||||
FqName fqName = DescriptorUtils.getFQName(klass).toSafe();
|
FqName fqName = DescriptorUtils.getFQName(klass).toSafe();
|
||||||
|
|
||||||
for (FunctionDescriptor fun : klass.getDefaultType().getMemberScope().getFunctions(functionName)) {
|
for (FunctionDescriptor fun : klass.getDefaultType().getMemberScope().getFunctions(functionName)) {
|
||||||
if (fun.getKind().isReal() && fun.getValueParameters().size() == parameterCount) {
|
CallableMemberDescriptor.Kind kind = fun.getKind();
|
||||||
|
if ((kind == CallableMemberDescriptor.Kind.DECLARATION || kind == CallableMemberDescriptor.Kind.DELEGATION) &&
|
||||||
|
fun.getValueParameters().size() == parameterCount) {
|
||||||
PsiElement declaration = BindingContextUtils.descriptorToDeclaration(bindingContext, fun);
|
PsiElement declaration = BindingContextUtils.descriptorToDeclaration(bindingContext, fun);
|
||||||
if (declaration instanceof PsiMethod) {
|
if (declaration instanceof PsiMethod) {
|
||||||
result.put(fqName, Pair.create(fun, (PsiMethod) declaration));
|
result.put(fqName, Pair.create(fun, (PsiMethod) declaration));
|
||||||
|
|||||||
+14
@@ -270,6 +270,8 @@ public final class JavaFunctionResolver {
|
|||||||
SimpleFunctionDescriptor function = resolveMethodToFunctionDescriptor(psiClass, method, scopeData, owner);
|
SimpleFunctionDescriptor function = resolveMethodToFunctionDescriptor(psiClass, method, scopeData, owner);
|
||||||
if (function != null) {
|
if (function != null) {
|
||||||
functionsFromCurrent.add(function);
|
functionsFromCurrent.add(function);
|
||||||
|
|
||||||
|
ContainerUtil.addIfNotNull(functionsFromCurrent, resolveSamAdapter(function));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,6 +370,18 @@ public final class JavaFunctionResolver {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private SimpleFunctionDescriptor resolveSamAdapter(@NotNull SimpleFunctionDescriptor original) {
|
||||||
|
if (SingleAbstractMethodUtils.isSamAdapterNecessary(original)) {
|
||||||
|
SimpleFunctionDescriptor adapterFunction = SingleAbstractMethodUtils.createSamAdapterFunction(original);
|
||||||
|
|
||||||
|
trace.record(BindingContext.SAM_ADAPTER_FUNCTION_TO_ORIGINAL, adapterFunction, original);
|
||||||
|
trace.record(BindingContext.SOURCE_DESCRIPTOR_FOR_SYNTHESIZED, adapterFunction, original);
|
||||||
|
return adapterFunction;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public Set<FunctionDescriptor> resolveFunctionGroup(
|
public Set<FunctionDescriptor> resolveFunctionGroup(
|
||||||
@NotNull Name methodName,
|
@NotNull Name methodName,
|
||||||
|
|||||||
+61
-4
@@ -23,10 +23,12 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
|||||||
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;
|
||||||
|
import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode;
|
||||||
import org.jetbrains.jet.lang.resolve.java.kotlinSignature.SignaturesUtil;
|
import org.jetbrains.jet.lang.resolve.java.kotlinSignature.SignaturesUtil;
|
||||||
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;
|
||||||
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
||||||
|
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||||
import org.jetbrains.jet.lang.types.Variance;
|
import org.jetbrains.jet.lang.types.Variance;
|
||||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||||
|
|
||||||
@@ -40,7 +42,9 @@ public class SingleAbstractMethodUtils {
|
|||||||
private static List<CallableMemberDescriptor> getAbstractMembers(@NotNull JetType type) {
|
private static List<CallableMemberDescriptor> getAbstractMembers(@NotNull JetType type) {
|
||||||
List<CallableMemberDescriptor> abstractMembers = Lists.newArrayList();
|
List<CallableMemberDescriptor> abstractMembers = Lists.newArrayList();
|
||||||
for (DeclarationDescriptor member : type.getMemberScope().getAllDescriptors()) {
|
for (DeclarationDescriptor member : type.getMemberScope().getAllDescriptors()) {
|
||||||
if (member instanceof CallableMemberDescriptor && ((CallableMemberDescriptor) member).getModality() == Modality.ABSTRACT) {
|
if (member instanceof CallableMemberDescriptor &&
|
||||||
|
((CallableMemberDescriptor) member).getModality() == Modality.ABSTRACT &&
|
||||||
|
((CallableMemberDescriptor) member).getKind() != CallableMemberDescriptor.Kind.SYNTHESIZED) {
|
||||||
abstractMembers.add((CallableMemberDescriptor) member);
|
abstractMembers.add((CallableMemberDescriptor) member);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -48,14 +52,17 @@ public class SingleAbstractMethodUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static JetType getFunctionTypeForFunction(@NotNull FunctionDescriptor function) {
|
private static JetType getFunctionTypeForSamType(@NotNull JetType samType) {
|
||||||
|
FunctionDescriptor function = getAbstractMethodOfSamType(samType);
|
||||||
JetType returnType = function.getReturnType();
|
JetType returnType = function.getReturnType();
|
||||||
assert returnType != null : "function is not initialized: " + function;
|
assert returnType != null : "function is not initialized: " + function;
|
||||||
List<JetType> parameterTypes = Lists.newArrayList();
|
List<JetType> parameterTypes = Lists.newArrayList();
|
||||||
for (ValueParameterDescriptor parameter : function.getValueParameters()) {
|
for (ValueParameterDescriptor parameter : function.getValueParameters()) {
|
||||||
parameterTypes.add(parameter.getType());
|
parameterTypes.add(parameter.getType());
|
||||||
}
|
}
|
||||||
return KotlinBuiltIns.getInstance().getFunctionType(Collections.<AnnotationDescriptor>emptyList(), null, parameterTypes, returnType);
|
JetType functionType = KotlinBuiltIns.getInstance()
|
||||||
|
.getFunctionType(Collections.<AnnotationDescriptor>emptyList(), null, parameterTypes, returnType);
|
||||||
|
return TypeUtils.makeNullableAsSpecified(functionType, samType.isNullable());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isSamInterface(@NotNull ClassDescriptor klass) {
|
private static boolean isSamInterface(@NotNull ClassDescriptor klass) {
|
||||||
@@ -91,7 +98,7 @@ public class SingleAbstractMethodUtils {
|
|||||||
SignaturesUtil.recreateTypeParametersAndReturnMapping(samInterface.getTypeConstructor().getParameters(), result);
|
SignaturesUtil.recreateTypeParametersAndReturnMapping(samInterface.getTypeConstructor().getParameters(), result);
|
||||||
TypeSubstitutor typeParametersSubstitutor = SignaturesUtil.createSubstitutorForTypeParameters(traitToFunTypeParameters);
|
TypeSubstitutor typeParametersSubstitutor = SignaturesUtil.createSubstitutorForTypeParameters(traitToFunTypeParameters);
|
||||||
|
|
||||||
JetType parameterTypeUnsubstituted = getFunctionTypeForFunction(getAbstractMethodOfSamType(samInterface.getDefaultType()));
|
JetType parameterTypeUnsubstituted = getFunctionTypeForSamType(samInterface.getDefaultType());
|
||||||
JetType parameterType = typeParametersSubstitutor.substitute(parameterTypeUnsubstituted, Variance.IN_VARIANCE);
|
JetType parameterType = typeParametersSubstitutor.substitute(parameterTypeUnsubstituted, Variance.IN_VARIANCE);
|
||||||
assert parameterType != null : "couldn't substitute type: " + parameterType + ", substitutor = " + typeParametersSubstitutor;
|
assert parameterType != null : "couldn't substitute type: " + parameterType + ", substitutor = " + typeParametersSubstitutor;
|
||||||
ValueParameterDescriptor parameter = new ValueParameterDescriptorImpl(
|
ValueParameterDescriptor parameter = new ValueParameterDescriptorImpl(
|
||||||
@@ -127,6 +134,56 @@ public class SingleAbstractMethodUtils {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isSamType(@NotNull JetType type) {
|
||||||
|
ClassifierDescriptor classifier = type.getConstructor().getDeclarationDescriptor();
|
||||||
|
return classifier instanceof ClassDescriptorFromJvmBytecode &&
|
||||||
|
((ClassDescriptorFromJvmBytecode) classifier).isSamInterface();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isSamAdapterNecessary(@NotNull SimpleFunctionDescriptor fun) {
|
||||||
|
for (ValueParameterDescriptor param : fun.getValueParameters()) {
|
||||||
|
if (isSamType(param.getType())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static SimpleFunctionDescriptor createSamAdapterFunction(@NotNull SimpleFunctionDescriptor original) {
|
||||||
|
SimpleFunctionDescriptorImpl result = new SimpleFunctionDescriptorImpl(
|
||||||
|
original.getContainingDeclaration(),
|
||||||
|
original.getAnnotations(),
|
||||||
|
original.getName(),
|
||||||
|
CallableMemberDescriptor.Kind.SYNTHESIZED
|
||||||
|
);
|
||||||
|
|
||||||
|
JetType returnType = original.getReturnType();
|
||||||
|
|
||||||
|
List<ValueParameterDescriptor> valueParameters = Lists.newArrayList();
|
||||||
|
for (ValueParameterDescriptor originalParam : original.getValueParameters()) {
|
||||||
|
JetType originalType = originalParam.getType();
|
||||||
|
JetType newType = isSamType(originalType) ? getFunctionTypeForSamType(originalType) : originalType;
|
||||||
|
|
||||||
|
ValueParameterDescriptor newParam = new ValueParameterDescriptorImpl(
|
||||||
|
result, originalParam.getIndex(), originalParam.getAnnotations(), originalParam.getName(), newType, false, null);
|
||||||
|
valueParameters.add(newParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
result.initialize(
|
||||||
|
null,
|
||||||
|
original.getExpectedThisObject(),
|
||||||
|
Collections.<TypeParameterDescriptor>emptyList(), // TODO copy type parameters
|
||||||
|
valueParameters,
|
||||||
|
returnType,
|
||||||
|
original.getModality(),
|
||||||
|
original.getVisibility(),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static SimpleFunctionDescriptor getAbstractMethodOfSamType(@NotNull JetType type) {
|
public static SimpleFunctionDescriptor getAbstractMethodOfSamType(@NotNull JetType type) {
|
||||||
return (SimpleFunctionDescriptor) getAbstractMembers(type).get(0);
|
return (SimpleFunctionDescriptor) getAbstractMembers(type).get(0);
|
||||||
|
|||||||
@@ -255,6 +255,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<CallableMemberDescriptor, DeclarationDescriptor> SOURCE_DESCRIPTOR_FOR_SYNTHESIZED = Slices.createSimpleSlice();
|
WritableSlice<CallableMemberDescriptor, DeclarationDescriptor> SOURCE_DESCRIPTOR_FOR_SYNTHESIZED = Slices.createSimpleSlice();
|
||||||
|
|
||||||
@SuppressWarnings("UnusedDeclaration")
|
@SuppressWarnings("UnusedDeclaration")
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
public class Basic {
|
||||||
|
public void foo(Runnable r) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void bar(Runnable r) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
public open class Basic : java.lang.Object {
|
||||||
|
public constructor Basic()
|
||||||
|
public open /*synthesized*/ fun foo(/*0*/ p0 : (() -> jet.Unit)?) : jet.Unit
|
||||||
|
public open fun foo(/*0*/ p0 : java.lang.Runnable?) : jet.Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
package Basic {
|
||||||
|
public open /*synthesized*/ fun bar(/*0*/ p0 : (() -> jet.Unit)?) : jet.Unit
|
||||||
|
public open fun bar(/*0*/ p0 : java.lang.Runnable?) : jet.Unit
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
import java.io.FilenameFilter;
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
public class NonTrivialFunctionType {
|
||||||
|
public void foo(FilenameFilter filenameFilter) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void foo(Comparator<String> comparator) {
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
public open class NonTrivialFunctionType : java.lang.Object {
|
||||||
|
public constructor NonTrivialFunctionType()
|
||||||
|
public open /*synthesized*/ fun foo(/*0*/ p0 : ((java.io.File?, jet.String?) -> jet.Boolean)?) : jet.Unit
|
||||||
|
public open /*synthesized*/ fun foo(/*0*/ p0 : ((jet.String?, jet.String?) -> jet.Int)?) : jet.Unit
|
||||||
|
public open fun foo(/*0*/ p0 : java.io.FilenameFilter?) : jet.Unit
|
||||||
|
public open fun foo(/*0*/ p0 : java.util.Comparator<jet.String>?) : jet.Unit
|
||||||
|
}
|
||||||
@@ -1172,6 +1172,7 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/loadJava/compiledJava/singleAbstractMethod")
|
@TestMetadata("compiler/testData/loadJava/compiledJava/singleAbstractMethod")
|
||||||
|
@InnerTestClasses({SingleAbstractMethod.Adapter.class})
|
||||||
public static class SingleAbstractMethod extends AbstractLoadJavaTest {
|
public static class SingleAbstractMethod extends AbstractLoadJavaTest {
|
||||||
public void testAllFilesPresentInSingleAbstractMethod() throws Exception {
|
public void testAllFilesPresentInSingleAbstractMethod() throws Exception {
|
||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadJava/compiledJava/singleAbstractMethod"), Pattern.compile("^(.+)\\.java$"), true);
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadJava/compiledJava/singleAbstractMethod"), Pattern.compile("^(.+)\\.java$"), true);
|
||||||
@@ -1217,6 +1218,30 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
|
|||||||
doTestCompiledJava("compiler/testData/loadJava/compiledJava/singleAbstractMethod/Runnable.java");
|
doTestCompiledJava("compiler/testData/loadJava/compiledJava/singleAbstractMethod/Runnable.java");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/loadJava/compiledJava/singleAbstractMethod/adapter")
|
||||||
|
public static class Adapter extends AbstractLoadJavaTest {
|
||||||
|
public void testAllFilesPresentInAdapter() throws Exception {
|
||||||
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadJava/compiledJava/singleAbstractMethod/adapter"), Pattern.compile("^(.+)\\.java$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Basic.java")
|
||||||
|
public void testBasic() throws Exception {
|
||||||
|
doTestCompiledJava("compiler/testData/loadJava/compiledJava/singleAbstractMethod/adapter/Basic.java");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("NonTrivialFunctionType.java")
|
||||||
|
public void testNonTrivialFunctionType() throws Exception {
|
||||||
|
doTestCompiledJava("compiler/testData/loadJava/compiledJava/singleAbstractMethod/adapter/NonTrivialFunctionType.java");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Test innerSuite() {
|
||||||
|
TestSuite suite = new TestSuite("SingleAbstractMethod");
|
||||||
|
suite.addTestSuite(SingleAbstractMethod.class);
|
||||||
|
suite.addTestSuite(Adapter.class);
|
||||||
|
return suite;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/loadJava/compiledJava/static")
|
@TestMetadata("compiler/testData/loadJava/compiledJava/static")
|
||||||
@@ -1269,7 +1294,7 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
|
|||||||
suite.addTestSuite(ProtectedPackage.class);
|
suite.addTestSuite(ProtectedPackage.class);
|
||||||
suite.addTestSuite(ProtectedStatic.class);
|
suite.addTestSuite(ProtectedStatic.class);
|
||||||
suite.addTestSuite(SignaturePropagation.class);
|
suite.addTestSuite(SignaturePropagation.class);
|
||||||
suite.addTestSuite(SingleAbstractMethod.class);
|
suite.addTest(SingleAbstractMethod.innerSuite());
|
||||||
suite.addTestSuite(Static.class);
|
suite.addTestSuite(Static.class);
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user