FIC: Make SAM conversions also for fun interfaces, add base test
This commit is contained in:
+28
@@ -7797,6 +7797,34 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/funInterface")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class FunInterface extends AbstractFirDiagnosticsSmokeTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInFunInterface() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/funInterface"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("basicFunInterface.kt")
|
||||
public void testBasicFunInterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/funInterface/basicFunInterface.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("basicFunInterfaceConversion.kt")
|
||||
public void testBasicFunInterfaceConversion() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/funInterface/basicFunInterfaceConversion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("basicFunInterfaceDisabled.kt")
|
||||
public void testBasicFunInterfaceDisabled() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/funInterface/basicFunInterfaceDisabled.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/functionAsExpression")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+3
-3
@@ -16,8 +16,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.load.java.sam
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.load.java.components.SamConversionResolver
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.types.SimpleType
|
||||
|
||||
@@ -25,9 +25,9 @@ class SamConversionResolverImpl(
|
||||
storageManager: StorageManager,
|
||||
private val samWithReceiverResolvers: Iterable<SamWithReceiverResolver>
|
||||
): SamConversionResolver {
|
||||
private val functionTypesForSamInterfaces = storageManager.createCacheWithNullableValues<JavaClassDescriptor, SimpleType>()
|
||||
private val functionTypesForSamInterfaces = storageManager.createCacheWithNullableValues<ClassDescriptor, SimpleType>()
|
||||
|
||||
override fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): SimpleType? {
|
||||
override fun resolveFunctionTypeIfSamInterface(classDescriptor: ClassDescriptor): SimpleType? {
|
||||
return functionTypesForSamInterfaces.computeIfAbsent(classDescriptor) {
|
||||
val abstractMethod = SingleAbstractMethodUtils.getSingleAbstractMethodOrNull(classDescriptor) ?: return@computeIfAbsent null
|
||||
val shouldConvertFirstParameterToDescriptor = samWithReceiverResolvers.any { it.shouldConvertFirstSamParameterToReceiver(abstractMethod) }
|
||||
|
||||
+16
-4
@@ -78,9 +78,12 @@ public class SingleAbstractMethodUtils {
|
||||
// e.g. samType == Comparator<String>?
|
||||
|
||||
ClassifierDescriptor classifier = samType.getConstructor().getDeclarationDescriptor();
|
||||
if (classifier instanceof JavaClassDescriptor) {
|
||||
if (classifier instanceof ClassDescriptor) {
|
||||
ClassDescriptor descriptor = (ClassDescriptor) classifier;
|
||||
if (!(descriptor instanceof JavaClassDescriptor) && !descriptor.isFun()) return null;
|
||||
|
||||
// Function2<T, T, Int>
|
||||
SimpleType functionTypeDefault = samResolver.resolveFunctionTypeIfSamInterface((JavaClassDescriptor) classifier);
|
||||
SimpleType functionTypeDefault = samResolver.resolveFunctionTypeIfSamInterface(descriptor);
|
||||
|
||||
if (functionTypeDefault != null) {
|
||||
SimpleType noProjectionsSamType = SingleAbstractMethodUtilsKt.nonProjectionParametrization(samType);
|
||||
@@ -131,7 +134,7 @@ public class SingleAbstractMethodUtils {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static FunctionDescriptor getSingleAbstractMethodOrNull(@NotNull JavaClassDescriptor klass) {
|
||||
public static FunctionDescriptor getSingleAbstractMethodOrNull(@NotNull ClassDescriptor klass) {
|
||||
// NB: this check MUST BE at start. Please do not touch until following to-do is resolved
|
||||
// Otherwise android data binding can cause resolve re-entrance
|
||||
// For details see KT-18687, KT-16149
|
||||
@@ -140,7 +143,13 @@ public class SingleAbstractMethodUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (klass.isDefinitelyNotSamInterface()) return null;
|
||||
if (klass instanceof JavaClassDescriptor) {
|
||||
if (((JavaClassDescriptor) klass).isDefinitelyNotSamInterface()) {
|
||||
return null;
|
||||
}
|
||||
} else if (!klass.isFun()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<CallableMemberDescriptor> abstractMembers = getAbstractMembers(klass);
|
||||
if (abstractMembers.size() == 1) {
|
||||
@@ -224,6 +233,9 @@ public class SingleAbstractMethodUtils {
|
||||
}
|
||||
|
||||
public static boolean isSamType(@NotNull KotlinType type) {
|
||||
ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
|
||||
if (descriptor instanceof ClassDescriptor && ((ClassDescriptor) descriptor).isFun()) return true;
|
||||
|
||||
return getFunctionTypeForSamType(type, SamConversionResolver.JavaBasedSamConversionResolver.INSTANCE) != null;
|
||||
}
|
||||
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// !LANGUAGE: +NewInference +FunctionInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
fun interface Foo {
|
||||
fun invoke()
|
||||
}
|
||||
|
||||
fun foo(f: Foo) {}
|
||||
|
||||
fun test() {
|
||||
foo {}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package
|
||||
|
||||
public fun foo(/*0*/ f: Foo): kotlin.Unit
|
||||
public fun test(): kotlin.Unit
|
||||
|
||||
public interface Foo {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public abstract fun invoke(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -7896,6 +7896,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
runTest("compiler/testData/diagnostics/tests/funInterface/basicFunInterface.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("basicFunInterfaceConversion.kt")
|
||||
public void testBasicFunInterfaceConversion() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/funInterface/basicFunInterfaceConversion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("basicFunInterfaceDisabled.kt")
|
||||
public void testBasicFunInterfaceDisabled() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/funInterface/basicFunInterfaceDisabled.kt");
|
||||
|
||||
Generated
+5
@@ -7891,6 +7891,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
runTest("compiler/testData/diagnostics/tests/funInterface/basicFunInterface.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("basicFunInterfaceConversion.kt")
|
||||
public void testBasicFunInterfaceConversion() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/funInterface/basicFunInterfaceConversion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("basicFunInterfaceDisabled.kt")
|
||||
public void testBasicFunInterfaceDisabled() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/funInterface/basicFunInterfaceDisabled.kt");
|
||||
|
||||
+5
-3
@@ -18,20 +18,22 @@ package org.jetbrains.kotlin.load.java.components
|
||||
|
||||
import org.jetbrains.kotlin.container.DefaultImplementation
|
||||
import org.jetbrains.kotlin.container.PlatformSpecificExtension
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.types.SimpleType
|
||||
|
||||
@DefaultImplementation(impl = SamConversionResolver.Empty::class)
|
||||
interface SamConversionResolver : PlatformSpecificExtension<SamConversionResolver> {
|
||||
object Empty : SamConversionResolver {
|
||||
override fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): SimpleType? = null
|
||||
override fun resolveFunctionTypeIfSamInterface(classDescriptor: ClassDescriptor): SimpleType? = null
|
||||
}
|
||||
|
||||
object JavaBasedSamConversionResolver : SamConversionResolver {
|
||||
override fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): SimpleType? {
|
||||
override fun resolveFunctionTypeIfSamInterface(classDescriptor: ClassDescriptor): SimpleType? {
|
||||
if (classDescriptor !is JavaClassDescriptor) return null
|
||||
return classDescriptor.defaultFunctionTypeForSamInterface
|
||||
}
|
||||
}
|
||||
|
||||
fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): SimpleType?
|
||||
fun resolveFunctionTypeIfSamInterface(classDescriptor: ClassDescriptor): SimpleType?
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user