Saving "SAM interface" mark when resolving Java class.

This commit is contained in:
Evgeny Gerashchenko
2013-04-12 22:52:17 +04:00
parent 0ae0941e43
commit 37eccdb01f
6 changed files with 36 additions and 24 deletions
@@ -30,15 +30,18 @@ import java.util.Collection;
* @see org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyClassDescriptor * @see org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyClassDescriptor
*/ */
public class ClassDescriptorFromJvmBytecode extends MutableClassDescriptorLite { public class ClassDescriptorFromJvmBytecode extends MutableClassDescriptorLite {
private final boolean isSamInterface;
private JavaClassNonStaticMembersScope scopeForConstructorResolve; private JavaClassNonStaticMembersScope scopeForConstructorResolve;
public ClassDescriptorFromJvmBytecode( public ClassDescriptorFromJvmBytecode(
@NotNull DeclarationDescriptor containingDeclaration, @NotNull DeclarationDescriptor containingDeclaration,
@NotNull ClassKind kind, @NotNull ClassKind kind,
boolean isInner boolean isInner,
boolean isSamInterface
) { ) {
super(containingDeclaration, kind, isInner); super(containingDeclaration, kind, isInner);
this.isSamInterface = isSamInterface;
} }
@@ -58,4 +61,8 @@ public class ClassDescriptorFromJvmBytecode extends MutableClassDescriptorLite {
public void setScopeForConstructorResolve(@NotNull JavaClassNonStaticMembersScope scopeForConstructorResolve) { public void setScopeForConstructorResolve(@NotNull JavaClassNonStaticMembersScope scopeForConstructorResolve) {
this.scopeForConstructorResolve = scopeForConstructorResolve; this.scopeForConstructorResolve = scopeForConstructorResolve;
} }
public boolean isSamInterface() {
return isSamInterface;
}
} }
@@ -336,7 +336,10 @@ public final class MembersCache {
} }
public static boolean isSamInterface(@NotNull PsiClass psiClass) { public static boolean isSamInterface(@NotNull PsiClass psiClass) {
if (!psiClass.isInterface()) { if (DescriptorResolverUtils.isKotlinClass(psiClass)) {
return false;
}
if (!psiClass.isInterface() || psiClass.isAnnotationType()) {
return false; return false;
} }
@@ -26,11 +26,9 @@ import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.java.DescriptorResolverUtils; import org.jetbrains.jet.lang.resolve.java.DescriptorResolverUtils;
import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices; import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode; import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode;
import org.jetbrains.jet.lang.resolve.java.kt.JetClassObjectAnnotation; import org.jetbrains.jet.lang.resolve.java.kt.JetClassObjectAnnotation;
import org.jetbrains.jet.lang.resolve.java.provider.ClassPsiDeclarationProvider; import org.jetbrains.jet.lang.resolve.java.provider.ClassPsiDeclarationProvider;
import org.jetbrains.jet.lang.resolve.java.provider.PsiDeclarationProviderFactory;
import org.jetbrains.jet.lang.resolve.java.scope.JavaClassNonStaticMembersScope; import org.jetbrains.jet.lang.resolve.java.scope.JavaClassNonStaticMembersScope;
import org.jetbrains.jet.lang.resolve.java.wrapper.PsiClassWrapper; import org.jetbrains.jet.lang.resolve.java.wrapper.PsiClassWrapper;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
@@ -102,7 +100,7 @@ public final class JavaClassObjectResolver {
FqName fqName = new FqName(qualifiedName); FqName fqName = new FqName(qualifiedName);
ClassPsiDeclarationProvider classObjectData = semanticServices.getPsiDeclarationProviderFactory().createBinaryClassData(classObjectPsiClass); ClassPsiDeclarationProvider classObjectData = semanticServices.getPsiDeclarationProviderFactory().createBinaryClassData(classObjectPsiClass);
ClassDescriptorFromJvmBytecode classObjectDescriptor ClassDescriptorFromJvmBytecode classObjectDescriptor
= new ClassDescriptorFromJvmBytecode(containing, ClassKind.CLASS_OBJECT, false); = new ClassDescriptorFromJvmBytecode(containing, ClassKind.CLASS_OBJECT, false, false);
classObjectDescriptor.setSupertypes(supertypesResolver.getSupertypes(classObjectDescriptor, classObjectDescriptor.setSupertypes(supertypesResolver.getSupertypes(classObjectDescriptor,
new PsiClassWrapper(classObjectPsiClass), new PsiClassWrapper(classObjectPsiClass),
classObjectData, classObjectData,
@@ -131,7 +129,7 @@ public final class JavaClassObjectResolver {
) { ) {
FqNameUnsafe fqName = DescriptorResolverUtils.getFqNameForClassObject(psiClass); FqNameUnsafe fqName = DescriptorResolverUtils.getFqNameForClassObject(psiClass);
ClassDescriptorFromJvmBytecode classObjectDescriptor = ClassDescriptorFromJvmBytecode classObjectDescriptor =
new ClassDescriptorFromJvmBytecode(containing, ClassKind.CLASS_OBJECT, false); new ClassDescriptorFromJvmBytecode(containing, ClassKind.CLASS_OBJECT, false, false);
ClassPsiDeclarationProvider data = semanticServices.getPsiDeclarationProviderFactory().createSyntheticClassObjectClassData(psiClass); ClassPsiDeclarationProvider data = semanticServices.getPsiDeclarationProviderFactory().createSyntheticClassObjectClassData(psiClass);
setUpClassObjectDescriptor(classObjectDescriptor, containing, fqName, data, getClassObjectName(containing.getName().getName())); setUpClassObjectDescriptor(classObjectDescriptor, containing, fqName, data, getClassObjectName(containing.getName().getName()));
return classObjectDescriptor; return classObjectDescriptor;
@@ -33,6 +33,7 @@ import org.jetbrains.jet.lang.resolve.java.*;
import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode; import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode;
import org.jetbrains.jet.lang.resolve.java.kt.JetClassAnnotation; import org.jetbrains.jet.lang.resolve.java.kt.JetClassAnnotation;
import org.jetbrains.jet.lang.resolve.java.provider.ClassPsiDeclarationProvider; import org.jetbrains.jet.lang.resolve.java.provider.ClassPsiDeclarationProvider;
import org.jetbrains.jet.lang.resolve.java.provider.MembersCache;
import org.jetbrains.jet.lang.resolve.java.scope.JavaClassNonStaticMembersScope; import org.jetbrains.jet.lang.resolve.java.scope.JavaClassNonStaticMembersScope;
import org.jetbrains.jet.lang.resolve.java.wrapper.PsiClassWrapper; import org.jetbrains.jet.lang.resolve.java.wrapper.PsiClassWrapper;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
@@ -227,8 +228,8 @@ public final class JavaClassResolver {
ClassKind kind = getClassKind(psiClass, jetClassAnnotation); ClassKind kind = getClassKind(psiClass, jetClassAnnotation);
ClassPsiDeclarationProvider classData = semanticServices.getPsiDeclarationProviderFactory().createBinaryClassData(psiClass); ClassPsiDeclarationProvider classData = semanticServices.getPsiDeclarationProviderFactory().createBinaryClassData(psiClass);
ClassDescriptorFromJvmBytecode classDescriptor = new ClassDescriptorFromJvmBytecode(containingDeclaration, kind, ClassDescriptorFromJvmBytecode classDescriptor = new ClassDescriptorFromJvmBytecode(
isInnerClass(psiClass)); containingDeclaration, kind, isInnerClass(psiClass), MembersCache.isSamInterface(psiClass));
cache(javaClassToKotlinFqName(fqName), classDescriptor); cache(javaClassToKotlinFqName(fqName), classDescriptor);
classDescriptor.setName(Name.identifier(psiClass.getName())); classDescriptor.setName(Name.identifier(psiClass.getName()));
@@ -357,7 +357,7 @@ public final class JavaFunctionResolver {
PsiClass samInterface = namedMembers.getSamInterface(); PsiClass samInterface = namedMembers.getSamInterface();
if (samInterface != null) { if (samInterface != null) {
ClassDescriptor klass = findClassInNamespace(ownerDescriptor, namedMembers.getName()); ClassDescriptor klass = findClassInNamespace(ownerDescriptor, namedMembers.getName());
if (klass != null && SingleAbstractMethodUtils.isSamInterface(klass)) { if (klass != null) {
SimpleFunctionDescriptor constructorFunction = SingleAbstractMethodUtils.createSamConstructorFunction(ownerDescriptor, SimpleFunctionDescriptor constructorFunction = SingleAbstractMethodUtils.createSamConstructorFunction(ownerDescriptor,
klass); klass);
trace.record(BindingContext.SAM_CONSTRUCTOR_TO_INTERFACE, constructorFunction, klass); trace.record(BindingContext.SAM_CONSTRUCTOR_TO_INTERFACE, constructorFunction, klass);
@@ -36,21 +36,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
public class SingleAbstractMethodUtils { public class SingleAbstractMethodUtils {
public static boolean isSamInterface(@NotNull ClassDescriptor klass) {
if (klass.getKind() != ClassKind.TRAIT) {
return false;
}
List<CallableMemberDescriptor> abstractMembers = getAbstractMembers(klass.getDefaultType());
if (abstractMembers.size() == 1) {
CallableMemberDescriptor member = abstractMembers.get(0);
if (member instanceof SimpleFunctionDescriptor) {
return member.getTypeParameters().isEmpty();
}
}
return false;
}
@NotNull @NotNull
private static List<CallableMemberDescriptor> getAbstractMembers(@NotNull JetType type) { private static List<CallableMemberDescriptor> getAbstractMembers(@NotNull JetType type) {
List<CallableMemberDescriptor> abstractMembers = Lists.newArrayList(); List<CallableMemberDescriptor> abstractMembers = Lists.newArrayList();
@@ -73,10 +58,28 @@ public class SingleAbstractMethodUtils {
return KotlinBuiltIns.getInstance().getFunctionType(Collections.<AnnotationDescriptor>emptyList(), null, parameterTypes, returnType); return KotlinBuiltIns.getInstance().getFunctionType(Collections.<AnnotationDescriptor>emptyList(), null, parameterTypes, returnType);
} }
private static boolean isSamInterface(@NotNull ClassDescriptor klass) {
if (klass.getKind() != ClassKind.TRAIT) {
return false;
}
List<CallableMemberDescriptor> abstractMembers = getAbstractMembers(klass.getDefaultType());
if (abstractMembers.size() == 1) {
CallableMemberDescriptor member = abstractMembers.get(0);
if (member instanceof SimpleFunctionDescriptor) {
return member.getTypeParameters().isEmpty();
}
}
return false;
}
@NotNull
public static SimpleFunctionDescriptor createSamConstructorFunction( public static SimpleFunctionDescriptor createSamConstructorFunction(
@NotNull ClassOrNamespaceDescriptor owner, @NotNull ClassOrNamespaceDescriptor owner,
@NotNull ClassDescriptor samInterface @NotNull ClassDescriptor samInterface
) { ) {
assert isSamInterface(samInterface) : samInterface;
SimpleFunctionDescriptorImpl result = new SimpleFunctionDescriptorImpl( SimpleFunctionDescriptorImpl result = new SimpleFunctionDescriptorImpl(
owner, owner,
samInterface.getAnnotations(), samInterface.getAnnotations(),