From 0b6bb38bb3a0d87dbb18a832a84ddc222ddc6cb0 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 10 Nov 2014 14:21:18 +0300 Subject: [PATCH] Move SAM function type calculation to SamConversionResolver --- .../resolver/SamConversionResolverImpl.kt | 47 +++++++++++++++++++ .../descriptors/LazyJavaClassDescriptor.kt | 47 +------------------ .../java/resolver/SamConversionResolver.kt | 8 ++++ 3 files changed, 57 insertions(+), 45 deletions(-) diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/SamConversionResolverImpl.kt b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/SamConversionResolverImpl.kt index 142ed8398ed..69fb9818dc8 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/SamConversionResolverImpl.kt +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/SamConversionResolverImpl.kt @@ -24,6 +24,15 @@ import org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils import org.jetbrains.jet.lang.descriptors.FunctionDescriptor import org.jetbrains.jet.lang.resolve.java.descriptor.JavaConstructorDescriptor import org.jetbrains.jet.lang.resolve.java.descriptor.JavaMethodDescriptor +import org.jetbrains.jet.lang.types.JetType +import org.jetbrains.jet.lang.types.TypeUtils +import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor +import java.util.ArrayList +import org.jetbrains.jet.lang.types.checker.JetTypeChecker +import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod +import org.jetbrains.jet.lang.resolve.java.descriptor.JavaClassDescriptor +import org.jetbrains.jet.lang.resolve.java.structure.JavaClass +import org.jetbrains.jet.lang.resolve.java.sources.JavaSourceElement public object SamConversionResolverImpl : SamConversionResolver { override fun resolveSamConstructor(name: Name, scope: JetScope): SamConstructorDescriptor? { @@ -41,4 +50,42 @@ public object SamConversionResolverImpl : SamConversionResolver { else -> null } } + + override fun resolveFunctionTypeIfSamInterface( + classDescriptor: JavaClassDescriptor, + resolveMethod: (JavaMethod) -> FunctionDescriptor + ): JetType? { + val jClass = (classDescriptor.getSource() as? JavaSourceElement)?.javaElement as? JavaClass ?: return null + val samInterfaceMethod = SingleAbstractMethodUtils.getSamInterfaceMethod(jClass) ?: return null + val abstractMethod = if (jClass.getFqName() == samInterfaceMethod.getContainingClass().getFqName()) { + resolveMethod(samInterfaceMethod) + } + else { + findFunctionWithMostSpecificReturnType(TypeUtils.getAllSupertypes(classDescriptor.getDefaultType())) + } + return SingleAbstractMethodUtils.getFunctionTypeForAbstractMethod(abstractMethod) + } + + private fun findFunctionWithMostSpecificReturnType(supertypes: Set): SimpleFunctionDescriptor { + val candidates = ArrayList(supertypes.size()) + for (supertype in supertypes) { + val abstractMembers = SingleAbstractMethodUtils.getAbstractMembers(supertype) + if (!abstractMembers.isEmpty()) { + candidates.add((abstractMembers[0] as SimpleFunctionDescriptor)) + } + } + if (candidates.isEmpty()) { + throw IllegalStateException("Couldn't find abstract method in supertypes " + supertypes) + } + var currentMostSpecificType = candidates[0] + for (candidate in candidates) { + val candidateReturnType = candidate.getReturnType() + val currentMostSpecificReturnType = currentMostSpecificType.getReturnType() + assert(candidateReturnType != null && currentMostSpecificReturnType != null) { "$candidate, $currentMostSpecificReturnType" } + if (JetTypeChecker.DEFAULT.isSubtypeOf(candidateReturnType!!, currentMostSpecificReturnType!!)) { + currentMostSpecificType = candidate + } + } + return currentMostSpecificType + } } diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaClassDescriptor.kt b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaClassDescriptor.kt index 4853bbb7cfa..2bd73a5aade 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaClassDescriptor.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaClassDescriptor.kt @@ -31,13 +31,8 @@ import org.jetbrains.jet.lang.resolve.java.lazy.types.toAttributes import org.jetbrains.jet.lang.resolve.scopes.InnerClassesScopeWrapper import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns import org.jetbrains.jet.utils.* -import org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils -import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod -import org.jetbrains.jet.lang.types.TypeUtils import org.jetbrains.jet.lang.resolve.java.descriptor.JavaClassDescriptor import org.jetbrains.jet.lang.descriptors.annotations.Annotations -import java.util.ArrayList -import org.jetbrains.jet.lang.types.checker.JetTypeChecker import org.jetbrains.jet.lang.types.AbstractClassTypeConstructor class LazyJavaClassDescriptor( @@ -96,51 +91,13 @@ class LazyJavaClassDescriptor( override fun getAnnotations() = _annotations() private val _functionTypeForSamInterface = c.storageManager.createNullableLazyValue { - val samInterfaceMethod = SingleAbstractMethodUtils.getSamInterfaceMethod(jClass); - if (samInterfaceMethod != null) { - val abstractMethod = resolveFunctionOfSamInterface(samInterfaceMethod); - SingleAbstractMethodUtils.getFunctionTypeForAbstractMethod(abstractMethod); + c.samConversionResolver.resolveFunctionTypeIfSamInterface(this) { method -> + _scopeForMemberLookup.resolveMethodToFunctionDescriptor(method, false) } - else null } override fun getFunctionTypeForSamInterface(): JetType? = _functionTypeForSamInterface() - private fun resolveFunctionOfSamInterface(samInterfaceMethod: JavaMethod): SimpleFunctionDescriptor { - val methodContainer = samInterfaceMethod.getContainingClass() - val containerFqName = methodContainer.getFqName() - assert(containerFqName != null, "qualified name is null for " + methodContainer) - if (fqName == containerFqName) { - return _scopeForMemberLookup.resolveMethodToFunctionDescriptor(samInterfaceMethod, false) - } - else { - return findFunctionWithMostSpecificReturnType(TypeUtils.getAllSupertypes(getDefaultType())) - } - } - - private fun findFunctionWithMostSpecificReturnType(supertypes: Set): SimpleFunctionDescriptor { - val candidates = ArrayList(supertypes.size()) - for (supertype in supertypes) { - val abstractMembers = SingleAbstractMethodUtils.getAbstractMembers(supertype) - if (!abstractMembers.isEmpty()) { - candidates.add((abstractMembers[0] as SimpleFunctionDescriptor)) - } - } - if (candidates.isEmpty()) { - throw IllegalStateException("Couldn't find abstract method in supertypes " + supertypes) - } - var currentMostSpecificType = candidates[0] - for (candidate in candidates) { - val candidateReturnType = candidate.getReturnType() - val currentMostSpecificReturnType = currentMostSpecificType.getReturnType() - assert(candidateReturnType != null && currentMostSpecificReturnType != null, "$candidate, $currentMostSpecificReturnType") - if (JetTypeChecker.DEFAULT.isSubtypeOf(candidateReturnType!!, currentMostSpecificReturnType!!)) { - currentMostSpecificType = candidate - } - } - return currentMostSpecificType - } - override fun toString() = "lazy java class $fqName" private inner class LazyJavaClassTypeConstructor : AbstractClassTypeConstructor() { diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/SamConversionResolver.kt b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/SamConversionResolver.kt index b8042ac6ac8..27e0081c6f4 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/SamConversionResolver.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/SamConversionResolver.kt @@ -20,9 +20,17 @@ import org.jetbrains.jet.lang.resolve.name.Name import org.jetbrains.jet.lang.resolve.scopes.JetScope import org.jetbrains.jet.lang.resolve.java.descriptor.SamConstructorDescriptor import org.jetbrains.jet.lang.descriptors.FunctionDescriptor +import org.jetbrains.jet.lang.types.JetType +import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod +import org.jetbrains.jet.lang.resolve.java.descriptor.JavaClassDescriptor public trait SamConversionResolver { public fun resolveSamConstructor(name: Name, scope: JetScope): SamConstructorDescriptor? public fun resolveSamAdapter(original: D): D? + + public fun resolveFunctionTypeIfSamInterface( + classDescriptor: JavaClassDescriptor, + resolveMethod: (JavaMethod) -> FunctionDescriptor + ): JetType? }