Serialize secondary constructors

This commit is contained in:
Denis Zharkov
2015-02-25 16:06:16 +03:00
parent e65382e6ec
commit 111a138a2a
8 changed files with 62 additions and 12 deletions
@@ -0,0 +1,9 @@
open class A {
val prop: String
constructor(x1: String, x2: String = "abc") {
prop = "$x1#$x2"
}
constructor(x1: Long) {
prop = "$x1"
}
}
@@ -0,0 +1,25 @@
import java.lang
class B1() : A("123") {
constructor(x1: Int): this() {}
}
class B2 : A {
constructor(x1: String): super(x1) {}
constructor(): this("empty") {}
constructor(x1: Int): super(x1.toLong()) {}
}
fun main(args: Array<String>) {
val b1 = B1()
if (b1.prop != "123#abc") throw AssertionError("fail1: ${b1.prop}")
val b2 = B1(456)
if (b2.prop != "123#abc") throw AssertionError("fail2: ${b2.prop}")
val b3 = B2("cde")
if (b3.prop != "cde#abc") throw AssertionError("fail3: ${b3.prop}")
val b4 = B2()
if (b4.prop != "empty#abc") throw AssertionError("fail4: ${b4.prop}")
val b5 = B2(789)
if (b5.prop != "789") throw AssertionError("fail5: ${b5.prop}")
}
@@ -144,6 +144,12 @@ public class CompileKotlinAgainstKotlinTestGenerated extends AbstractCompileKotl
doTest(fileName);
}
@TestMetadata("SecondaryConstructors.A.kt")
public void testSecondaryConstructors() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstKotlin/SecondaryConstructors.A.kt");
doTest(fileName);
}
@TestMetadata("Simple.A.kt")
public void testSimple() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstKotlin/Simple.A.kt");
+1 -1
View File
@@ -201,7 +201,7 @@ message Class {
// This field is present if and only if the class has a primary constructor
optional PrimaryConstructor primary_constructor = 13;
// todo: other constructors?
repeated Callable secondary_constructor = 14;
extensions 100 to 199;
}
@@ -110,7 +110,10 @@ public class DescriptorSerializer {
}
}
// TODO: other constructors
for (ConstructorDescriptor constructorDescriptor : classDescriptor.getConstructors()) {
if (constructorDescriptor.isPrimary()) continue;
builder.addSecondaryConstructor(callableProto(constructorDescriptor));
}
for (DeclarationDescriptor descriptor : sort(classDescriptor.getDefaultType().getMemberScope().getAllDescriptors())) {
if (descriptor instanceof CallableMemberDescriptor) {
@@ -31,7 +31,6 @@ public class MemberDeserializer(private val c: DeserializationContext) {
return when (callableKind) {
FUN -> loadFunction(proto)
VAL, VAR -> loadProperty(proto)
CONSTRUCTOR -> loadConstructor(proto)
else -> throw IllegalArgumentException("Unsupported callable kind: $callableKind")
}
}
@@ -143,11 +142,11 @@ public class MemberDeserializer(private val c: DeserializationContext) {
return (c.containingDeclaration as? ClassDescriptor)?.getThisAsReceiverParameter()
}
private fun loadConstructor(proto: Callable): CallableMemberDescriptor {
public fun loadConstructor(proto: Callable, isPrimary: Boolean): ConstructorDescriptor {
val classDescriptor = c.containingDeclaration as ClassDescriptor
val descriptor = ConstructorDescriptorImpl.create(
classDescriptor, getAnnotations(proto, proto.getFlags(), AnnotatedCallableKind.FUNCTION), // TODO: primary
true, SourceElement.NO_SOURCE
classDescriptor, getAnnotations(proto, proto.getFlags(), AnnotatedCallableKind.FUNCTION),
isPrimary, SourceElement.NO_SOURCE
)
val local = c.childContext(descriptor, listOf())
descriptor.initialize(
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.serialization.deserialization
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.utils.singletonOrEmptyList
import java.util.*
public class DeserializedClassDescriptor(
@@ -62,6 +63,7 @@ public class DeserializedClassDescriptor(
private val containingDeclaration = outerContext.containingDeclaration
private val primaryConstructor = c.storageManager.createNullableLazyValue { computePrimaryConstructor() }
private val constructors = c.storageManager.createLazyValue { computeConstructors() }
private val defaultObjectDescriptor = c.storageManager.createNullableLazyValue { computeDefaultObjectDescriptor() }
private val annotations =
@@ -102,16 +104,20 @@ public class DeserializedClassDescriptor(
return descriptor
}
return c.memberDeserializer.loadCallable(constructorProto.getData()) as ConstructorDescriptor
return c.memberDeserializer.loadConstructor(constructorProto.getData(), true)
}
override fun getUnsubstitutedPrimaryConstructor(): ConstructorDescriptor? = primaryConstructor()
override fun getConstructors(): Collection<ConstructorDescriptor> {
val constructor = getUnsubstitutedPrimaryConstructor() ?: return listOf()
// TODO: other constructors
return listOf(constructor)
}
private fun computeConstructors(): Collection<ConstructorDescriptor> =
computeSecondaryConstructors() + getUnsubstitutedPrimaryConstructor().singletonOrEmptyList()
private fun computeSecondaryConstructors(): List<ConstructorDescriptor> =
classProto.getSecondaryConstructorList().map {
c.memberDeserializer.loadConstructor(it, false)
}
override fun getConstructors() = constructors()
private fun computeDefaultObjectDescriptor(): ClassDescriptor? {
if (!classProto.hasDefaultObjectName()) return null
@@ -103,3 +103,5 @@ public fun <E> newHashSetWithExpectedSize(expectedSize: Int): HashSet<E> {
public fun <T> Collection<T>.toReadOnlyList(): List<T> =
if (isEmpty()) Collections.emptyList() else ArrayList(this)
public fun <T: Any> T?.singletonOrEmptyList(): List<T> = if (this != null) Collections.singletonList(this) else Collections.emptyList()