diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesUtil.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesUtil.java index 25f2dc9cb4a..158ebf66582 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesUtil.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesUtil.java @@ -34,7 +34,7 @@ public class SignaturesUtil { @NotNull List originalParameters, @Nullable DeclarationDescriptor newOwner ) { - Map result = Maps.newHashMap(); + Map result = Maps.newLinkedHashMap(); // save order of type parameters for (TypeParameterDescriptor typeParameter : originalParameters) { result.put(typeParameter, TypeParameterDescriptorImpl.createForFurtherModification( diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/sam/SingleAbstractMethodUtils.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/sam/SingleAbstractMethodUtils.java index 93340e13f37..fb9e88a17c4 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/sam/SingleAbstractMethodUtils.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/sam/SingleAbstractMethodUtils.java @@ -21,14 +21,19 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl; +import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl; import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl; +import org.jetbrains.jet.lang.resolve.java.kotlinSignature.SignaturesUtil; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.TypeSubstitutor; +import org.jetbrains.jet.lang.types.Variance; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Map; public class SingleAbstractMethodUtils { public static boolean isFunctionalInterface(@NotNull ClassDescriptor klass) { @@ -53,7 +58,6 @@ public class SingleAbstractMethodUtils { @NotNull private static JetType getFunctionalTypeForFunction(@NotNull FunctionDescriptor function) { - // TODO substitute type parameters of class // TODO substitute type parameters of function with star projections JetType returnType = function.getReturnType(); assert returnType != null : "function is not initialized: " + function; @@ -72,16 +76,32 @@ public class SingleAbstractMethodUtils { CallableMemberDescriptor.Kind.SYNTHESIZED ); - JetType parameterType = getFunctionalTypeForFunction(getAbstractMethodOfFunctionalInterface(klass));; + Map traitToFunTypeParameters = + SignaturesUtil.recreateTypeParametersAndReturnMapping(klass.getTypeConstructor().getParameters(), result); + TypeSubstitutor typeParametersSubstitutor = SignaturesUtil.createSubstitutorForTypeParameters(traitToFunTypeParameters); + + JetType parameterTypeUnsubstituted = getFunctionalTypeForFunction(getAbstractMethodOfFunctionalInterface(klass)); + JetType parameterType = typeParametersSubstitutor.substitute(parameterTypeUnsubstituted, Variance.IN_VARIANCE); + assert parameterType != null : "couldn't substitute type: " + parameterType + ", substitutor = " + typeParametersSubstitutor; ValueParameterDescriptor parameter = new ValueParameterDescriptorImpl( result, 0, Collections.emptyList(), Name.identifier("function"), parameterType, false, null); + JetType returnType = typeParametersSubstitutor.substitute(klass.getDefaultType(), Variance.OUT_VARIANCE); + assert returnType != null : "couldn't substitute type: " + returnType + ", substitutor = " + typeParametersSubstitutor; + + for (TypeParameterDescriptorImpl typeParameter : traitToFunTypeParameters.values()) { + // TODO copy substituted upper bound + // TODO consider recursive upper bound + typeParameter.addDefaultUpperBound(); + typeParameter.setInitialized(); + } + result.initialize( null, null, - Lists.newArrayList(), // TODO recreate type parameters of class + Lists.newArrayList(traitToFunTypeParameters.values()), Arrays.asList(parameter), - klass.getDefaultType(), // TODO substitute type parameters of class + returnType, Modality.FINAL, klass.getVisibility(), false diff --git a/compiler/testData/loadJava/compiledJava/singleAbstractMethod/Comparator.java b/compiler/testData/loadJava/compiledJava/singleAbstractMethod/Comparator.java new file mode 100644 index 00000000000..853160a4ded --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/singleAbstractMethod/Comparator.java @@ -0,0 +1,7 @@ +package test; + +public interface Comparator { + int compare(T o1, T o2); + + boolean equals(Object obj); +} diff --git a/compiler/testData/loadJava/compiledJava/singleAbstractMethod/Comparator.txt b/compiler/testData/loadJava/compiledJava/singleAbstractMethod/Comparator.txt new file mode 100644 index 00000000000..db9c7ae8931 --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/singleAbstractMethod/Comparator.txt @@ -0,0 +1,7 @@ +package test + +public /*synthesized*/ fun Comparator(/*0*/ function : (T?, T?) -> jet.Int) : test.Comparator + +public trait Comparator : java.lang.Object { + public abstract fun compare(/*0*/ p0 : T?, /*1*/ p1 : T?) : jet.Int +} diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java index 2eb50924b61..4e17da419b0 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java @@ -1130,6 +1130,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadJava/compiledJava/singleAbstractMethod"), Pattern.compile("^(.+)\\.java$"), true); } + @TestMetadata("Comparator.java") + public void testComparator() throws Exception { + doTestCompiledJava("compiler/testData/loadJava/compiledJava/singleAbstractMethod/Comparator.java"); + } + @TestMetadata("FilenameFilter.java") public void testFilenameFilter() throws Exception { doTestCompiledJava("compiler/testData/loadJava/compiledJava/singleAbstractMethod/FilenameFilter.java");