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")
|
@TestMetadata("compiler/testData/diagnostics/tests/functionAsExpression")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+3
-3
@@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.load.java.sam
|
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.components.SamConversionResolver
|
||||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
|
||||||
import org.jetbrains.kotlin.storage.StorageManager
|
import org.jetbrains.kotlin.storage.StorageManager
|
||||||
import org.jetbrains.kotlin.types.SimpleType
|
import org.jetbrains.kotlin.types.SimpleType
|
||||||
|
|
||||||
@@ -25,9 +25,9 @@ class SamConversionResolverImpl(
|
|||||||
storageManager: StorageManager,
|
storageManager: StorageManager,
|
||||||
private val samWithReceiverResolvers: Iterable<SamWithReceiverResolver>
|
private val samWithReceiverResolvers: Iterable<SamWithReceiverResolver>
|
||||||
): SamConversionResolver {
|
): 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) {
|
return functionTypesForSamInterfaces.computeIfAbsent(classDescriptor) {
|
||||||
val abstractMethod = SingleAbstractMethodUtils.getSingleAbstractMethodOrNull(classDescriptor) ?: return@computeIfAbsent null
|
val abstractMethod = SingleAbstractMethodUtils.getSingleAbstractMethodOrNull(classDescriptor) ?: return@computeIfAbsent null
|
||||||
val shouldConvertFirstParameterToDescriptor = samWithReceiverResolvers.any { it.shouldConvertFirstSamParameterToReceiver(abstractMethod) }
|
val shouldConvertFirstParameterToDescriptor = samWithReceiverResolvers.any { it.shouldConvertFirstSamParameterToReceiver(abstractMethod) }
|
||||||
|
|||||||
+16
-4
@@ -78,9 +78,12 @@ public class SingleAbstractMethodUtils {
|
|||||||
// e.g. samType == Comparator<String>?
|
// e.g. samType == Comparator<String>?
|
||||||
|
|
||||||
ClassifierDescriptor classifier = samType.getConstructor().getDeclarationDescriptor();
|
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>
|
// Function2<T, T, Int>
|
||||||
SimpleType functionTypeDefault = samResolver.resolveFunctionTypeIfSamInterface((JavaClassDescriptor) classifier);
|
SimpleType functionTypeDefault = samResolver.resolveFunctionTypeIfSamInterface(descriptor);
|
||||||
|
|
||||||
if (functionTypeDefault != null) {
|
if (functionTypeDefault != null) {
|
||||||
SimpleType noProjectionsSamType = SingleAbstractMethodUtilsKt.nonProjectionParametrization(samType);
|
SimpleType noProjectionsSamType = SingleAbstractMethodUtilsKt.nonProjectionParametrization(samType);
|
||||||
@@ -131,7 +134,7 @@ public class SingleAbstractMethodUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@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
|
// 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
|
// Otherwise android data binding can cause resolve re-entrance
|
||||||
// For details see KT-18687, KT-16149
|
// For details see KT-18687, KT-16149
|
||||||
@@ -140,7 +143,13 @@ public class SingleAbstractMethodUtils {
|
|||||||
return null;
|
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);
|
List<CallableMemberDescriptor> abstractMembers = getAbstractMembers(klass);
|
||||||
if (abstractMembers.size() == 1) {
|
if (abstractMembers.size() == 1) {
|
||||||
@@ -224,6 +233,9 @@ public class SingleAbstractMethodUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isSamType(@NotNull KotlinType type) {
|
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;
|
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");
|
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")
|
@TestMetadata("basicFunInterfaceDisabled.kt")
|
||||||
public void testBasicFunInterfaceDisabled() throws Exception {
|
public void testBasicFunInterfaceDisabled() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/funInterface/basicFunInterfaceDisabled.kt");
|
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");
|
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")
|
@TestMetadata("basicFunInterfaceDisabled.kt")
|
||||||
public void testBasicFunInterfaceDisabled() throws Exception {
|
public void testBasicFunInterfaceDisabled() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/funInterface/basicFunInterfaceDisabled.kt");
|
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.DefaultImplementation
|
||||||
import org.jetbrains.kotlin.container.PlatformSpecificExtension
|
import org.jetbrains.kotlin.container.PlatformSpecificExtension
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||||
import org.jetbrains.kotlin.types.SimpleType
|
import org.jetbrains.kotlin.types.SimpleType
|
||||||
|
|
||||||
@DefaultImplementation(impl = SamConversionResolver.Empty::class)
|
@DefaultImplementation(impl = SamConversionResolver.Empty::class)
|
||||||
interface SamConversionResolver : PlatformSpecificExtension<SamConversionResolver> {
|
interface SamConversionResolver : PlatformSpecificExtension<SamConversionResolver> {
|
||||||
object Empty : SamConversionResolver {
|
object Empty : SamConversionResolver {
|
||||||
override fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): SimpleType? = null
|
override fun resolveFunctionTypeIfSamInterface(classDescriptor: ClassDescriptor): SimpleType? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
object JavaBasedSamConversionResolver : SamConversionResolver {
|
object JavaBasedSamConversionResolver : SamConversionResolver {
|
||||||
override fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): SimpleType? {
|
override fun resolveFunctionTypeIfSamInterface(classDescriptor: ClassDescriptor): SimpleType? {
|
||||||
|
if (classDescriptor !is JavaClassDescriptor) return null
|
||||||
return classDescriptor.defaultFunctionTypeForSamInterface
|
return classDescriptor.defaultFunctionTypeForSamInterface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): SimpleType?
|
fun resolveFunctionTypeIfSamInterface(classDescriptor: ClassDescriptor): SimpleType?
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user