From e0fae55ee4c5498d0e38c724a1f6286a06ffa45f Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Wed, 22 Feb 2012 22:11:08 +0400 Subject: [PATCH] read kotlin class objects from binary classes --- .../codegen/ImplementationBodyCodegen.java | 8 ++- .../jetbrains/jet/codegen/JetTypeMapper.java | 4 +- .../resolve/java/JavaDescriptorResolver.java | 55 +++++++++++++++---- .../jet/lang/resolve/java/JvmAbi.java | 2 + .../classObject/ClassObjectDeclaresVal.kt | 7 +++ .../classObject/ClassObjectDeclaresVal.txt | 9 +++ .../classObject/ClassObjectDeclaresVar.kt | 7 +++ .../classObject/ClassObjectDeclaresVar.txt | 9 +++ .../classObject/ClassObjectExtendsTrait.kt | 8 +++ .../classObject/ClassObjectExtendsTrait.txt | 10 ++++ .../ClassObjectExtendsTraitWithTP.kt | 8 +++ .../ClassObjectExtendsTraitWithTP.txt | 10 ++++ .../classObject/SimpleClassObject.kt | 6 ++ .../classObject/SimpleClassObject.txt | 8 +++ .../jet/compiler/NamespaceComparator.java | 3 +- 15 files changed, 140 insertions(+), 14 deletions(-) create mode 100644 compiler/testData/readKotlinBinaryClass/classObject/ClassObjectDeclaresVal.kt create mode 100644 compiler/testData/readKotlinBinaryClass/classObject/ClassObjectDeclaresVal.txt create mode 100644 compiler/testData/readKotlinBinaryClass/classObject/ClassObjectDeclaresVar.kt create mode 100644 compiler/testData/readKotlinBinaryClass/classObject/ClassObjectDeclaresVar.txt create mode 100644 compiler/testData/readKotlinBinaryClass/classObject/ClassObjectExtendsTrait.kt create mode 100644 compiler/testData/readKotlinBinaryClass/classObject/ClassObjectExtendsTrait.txt create mode 100644 compiler/testData/readKotlinBinaryClass/classObject/ClassObjectExtendsTraitWithTP.kt create mode 100644 compiler/testData/readKotlinBinaryClass/classObject/ClassObjectExtendsTraitWithTP.txt create mode 100644 compiler/testData/readKotlinBinaryClass/classObject/SimpleClassObject.kt create mode 100644 compiler/testData/readKotlinBinaryClass/classObject/SimpleClassObject.txt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 25d4cc0ddac..d922e88cc3b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -135,9 +135,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { v.visitInnerClass(innerClassInternalName, outerClassInernalName, innerClass.getName(), innerClassAccess); } + if (descriptor.getClassObjectDescriptor() != null) { + int innerClassAccess = ACC_PUBLIC | ACC_FINAL | ACC_STATIC; + String outerClassInernalName = typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(); + v.visitInnerClass(outerClassInernalName + JvmAbi.CLASS_OBJECT_SUFFIX, outerClassInernalName, JvmAbi.CLASS_OBJECT_CLASS_NAME, innerClassAccess); + } + AnnotationCodegen.forClass(v.getVisitor()).genAnnotations(descriptor, typeMapper); - if(myClass instanceof JetClass && signature.getKotlinGenericSignature() != null) { + if (signature.getKotlinGenericSignature() != null) { AnnotationVisitor annotationVisitor = v.newAnnotation(myClass, JvmStdlibNames.JET_CLASS.getDescriptor(), true); annotationVisitor.visit(JvmStdlibNames.JET_CLASS_SIGNATURE, signature.getKotlinGenericSignature()); annotationVisitor.visitEnd(); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 6538bc15a06..4ab7089bfad 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -170,7 +170,7 @@ public class JetTypeMapper { public static String getLocalNameForObject(JetObjectDeclaration object) { PsiElement parent = object.getParent(); if (parent instanceof JetClassObject) { - return "ClassObject$"; + return JvmAbi.CLASS_OBJECT_CLASS_NAME; } return null; @@ -755,7 +755,7 @@ public class JetTypeMapper { ClassDescriptor myClass = bindingContext.get(BindingContext.CLASS, expression); if(CodegenUtil.isClassObject(myClass)) { - return mapType(aClass.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName() + "$ClassObject$"; + return mapType(aClass.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName() + JvmAbi.CLASS_OBJECT_SUFFIX; } else baseName = classNameForAnonymousClass((JetElement) container); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index 6a7c3a07992..e4558848197 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -31,6 +31,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.psi.JetPsiUtil; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.OverrideResolver; @@ -406,8 +407,10 @@ public class JavaDescriptorResolver { } } - // TODO - //classData.classDescriptor.setClassObjectDescriptor(createClassObjectDescriptor(classData.classDescriptor)); + MutableClassDescriptorLite classObject = createClassObjectDescriptor(classData.classDescriptor, psiClass); + if (classObject != null) { + classData.classDescriptor.setClassObjectDescriptor(classObject); + } semanticServices.getTrace().record(BindingContext.CLASS, psiClass, classData.classDescriptor); @@ -420,19 +423,47 @@ public class JavaDescriptorResolver { } } + @Nullable + private PsiClass getInnerClassClassObject(@NotNull PsiClass outer) { + for (PsiClass inner : outer.getInnerClasses()) { + if (inner.getName().equals(JvmAbi.CLASS_OBJECT_CLASS_NAME)) { + return inner; + } + } + return null; + } + /** * TODO * @see #createJavaNamespaceDescriptor(com.intellij.psi.PsiClass) */ @Nullable private MutableClassDescriptorLite createClassObjectDescriptor(@NotNull ClassDescriptor containing, @NotNull PsiClass psiClass) { - MutableClassDescriptorLite classObjectDescriptor = new MutableClassDescriptorLite(containing, ClassKind.OBJECT); - classObjectDescriptor.setName(""); // TODO - classObjectDescriptor.setModality(Modality.FINAL); - classObjectDescriptor.setTypeParameterDescriptors(new ArrayList(0)); - classObjectDescriptor.createTypeConstructor(); - classObjectDescriptor.setScopeForMemberLookup(new JavaClassMembersScope(classObjectDescriptor, psiClass, semanticServices, true)); - return classObjectDescriptor; + PsiClass classObjectPsiClass = getInnerClassClassObject(psiClass); + if (classObjectPsiClass == null) { + return null; + } + + ResolverBinaryClassData classData = new ResolverBinaryClassData(); + classData.kotlin = true; + classData.classDescriptor = new MutableClassDescriptorLite(containing, ClassKind.OBJECT); + + classDescriptorCache.put(classObjectPsiClass.getQualifiedName(), classData); + + classData.classDescriptor.setSupertypes(getSupertypes(new PsiClassWrapper(classObjectPsiClass), classData.classDescriptor, new ArrayList(0))); + classData.classDescriptor.setName(JetPsiUtil.NO_NAME_PROVIDED); // TODO + classData.classDescriptor.setModality(Modality.FINAL); + classData.classDescriptor.setTypeParameterDescriptors(new ArrayList(0)); + classData.classDescriptor.createTypeConstructor(); + classData.classDescriptor.setScopeForMemberLookup(new JavaClassMembersScope(classData.classDescriptor, classObjectPsiClass, semanticServices, false)); + + // TODO: wrong: class objects do not need visible constructors + ConstructorDescriptorImpl constructor = new ConstructorDescriptorImpl(classData.classDescriptor, new ArrayList(0), true); + constructor.setReturnType(classData.classDescriptor.getDefaultType()); + constructor.initialize(new ArrayList(0), new ArrayList(0), Visibility.PUBLIC); + + classData.classDescriptor.addConstructor(constructor, null); + return classData.classDescriptor; } private List createUninitializedClassTypeParameters(PsiClass psiClass, ResolverBinaryClassData classData, TypeVariableResolver typeVariableResolver) { @@ -679,7 +710,7 @@ public class JavaDescriptorResolver { } } - private Collection getSupertypes(PsiClassWrapper psiClass, ClassDescriptor classDescriptor, List typeParameters) { + private Collection getSupertypes(PsiClassWrapper psiClass, ClassDescriptor classDescriptor, List typeParameters) { final List result = new ArrayList(); if (psiClass.getJetClass().signature().length() > 0) { @@ -1271,6 +1302,7 @@ public class JavaDescriptorResolver { } private ResolverScopeData getResolverScopeData(@NotNull ClassOrNamespaceDescriptor owner, PsiClassWrapper psiClass) { + // TODO: store scopeData in Java*Scope ResolverScopeData scopeData; boolean staticMembers; if (owner instanceof JavaNamespaceDescriptor) { @@ -1576,6 +1608,9 @@ public class JavaDescriptorResolver { // TODO: hack against inner classes continue; } + if (innerPsiClass.getName().equals(JvmAbi.CLASS_OBJECT_CLASS_NAME)) { + continue; + } r.add(resolveClass(innerPsiClass)); } return r; diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JvmAbi.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JvmAbi.java index eaddd5caefa..35498eeba7e 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JvmAbi.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JvmAbi.java @@ -25,6 +25,8 @@ public class JvmAbi { public static final String GETTER_PREFIX = "get"; public static final String SETTER_PREFIX = "set"; public static final String PACKAGE_CLASS = "namespace"; + public static final String CLASS_OBJECT_SUFFIX = "$ClassObject$"; + public static final String CLASS_OBJECT_CLASS_NAME = "ClassObject$"; public static final JvmClassName JETBRAINS_NOT_NULL_ANNOTATION = new JvmClassName("org.jetbrains.annotations.NotNull"); } diff --git a/compiler/testData/readKotlinBinaryClass/classObject/ClassObjectDeclaresVal.kt b/compiler/testData/readKotlinBinaryClass/classObject/ClassObjectDeclaresVal.kt new file mode 100644 index 00000000000..4a863e301ce --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/classObject/ClassObjectDeclaresVal.kt @@ -0,0 +1,7 @@ +package test + +class ClassObjectDeclaresProperty { + class object { + val i = 1 + } +} diff --git a/compiler/testData/readKotlinBinaryClass/classObject/ClassObjectDeclaresVal.txt b/compiler/testData/readKotlinBinaryClass/classObject/ClassObjectDeclaresVal.txt new file mode 100644 index 00000000000..e0cb10d368a --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/classObject/ClassObjectDeclaresVal.txt @@ -0,0 +1,9 @@ +namespace test + +final class test.ClassObjectDeclaresProperty : jet.Any { + final /*constructor*/ fun (): test.ClassObjectDeclaresProperty + final object test.ClassObjectDeclaresProperty. : jet.Any { + final /*constructor*/ fun (): test.ClassObjectDeclaresProperty. + val i: jet.Int + } +} diff --git a/compiler/testData/readKotlinBinaryClass/classObject/ClassObjectDeclaresVar.kt b/compiler/testData/readKotlinBinaryClass/classObject/ClassObjectDeclaresVar.kt new file mode 100644 index 00000000000..880b0e92a5a --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/classObject/ClassObjectDeclaresVar.kt @@ -0,0 +1,7 @@ +package test + +class ClassObjectDeclaresProperty { + class object { + var s = "" + } +} diff --git a/compiler/testData/readKotlinBinaryClass/classObject/ClassObjectDeclaresVar.txt b/compiler/testData/readKotlinBinaryClass/classObject/ClassObjectDeclaresVar.txt new file mode 100644 index 00000000000..c04002b38d8 --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/classObject/ClassObjectDeclaresVar.txt @@ -0,0 +1,9 @@ +namespace test + +final class test.ClassObjectDeclaresProperty : jet.Any { + final /*constructor*/ fun (): test.ClassObjectDeclaresProperty + final object test.ClassObjectDeclaresProperty. : jet.Any { + final /*constructor*/ fun (): test.ClassObjectDeclaresProperty. + var s: jet.String + } +} diff --git a/compiler/testData/readKotlinBinaryClass/classObject/ClassObjectExtendsTrait.kt b/compiler/testData/readKotlinBinaryClass/classObject/ClassObjectExtendsTrait.kt new file mode 100644 index 00000000000..dcdcaa91e49 --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/classObject/ClassObjectExtendsTrait.kt @@ -0,0 +1,8 @@ +package test + +trait Bbb + +class ClassObjectextendsTrait { + class object : Bbb { + } +} diff --git a/compiler/testData/readKotlinBinaryClass/classObject/ClassObjectExtendsTrait.txt b/compiler/testData/readKotlinBinaryClass/classObject/ClassObjectExtendsTrait.txt new file mode 100644 index 00000000000..ead6b9d20f6 --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/classObject/ClassObjectExtendsTrait.txt @@ -0,0 +1,10 @@ +namespace test + +abstract trait test.Bbb : jet.Any { +} +final class test.ClassObjectextendsTrait : jet.Any { + final /*constructor*/ fun (): test.ClassObjectextendsTrait + final object test.ClassObjectextendsTrait. : test.Bbb { + final /*constructor*/ fun (): test.ClassObjectextendsTrait. + } +} diff --git a/compiler/testData/readKotlinBinaryClass/classObject/ClassObjectExtendsTraitWithTP.kt b/compiler/testData/readKotlinBinaryClass/classObject/ClassObjectExtendsTraitWithTP.kt new file mode 100644 index 00000000000..c81c15fec2c --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/classObject/ClassObjectExtendsTraitWithTP.kt @@ -0,0 +1,8 @@ +package test + +trait Bbb

+ +class ClassObjectExtendsTraitWithTP { + class object : Bbb { + } +} diff --git a/compiler/testData/readKotlinBinaryClass/classObject/ClassObjectExtendsTraitWithTP.txt b/compiler/testData/readKotlinBinaryClass/classObject/ClassObjectExtendsTraitWithTP.txt new file mode 100644 index 00000000000..aaadf2d5e4f --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/classObject/ClassObjectExtendsTraitWithTP.txt @@ -0,0 +1,10 @@ +namespace test + +final class test.ClassObjectExtendsTraitWithTP : jet.Any { + final /*constructor*/ fun (): test.ClassObjectExtendsTraitWithTP + final object test.ClassObjectExtendsTraitWithTP. : test.Bbb { + final /*constructor*/ fun (): test.ClassObjectExtendsTraitWithTP. + } +} +abstract trait test.Bbb : jet.Any { +} diff --git a/compiler/testData/readKotlinBinaryClass/classObject/SimpleClassObject.kt b/compiler/testData/readKotlinBinaryClass/classObject/SimpleClassObject.kt new file mode 100644 index 00000000000..dcbab40afd8 --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/classObject/SimpleClassObject.kt @@ -0,0 +1,6 @@ +package test + +class SimpleClassObject() { + class object { + } +} diff --git a/compiler/testData/readKotlinBinaryClass/classObject/SimpleClassObject.txt b/compiler/testData/readKotlinBinaryClass/classObject/SimpleClassObject.txt new file mode 100644 index 00000000000..2c257b95113 --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/classObject/SimpleClassObject.txt @@ -0,0 +1,8 @@ +namespace test + +final class test.SimpleClassObject : jet.Any { + final /*constructor*/ fun (): test.SimpleClassObject + final object test.SimpleClassObject. : jet.Any { + final /*constructor*/ fun (): test.SimpleClassObject. + } +} diff --git a/compiler/tests/org/jetbrains/jet/compiler/NamespaceComparator.java b/compiler/tests/org/jetbrains/jet/compiler/NamespaceComparator.java index 73c590892fb..168a611c1ed 100644 --- a/compiler/tests/org/jetbrains/jet/compiler/NamespaceComparator.java +++ b/compiler/tests/org/jetbrains/jet/compiler/NamespaceComparator.java @@ -34,6 +34,7 @@ import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.psi.JetPsiUtil; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.JavaNamespaceDescriptor; import org.jetbrains.jet.lang.resolve.scopes.JetScope; @@ -316,7 +317,7 @@ class NamespaceComparator { sb.append(modality.name().toLowerCase()); } - public void serialize(JetType type) { + public void serialize(@NotNull JetType type) { serialize(type.getConstructor().getDeclarationDescriptor()); if (!type.getArguments().isEmpty()) { sb.append("<");