Rework class objects

Class objects have name "Default" by default
Do not produce synthetic class objects
Class objects have new semantics:
    class "A" has class object "B" if literal "A" can be used as a value of type "B"
Class objects act like ordinary nested objects
    i.e. are accessible from class scope via getClassifier()
Jvm backend: class object fields and class have the name of class object ("Default")
	as opposed to special "OBJECT$" and "object"
Serialization: only the name of class object is needed to serialize data
This commit is contained in:
Pavel V. Talanov
2015-01-14 15:34:33 +03:00
parent 4b6112d380
commit 0343fd8fc7
39 changed files with 254 additions and 1728 deletions
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.load.java;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.name.SpecialNames;
public final class JvmAbi {
/**
@@ -35,7 +36,7 @@ public final class JvmAbi {
public static final String GETTER_PREFIX = "get";
public static final String SETTER_PREFIX = "set";
public static final String CLASS_OBJECT_CLASS_NAME = "object";
public static final String CLASS_OBJECT_CLASS_NAME = SpecialNames.DEFAULT_NAME_FOR_DEFAULT_OBJECT.asString();
public static final String CLASS_OBJECT_SUFFIX = "$" + CLASS_OBJECT_CLASS_NAME;
public static final String DELEGATED_PROPERTY_NAME_SUFFIX = "$delegate";
@@ -43,7 +44,7 @@ public final class JvmAbi {
public static final String ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX = "$annotations";
public static final String INSTANCE_FIELD = "INSTANCE$";
public static final String CLASS_OBJECT_FIELD = "OBJECT$";
public static final String CLASS_OBJECT_FIELD = CLASS_OBJECT_CLASS_NAME;
public static final FqName K_OBJECT = new FqName("kotlin.jvm.internal.KObject");
public static final String KOTLIN_CLASS_FIELD_NAME = "$kotlinClass";
@@ -20,24 +20,25 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor;
import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.name.*;
import org.jetbrains.kotlin.name.ClassId;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.FqNameUnsafe;
import org.jetbrains.kotlin.name.Name;
import java.util.ArrayList;
import java.util.List;
import static org.jetbrains.kotlin.name.SpecialNames.isClassObjectName;
public class DeserializedResolverUtils {
private DeserializedResolverUtils() {
}
//TODO_R: remove usages
@NotNull
public static FqName kotlinFqNameToJavaFqName(@NotNull FqNameUnsafe kotlinFqName) {
List<Name> segments = kotlinFqName.pathSegments();
List<String> correctedSegments = new ArrayList<String>(segments.size());
for (Name segment : segments) {
correctedSegments.add(isClassObjectName(segment) ? JvmAbi.CLASS_OBJECT_CLASS_NAME : segment.getIdentifier());
correctedSegments.add(segment.getIdentifier());
}
return FqName.fromSegments(correctedSegments);
}
@@ -47,6 +48,7 @@ public class DeserializedResolverUtils {
return new ClassId(kotlinClassId.getPackageFqName(), kotlinFqNameToJavaFqName(kotlinClassId.getRelativeClassName()).toUnsafe());
}
//TODO_R: remove usages
@NotNull
public static FqNameUnsafe javaFqNameToKotlinFqName(@NotNull FqName javaFqName) {
if (javaFqName.isRoot()) {
@@ -56,14 +58,12 @@ public class DeserializedResolverUtils {
List<Name> correctedSegments = new ArrayList<Name>(segments.size());
correctedSegments.add(segments.get(0));
for (int i = 1; i < segments.size(); i++) {
Name segment = segments.get(i);
boolean isClassObjectName = segment.asString().equals(JvmAbi.CLASS_OBJECT_CLASS_NAME);
Name correctedSegment = isClassObjectName ? SpecialNames.getClassObjectName(segments.get(i - 1)) : segment;
correctedSegments.add(correctedSegment);
correctedSegments.add(segments.get(i));
}
return FqNameUnsafe.fromSegments(correctedSegments);
}
//TODO_R: remove usages
@NotNull
public static ClassId javaClassIdToKotlinClassId(@NotNull ClassId javaClassId) {
return new ClassId(javaClassId.getPackageFqName(), javaFqNameToKotlinFqName(javaClassId.getRelativeClassName().toSafe()));
@@ -51,7 +51,6 @@ public class JvmClassName {
return byFqNameWithoutInnerClasses(new FqName(fqName));
}
private final static String CLASS_OBJECT_REPLACE_GUARD = "<class_object>";
private final static String TRAIT_IMPL_REPLACE_GUARD = "<trait_impl>";
// Internal name: kotlin/Map$Entry
@@ -71,12 +70,10 @@ public class JvmClassName {
public FqName getFqNameForClassNameWithoutDollars() {
if (fqName == null) {
String fqName = internalName
.replace(JvmAbi.CLASS_OBJECT_CLASS_NAME, CLASS_OBJECT_REPLACE_GUARD)
.replace(JvmAbi.TRAIT_IMPL_CLASS_NAME, TRAIT_IMPL_REPLACE_GUARD)
.replace('$', '.')
.replace('/', '.')
.replace(TRAIT_IMPL_REPLACE_GUARD, JvmAbi.TRAIT_IMPL_CLASS_NAME)
.replace(CLASS_OBJECT_REPLACE_GUARD, JvmAbi.CLASS_OBJECT_CLASS_NAME);
.replace(TRAIT_IMPL_REPLACE_GUARD, JvmAbi.TRAIT_IMPL_CLASS_NAME);
this.fqName = new FqName(fqName);
}
return fqName;