Fixed loading SAM interfaces when they inherit abstract methods.
This commit is contained in:
committed by
Natalia.Ukhorskaya
parent
cdb096035b
commit
19e1331c11
-3
@@ -409,9 +409,6 @@ public final class MembersCache {
|
|||||||
// Returns null if not SAM interface
|
// Returns null if not SAM interface
|
||||||
@Nullable
|
@Nullable
|
||||||
public static PsiMethod getSamInterfaceMethod(@NotNull PsiClass psiClass) {
|
public static PsiMethod getSamInterfaceMethod(@NotNull PsiClass psiClass) {
|
||||||
if (psiClass.hasModifierProperty(PsiModifier.PRIVATE)) { // TODO hacky
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (DescriptorResolverUtils.isKotlinClass(psiClass)) {
|
if (DescriptorResolverUtils.isKotlinClass(psiClass)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
+32
-2
@@ -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.FqNameUnsafe;
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
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 javax.inject.Inject;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -275,14 +277,42 @@ public final class JavaClassResolver {
|
|||||||
|
|
||||||
PsiMethod samInterfaceMethod = MembersCache.getSamInterfaceMethod(psiClass);
|
PsiMethod samInterfaceMethod = MembersCache.getSamInterfaceMethod(psiClass);
|
||||||
if (samInterfaceMethod != null) {
|
if (samInterfaceMethod != null) {
|
||||||
SimpleFunctionDescriptor abstractMethod = functionResolver.resolveFunctionMutely(
|
SimpleFunctionDescriptor abstractMethod = resolveFunctionOfSamInterface(psiClass, samInterfaceMethod, classDescriptor);
|
||||||
psiClass, new PsiMethodWrapper(samInterfaceMethod), classDescriptor);
|
|
||||||
classDescriptor.setFunctionTypeForSamInterface(SingleAbstractMethodUtils.getFunctionTypeForAbstractMethod(abstractMethod));
|
classDescriptor.setFunctionTypeForSamInterface(SingleAbstractMethodUtils.getFunctionTypeForAbstractMethod(abstractMethod));
|
||||||
}
|
}
|
||||||
|
|
||||||
return classDescriptor;
|
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) {
|
private void cache(@NotNull FqNameBase fqName, @Nullable ClassDescriptor classDescriptor) {
|
||||||
if (classDescriptor == null) {
|
if (classDescriptor == null) {
|
||||||
cacheNegativeValue(fqName);
|
cacheNegativeValue(fqName);
|
||||||
|
|||||||
+4
-2
@@ -92,10 +92,12 @@ public final class JavaFunctionResolver {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
SimpleFunctionDescriptor resolveFunctionMutely(
|
SimpleFunctionDescriptor resolveFunctionMutely(
|
||||||
@NotNull PsiClass psiClass, PsiMethodWrapper method,
|
@NotNull PsiMethodWrapper method,
|
||||||
@NotNull ClassOrNamespaceDescriptor ownerDescriptor
|
@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
|
@Nullable
|
||||||
|
|||||||
+1
-1
@@ -40,7 +40,7 @@ import static org.jetbrains.jet.lang.types.Variance.INVARIANT;
|
|||||||
public class SingleAbstractMethodUtils {
|
public class SingleAbstractMethodUtils {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static List<CallableMemberDescriptor> getAbstractMembers(@NotNull JetType type) {
|
public static List<CallableMemberDescriptor> getAbstractMembers(@NotNull JetType type) {
|
||||||
List<CallableMemberDescriptor> abstractMembers = Lists.newArrayList();
|
List<CallableMemberDescriptor> abstractMembers = Lists.newArrayList();
|
||||||
for (DeclarationDescriptor member : type.getMemberScope().getAllDescriptors()) {
|
for (DeclarationDescriptor member : type.getMemberScope().getAllDescriptors()) {
|
||||||
if (member instanceof CallableMemberDescriptor &&
|
if (member instanceof CallableMemberDescriptor &&
|
||||||
|
|||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
public interface SubstitutedSamInterface extends Comparator<String> {
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
public /*synthesized*/ fun SubstitutedSamInterface(/*0*/ function: (jet.String?, jet.String?) -> jet.Int): test.SubstitutedSamInterface
|
||||||
|
|
||||||
|
public trait SubstitutedSamInterface : java.util.Comparator<jet.String> {
|
||||||
|
public abstract override /*1*/ /*fake_override*/ fun compare(/*0*/ p0: jet.String?, /*1*/ p1: jet.String?): jet.Int
|
||||||
|
}
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
public interface SubstitutedSamInterfaceSubclassOfBuiltin extends Comparable<SubstitutedSamInterfaceSubclassOfBuiltin> {
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
public /*synthesized*/ fun SubstitutedSamInterfaceSubclassOfBuiltin(/*0*/ function: (test.SubstitutedSamInterfaceSubclassOfBuiltin) -> jet.Int): test.SubstitutedSamInterfaceSubclassOfBuiltin
|
||||||
|
|
||||||
|
public trait SubstitutedSamInterfaceSubclassOfBuiltin : jet.Comparable<test.SubstitutedSamInterfaceSubclassOfBuiltin> {
|
||||||
|
public abstract override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: test.SubstitutedSamInterfaceSubclassOfBuiltin): jet.Int
|
||||||
|
}
|
||||||
@@ -1218,6 +1218,16 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
|
|||||||
doTestCompiledJava("compiler/testData/loadJava/compiledJava/singleAbstractMethod/Runnable.java");
|
doTestCompiledJava("compiler/testData/loadJava/compiledJava/singleAbstractMethod/Runnable.java");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("SubstitutedSamInterface.java")
|
||||||
|
public void testSubstitutedSamInterface() throws Exception {
|
||||||
|
doTestCompiledJava("compiler/testData/loadJava/compiledJava/singleAbstractMethod/SubstitutedSamInterface.java");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("SubstitutedSamInterfaceSubclassOfBuiltin.java")
|
||||||
|
public void testSubstitutedSamInterfaceSubclassOfBuiltin() throws Exception {
|
||||||
|
doTestCompiledJava("compiler/testData/loadJava/compiledJava/singleAbstractMethod/SubstitutedSamInterfaceSubclassOfBuiltin.java");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/loadJava/compiledJava/singleAbstractMethod/adapter")
|
@TestMetadata("compiler/testData/loadJava/compiledJava/singleAbstractMethod/adapter")
|
||||||
public static class Adapter extends AbstractLoadJavaTest {
|
public static class Adapter extends AbstractLoadJavaTest {
|
||||||
public void testAllFilesPresentInAdapter() throws Exception {
|
public void testAllFilesPresentInAdapter() throws Exception {
|
||||||
|
|||||||
+5
@@ -130,6 +130,11 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso
|
|||||||
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/class/InheritClassWithParam.kt");
|
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/class/InheritClassWithParam.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("InheritSubstitutedMethod.kt")
|
||||||
|
public void testInheritSubstitutedMethod() throws Exception {
|
||||||
|
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/class/InheritSubstitutedMethod.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("InheritTraitWithParam.kt")
|
@TestMetadata("InheritTraitWithParam.kt")
|
||||||
public void testInheritTraitWithParam() throws Exception {
|
public void testInheritTraitWithParam() throws Exception {
|
||||||
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/class/InheritTraitWithParam.kt");
|
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/class/InheritTraitWithParam.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user