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
@@ -256,11 +256,7 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
@NotNull
private static FqName getClassRelativeName(@NotNull JetClassOrObject decompiledClassOrObject) {
Name name = decompiledClassOrObject.getNameAsName();
if (name == null) {
assert decompiledClassOrObject instanceof JetObjectDeclaration &&
((JetObjectDeclaration) decompiledClassOrObject).isClassObject();
name = Name.identifier(JvmAbi.CLASS_OBJECT_CLASS_NAME);
}
assert name != null;
JetClassOrObject parent = PsiTreeUtil.getParentOfType(decompiledClassOrObject, JetClassOrObject.class, true);
if (parent == null) {
assert decompiledClassOrObject.isTopLevel();
@@ -31,7 +31,6 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.JetDelegationSpecifierList
import org.jetbrains.kotlin.psi.JetDelegatorToSuperClass
import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.name.SpecialNames.getClassObjectName
import org.jetbrains.kotlin.psi.JetClassObject
import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
import org.jetbrains.kotlin.psi.stubs.impl.KotlinModifierListStubImpl
@@ -68,6 +67,7 @@ private class ClassClsStubBuilder(
supertypeIds
}
}
private val classObjectName = if (classProto.hasClassObjectName()) c.nameResolver.getName(classProto.getClassObjectName()) else null
private val classOrObjectStub = createClassOrObjectStubAndModifierListStub()
@@ -112,8 +112,8 @@ private class ClassClsStubBuilder(
private fun doCreateClassOrObjectStub(parent: StubElement<out PsiElement>): StubElement<out PsiElement> {
val isClassObject = classKind == ProtoBuf.Class.Kind.CLASS_OBJECT
val fqName = if (!isClassObject) outerContext.memberFqNameProvider.getMemberFqName(classId.getRelativeClassName().shortName()) else null
val shortName = fqName?.shortName()?.ref()
val fqName = outerContext.memberFqNameProvider.getMemberFqName(classId.getRelativeClassName().shortName())
val shortName = fqName.shortName()?.ref()
val superTypeRefs = supertypeIds.filter {
//TODO: filtering function types should go away
!KotlinBuiltIns.isExactFunctionType(it.asSingleFqName()) && !KotlinBuiltIns.isExactExtensionFunctionType(it.asSingleFqName())
@@ -132,7 +132,7 @@ private class ClassClsStubBuilder(
KotlinClassStubImpl(
JetClassElementType.getStubType(classKind == ProtoBuf.Class.Kind.ENUM_ENTRY),
parent,
fqName?.ref(),
fqName.ref(),
shortName,
superTypeRefs,
isTrait = classKind == ProtoBuf.Class.Kind.TRAIT,
@@ -181,11 +181,11 @@ private class ClassClsStubBuilder(
}
private fun createClassObjectStub(classBody: KotlinPlaceHolderStubImpl<JetClassBody>) {
if (!classProto.hasClassObject() || classKind == ProtoBuf.Class.Kind.OBJECT) {
if (classObjectName == null) {
return
}
val classObjectId = classId.createNestedClassId(getClassObjectName(classId.getRelativeClassName().shortName()))
val classObjectId = classId.createNestedClassId(classObjectName)
createNestedClassStub(classBody, classObjectId)
}
@@ -221,8 +221,11 @@ private class ClassClsStubBuilder(
private fun createInnerAndNestedClasses(classBody: KotlinPlaceHolderStubImpl<JetClassBody>) {
classProto.getNestedClassNameList().forEach { id ->
val nestedClassId = classId.createNestedClassId(c.nameResolver.getName(id))
createNestedClassStub(classBody, nestedClassId)
val nestedClassName = c.nameResolver.getName(id)
if (nestedClassName != classObjectName) {
val nestedClassId = classId.createNestedClassId(nestedClassName)
createNestedClassStub(classBody, nestedClassId)
}
}
}
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.load.kotlin.AbstractBinaryClassAnnotationAndConstant
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
import org.jetbrains.kotlin.name.SpecialNames
class ClsStubBuilderComponents(
@@ -42,11 +41,11 @@ class ClsStubBuilderComponents(
}
}
//TODO_R: remove?
class MemberFqNameProvider(val fqName: FqName) {
fun getMemberFqName(name: Name): FqName = fqName.child(name)
fun child(name: Name?): MemberFqNameProvider =
if (name == null || SpecialNames.isClassObjectName(name)) this else MemberFqNameProvider(fqName.child(name))
fun child(name: Name?): MemberFqNameProvider = if (name == null) this else MemberFqNameProvider(fqName.child(name))
}
trait TypeParameters {
@@ -97,8 +97,7 @@ fun createStubForPackageName(packageDirectiveStub: KotlinPlaceHolderStubImpl<Jet
}
fun createStubForTypeName(typeClassId: ClassId, parent: StubElement<out PsiElement>): KotlinUserTypeStub {
//TODO: should go away with default objects
val segments = typeClassId.asSingleFqName().pathSegments().filter { !SpecialNames.isClassObjectName(it) }.toArrayList()
val segments = typeClassId.asSingleFqName().pathSegments().toArrayList()
assert(segments.isNotEmpty())
val iterator = segments.listIterator(segments.size())
@@ -148,7 +148,7 @@ private fun buildDecompiledText(packageFqName: FqName, descriptors: List<Declara
var firstPassed = false
val subindent = indent + " "
val classObject = descriptor.getClassObjectDescriptor()
if (classObject != null && !isSyntheticClassObject(classObject)) {
if (classObject != null && !descriptor.getKind().isSingleton() && !isSyntheticClassObject(classObject)) {
firstPassed = true
builder.append(subindent)
appendDescriptor(classObject, subindent)
@@ -157,6 +157,9 @@ private fun buildDecompiledText(packageFqName: FqName, descriptors: List<Declara
if (member.getContainingDeclaration() != descriptor) {
continue
}
if (member == classObject) {
continue
}
if (member is CallableMemberDescriptor
&& member.getKind() != CallableMemberDescriptor.Kind.DECLARATION
//TODO: not synthesized and component like
@@ -114,16 +114,7 @@ public class DeprecatedAnnotationVisitor extends AfterAnalysisHighlightingVisito
}
private void checkClassDescriptor(@NotNull JetExpression expression, @NotNull ClassDescriptor target) {
// Deprecated for Class, for ClassObject (if reference isn't in UserType or in ModifierList (trait))
if (!reportAnnotationIfNeeded(expression, target)) {
if (PsiTreeUtil.getParentOfType(expression, JetUserType.class) == null &&
PsiTreeUtil.getParentOfType(expression, JetModifierList.class) == null) {
ClassDescriptor classObjectDescriptor = target.getClassObjectDescriptor();
if (classObjectDescriptor != null) {
reportAnnotationIfNeeded(expression, classObjectDescriptor);
}
}
}
reportAnnotationIfNeeded(expression, target);
}
private void checkPropertyDescriptor(
@@ -56,25 +56,11 @@ public class StubIndexServiceImpl implements StubIndexService {
@Override
public void indexObject(KotlinObjectStub stub, IndexSink sink) {
String name = stub.getName();
FqName fqName = stub.getFqName();
if (stub.isClassObject()) {
StubElement parentClassStub = stub.getParentStub().getParentStub().getParentStub();
assert parentClassStub instanceof KotlinStubWithFqName<?>
: "Something but a class/object is a parent to class object stub: " + parentClassStub;
name = JvmAbi.CLASS_OBJECT_CLASS_NAME;
FqName parentFqName = ((KotlinStubWithFqName<?>) parentClassStub).getFqName();
if (parentFqName != null) {
fqName = parentFqName.child(Name.identifier(name));
}
}
if (name != null) {
sink.occurrence(JetClassShortNameIndex.getInstance().getKey(), name);
}
FqName fqName = stub.getFqName();
if (fqName != null) {
sink.occurrence(JetFullClassNameIndex.getInstance().getKey(), fqName.asString());