Fixed loading SAM interfaces when they inherit abstract methods.

This commit is contained in:
Evgeny Gerashchenko
2013-05-21 16:37:24 +04:00
parent fb416418f0
commit de6d5a4a96
10 changed files with 76 additions and 8 deletions
@@ -409,9 +409,6 @@ public final class MembersCache {
// Returns null if not SAM interface
@Nullable
public static PsiMethod getSamInterfaceMethod(@NotNull PsiClass psiClass) {
if (psiClass.hasModifierProperty(PsiModifier.PRIVATE)) { // TODO hacky
return null;
}
if (DescriptorResolverUtils.isKotlinClass(psiClass)) {
return null;
}
@@ -44,6 +44,8 @@ import org.jetbrains.jet.lang.resolve.name.FqNameBase;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
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.TypeUtils;
import javax.inject.Inject;
import java.util.ArrayList;
@@ -275,14 +277,42 @@ public final class JavaClassResolver {
PsiMethod samInterfaceMethod = MembersCache.getSamInterfaceMethod(psiClass);
if (samInterfaceMethod != null) {
SimpleFunctionDescriptor abstractMethod = functionResolver.resolveFunctionMutely(
psiClass, new PsiMethodWrapper(samInterfaceMethod), classDescriptor);
SimpleFunctionDescriptor abstractMethod = resolveFunctionOfSamInterface(psiClass, samInterfaceMethod, classDescriptor);
classDescriptor.setFunctionTypeForSamInterface(SingleAbstractMethodUtils.getFunctionTypeForAbstractMethod(abstractMethod));
}
return classDescriptor;
}
@NotNull
private SimpleFunctionDescriptor resolveFunctionOfSamInterface(
@NotNull PsiClass psiClass,
@NotNull PsiMethod samInterfaceMethod,
@NotNull ClassDescriptorFromJvmBytecode samInterface
) {
PsiClass methodContainer = samInterfaceMethod.getContainingClass();
assert methodContainer != null : "method container is null for " + methodContainer;
String containerQualifiedName = methodContainer.getQualifiedName();
assert containerQualifiedName != null : "qualified name is null for " + psiClass;
if (DescriptorUtils.getFQName(samInterface).getFqName().equals(containerQualifiedName)) {
SimpleFunctionDescriptor abstractMethod =
functionResolver.resolveFunctionMutely(new PsiMethodWrapper(samInterfaceMethod), samInterface);
assert abstractMethod != null : "couldn't resolve method " + samInterfaceMethod;
return abstractMethod;
}
else {
Set<JetType> supertypes = TypeUtils.getAllSupertypes(samInterface.getDefaultType());
for (JetType supertype : supertypes) {
List<CallableMemberDescriptor> abstractMembers = SingleAbstractMethodUtils.getAbstractMembers(supertype);
if (!abstractMembers.isEmpty()) {
return (SimpleFunctionDescriptor) abstractMembers.get(0);
}
}
throw new IllegalStateException("Couldn't find abstract method in supertypes " + supertypes);
}
}
private void cache(@NotNull FqNameBase fqName, @Nullable ClassDescriptor classDescriptor) {
if (classDescriptor == null) {
cacheNegativeValue(fqName);
@@ -92,10 +92,12 @@ public final class JavaFunctionResolver {
@Nullable
SimpleFunctionDescriptor resolveFunctionMutely(
@NotNull PsiClass psiClass, PsiMethodWrapper method,
@NotNull PsiMethodWrapper method,
@NotNull ClassOrNamespaceDescriptor ownerDescriptor
) {
return resolveMethodToFunctionDescriptor(psiClass, method, DeclarationOrigin.JAVA, ownerDescriptor, false);
PsiClass containingClass = method.getPsiMethod().getContainingClass();
assert containingClass != null : "containing class is null for " + method;
return resolveMethodToFunctionDescriptor(containingClass, method, DeclarationOrigin.JAVA, ownerDescriptor, false);
}
@Nullable
@@ -40,7 +40,7 @@ import static org.jetbrains.jet.lang.types.Variance.INVARIANT;
public class SingleAbstractMethodUtils {
@NotNull
private static List<CallableMemberDescriptor> getAbstractMembers(@NotNull JetType type) {
public static List<CallableMemberDescriptor> getAbstractMembers(@NotNull JetType type) {
List<CallableMemberDescriptor> abstractMembers = Lists.newArrayList();
for (DeclarationDescriptor member : type.getMemberScope().getAllDescriptors()) {
if (member instanceof CallableMemberDescriptor &&