Treat anonymous objects as classes (ClassKind.CLASS)

They're not objects per se, i.e. they're not singletons
This commit is contained in:
Alexander Udalov
2013-10-25 20:55:16 +04:00
parent 27f832a713
commit 18c59d5495
10 changed files with 78 additions and 78 deletions
@@ -252,6 +252,10 @@ public class AsmUtil {
return NO_FLAG_PACKAGE_PRIVATE;
}
if (memberDescriptor instanceof ConstructorDescriptor) {
if (isAnonymousObject(containingDeclaration)) {
return NO_FLAG_PACKAGE_PRIVATE;
}
ClassKind kind = ((ClassDescriptor) containingDeclaration).getKind();
if (kind == ClassKind.OBJECT) {
return NO_FLAG_PACKAGE_PRIVATE;
@@ -34,8 +34,6 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl;
import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.lang.psi.JetObjectDeclaration;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil;
import org.jetbrains.jet.lang.resolve.name.Name;
@@ -87,10 +85,6 @@ public class CodegenUtil {
return invokeDescriptor;
}
public static boolean isNonLiteralObject(JetClassOrObject myClass) {
return myClass instanceof JetObjectDeclaration && !((JetObjectDeclaration) myClass).isObjectLiteral();
}
public static String createTmpVariableName(Collection<String> existingNames) {
String prefix = "tmp";
int i = RANDOM.nextInt(Integer.MAX_VALUE);
@@ -1028,35 +1028,35 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.load(0, OBJECT_TYPE);
}
for (int paramIndex = 0; paramIndex < argTypes.length; paramIndex++) {
Type argType = argTypes[paramIndex];
for (Type argType : argTypes) {
iv.load(reg, argType);
//noinspection AssignmentToForLoopParameter
reg += argType.getSize();
}
callableMethod.invokeWithoutAssertions(iv);
}
private void generateFieldForSingleton() {
boolean hasClassObject = descriptor.getClassObjectDescriptor() != null;
boolean isEnumClass = DescriptorUtils.isEnumClass(descriptor);
boolean isObjectDeclaration = descriptor.getKind() == ClassKind.OBJECT && isNonLiteralObject(myClass) ;
if (isEnumClass(descriptor)) return;
if (!isObjectDeclaration && !hasClassObject || isEnumClass) return;
ClassDescriptor fieldTypeDescriptor = hasClassObject ? descriptor.getClassObjectDescriptor() : descriptor;
assert fieldTypeDescriptor != null;
StackValue.Field field = StackValue.singleton(fieldTypeDescriptor, typeMapper);
ClassDescriptor classObjectDescriptor = descriptor.getClassObjectDescriptor();
ClassDescriptor fieldTypeDescriptor;
JetClassOrObject original;
if (hasClassObject) {
if (isObject(descriptor)) {
original = myClass;
fieldTypeDescriptor = descriptor;
}
else if (classObjectDescriptor != null) {
JetClassObject classObject = ((JetClass) myClass).getClassObject();
assert classObject != null : myClass.getText();
assert classObject != null : "Class object not found: " + myClass.getText();
original = classObject.getObjectDeclaration();
fieldTypeDescriptor = classObjectDescriptor;
}
else {
original = myClass;
return;
}
StackValue.Field field = StackValue.singleton(fieldTypeDescriptor, typeMapper);
v.newField(original, ACC_PUBLIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null);
if (!AsmUtil.isClassObjectWithBackingFieldsInOuter(fieldTypeDescriptor)) {
@@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.impl.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.name.SpecialNames;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.RedeclarationHandler;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
@@ -478,11 +479,18 @@ public class TypeHierarchyResolver {
@Override
public void visitObjectDeclaration(@NotNull JetObjectDeclaration declaration) {
MutableClassDescriptor objectDescriptor =
createClassDescriptorForObject(declaration, owner, outerScope, JetPsiUtil.safeName(declaration.getName()),
ClassKind.OBJECT);
owner.addObjectDescriptor(objectDescriptor);
trace.record(FQNAME_TO_CLASS_DESCRIPTOR, JetPsiUtil.getFQName(declaration), objectDescriptor);
if (declaration.isObjectLiteral()) {
MutableClassDescriptor descriptor =
createClassDescriptorForObject(declaration, SpecialNames.NO_NAME_PROVIDED, ClassKind.CLASS);
context.getClasses().put(declaration, descriptor);
return;
}
MutableClassDescriptor descriptor =
createClassDescriptorForObject(declaration, JetPsiUtil.safeName(declaration.getName()), ClassKind.OBJECT);
context.getObjects().put(declaration, descriptor);
owner.addObjectDescriptor(descriptor);
trace.record(FQNAME_TO_CLASS_DESCRIPTOR, JetPsiUtil.getFQName(declaration), descriptor);
}
@Override
@@ -504,11 +512,10 @@ public class TypeHierarchyResolver {
public void visitClassObject(@NotNull JetClassObject classObject) {
JetObjectDeclaration objectDeclaration = classObject.getObjectDeclaration();
if (objectDeclaration != null) {
Name classObjectName = getClassObjectName(owner.getOwnerForChildren().getName());
MutableClassDescriptor classObjectDescriptor = createClassDescriptorForObject(
objectDeclaration, owner, outerScope,
classObjectName, ClassKind.CLASS_OBJECT);
MutableClassDescriptor classObjectDescriptor =
createClassDescriptorForObject(objectDeclaration, getClassObjectName(owner.getOwnerForChildren().getName()),
ClassKind.CLASS_OBJECT);
context.getObjects().put(objectDeclaration, classObjectDescriptor);
NamespaceLikeBuilder.ClassObjectStatus status = owner.setClassObjectDescriptor(classObjectDescriptor);
switch (status) {
@@ -571,21 +578,17 @@ public class TypeHierarchyResolver {
@NotNull
private MutableClassDescriptor createClassDescriptorForObject(
@NotNull JetObjectDeclaration declaration, @NotNull NamespaceLikeBuilder owner,
@NotNull JetScope scope, @NotNull Name name, @NotNull ClassKind kind
@NotNull JetObjectDeclaration declaration,
@NotNull Name name,
@NotNull ClassKind kind
) {
MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor(
owner.getOwnerForChildren(), scope, kind, false, name);
MutableClassDescriptor descriptor = new MutableClassDescriptor(owner.getOwnerForChildren(), outerScope, kind, false, name);
context.getObjects().put(declaration, mutableClassDescriptor);
prepareForDeferredCall(descriptor.getScopeForMemberResolution(), descriptor, declaration);
JetScope classScope = mutableClassDescriptor.getScopeForMemberResolution();
prepareForDeferredCall(classScope, mutableClassDescriptor, declaration);
createPrimaryConstructorForObject(declaration, mutableClassDescriptor);
trace.record(BindingContext.CLASS, declaration, mutableClassDescriptor);
return mutableClassDescriptor;
createPrimaryConstructorForObject(declaration, descriptor);
trace.record(BindingContext.CLASS, declaration, descriptor);
return descriptor;
}
private MutableClassDescriptor createClassDescriptorForEnumEntry(
@@ -0,0 +1,7 @@
class Foo {
val x = object { }
}
// TESTED_OBJECT_KIND: class
// TESTED_OBJECTS: Foo$x$1
// FLAGS: ACC_PUBLIC, ACC_FINAL, ACC_SUPER
@@ -50,6 +50,11 @@ public class WriteFlagsTestGenerated extends AbstractWriteFlagsTest {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/writeFlags/class/accessFlags"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("objectLiteral.kt")
public void testObjectLiteral() throws Exception {
doTest("compiler/testData/writeFlags/class/accessFlags/objectLiteral.kt");
}
@TestMetadata("publicFinalClass.kt")
public void testPublicFinalClass() throws Exception {
doTest("compiler/testData/writeFlags/class/accessFlags/publicFinalClass.kt");
@@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.name.SpecialNames;
import org.jetbrains.jet.lang.resolve.scopes.FilteringScope;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.*;
@@ -230,8 +231,12 @@ public class DescriptorUtils {
return isKindOf(descriptor, ClassKind.CLASS_OBJECT);
}
public static boolean isAnonymousObject(@NotNull ClassifierDescriptor descriptor) {
return isKindOf(descriptor, ClassKind.OBJECT) && descriptor.getName().isSpecial();
public static boolean isAnonymousObject(@NotNull DeclarationDescriptor descriptor) {
return isClass(descriptor) && descriptor.getName().equals(SpecialNames.NO_NAME_PROVIDED);
}
public static boolean isObject(@NotNull DeclarationDescriptor descriptor) {
return isKindOf(descriptor, ClassKind.OBJECT);
}
public static boolean isEnumEntry(@NotNull DeclarationDescriptor descriptor) {
@@ -325,10 +330,7 @@ public class DescriptorUtils {
@NotNull
public static Visibility getDefaultConstructorVisibility(@NotNull ClassDescriptor classDescriptor) {
ClassKind classKind = classDescriptor.getKind();
if (classKind == ClassKind.ENUM_CLASS) {
return Visibilities.PRIVATE;
}
if (classKind.isSingleton()) {
if (classKind == ClassKind.ENUM_CLASS || classKind.isSingleton() || isAnonymousObject(classDescriptor)) {
return Visibilities.PRIVATE;
}
assert classKind == ClassKind.CLASS || classKind == ClassKind.TRAIT || classKind == ClassKind.ANNOTATION_CLASS;
@@ -19,12 +19,13 @@ package org.jetbrains.k2js.translate.context;
import com.google.dart.compiler.backend.js.ast.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassKind;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.plugin.JetLanguage;
import java.util.List;
import static org.jetbrains.jet.lang.descriptors.ClassKind.TRAIT;
/**
* Encapuslates different types of constants and naming conventions.
@@ -267,19 +268,17 @@ public final class Namer {
}
@NotNull
public JsInvocation classCreateInvocation(@NotNull ClassDescriptor descriptor, @NotNull List<JsExpression> arguments) {
switch (descriptor.getKind()) {
case TRAIT:
return new JsInvocation(traitCreationMethodReference(), arguments);
case OBJECT:
case CLASS_OBJECT:
case ENUM_ENTRY:
return new JsInvocation(objectCreationMethodReference(), arguments);
default:
return new JsInvocation(classCreationMethodReference(), arguments);
public JsExpression classCreateInvocation(@NotNull ClassDescriptor descriptor) {
ClassKind kind = descriptor.getKind();
if (kind == TRAIT) {
return traitCreationMethodReference();
}
if (kind.isSingleton() || DescriptorUtils.isAnonymousObject(descriptor)) {
return objectCreationMethodReference();
}
return classCreationMethodReference();
}
@NotNull
@@ -37,8 +37,7 @@ import org.jetbrains.k2js.translate.utils.JsAstUtils;
import java.util.*;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getClassDescriptorForType;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getClassDescriptorForTypeConstructor;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
import static org.jetbrains.jet.lang.types.TypeUtils.topologicallySortSuperclassesAndRecordAllInstances;
import static org.jetbrains.k2js.translate.expression.LiteralFunctionTranslator.createPlace;
import static org.jetbrains.k2js.translate.initializer.InitializerUtils.createClassObjectInitializer;
@@ -121,7 +120,7 @@ public final class ClassTranslator extends AbstractTranslator {
@NotNull
public JsInvocation translate(@NotNull TranslationContext declarationContext) {
return context().namer().classCreateInvocation(descriptor, getClassCreateInvocationArguments(declarationContext));
return new JsInvocation(context().namer().classCreateInvocation(descriptor), getClassCreateInvocationArguments(declarationContext));
}
private boolean isTrait() {
@@ -138,7 +137,7 @@ public final class ClassTranslator extends AbstractTranslator {
if (!isTopLevelDeclaration) {
qualifiedReference = null;
}
else if (descriptor.getKind().isSingleton()) {
else if (descriptor.getKind().isSingleton() || isAnonymousObject(descriptor)) {
qualifiedReference = null;
declarationContext.literalFunctionTranslator().setDefinitionPlace(
new NotNullLazyValue<Trinity<List<JsPropertyInitializer>, LabelGenerator, JsExpression>>() {
@@ -19,7 +19,6 @@ package org.jetbrains.k2js.translate.utils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassKind;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
@@ -29,8 +28,6 @@ import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getContaining
public final class AnnotationsUtils {
private static final String ENUMERABLE = "js.enumerable";
private AnnotationsUtils() {
}
@@ -108,16 +105,6 @@ public final class AnnotationsUtils {
return hasAnnotationOrInsideAnnotatedClass(descriptor, PredefinedAnnotation.NATIVE);
}
public static boolean isEnumerable(@NotNull DeclarationDescriptor descriptor) {
if (getAnnotationByName(descriptor, ENUMERABLE) != null) {
return true;
}
ClassDescriptor containingClass = getContainingClass(descriptor);
return containingClass != null &&
((containingClass.getKind().equals(ClassKind.OBJECT) && containingClass.getName().isSpecial()) ||
getAnnotationByName(containingClass, ENUMERABLE) != null);
}
public static boolean isLibraryObject(@NotNull DeclarationDescriptor descriptor) {
return hasAnnotationOrInsideAnnotatedClass(descriptor, PredefinedAnnotation.LIBRARY);
}