KT-11030 Initialization order of enum entries in JS now conforms to JVM backend

This commit is contained in:
Alexey Andreev
2016-04-15 12:13:11 +03:00
parent 87ea0bd0cb
commit ade5477c33
5 changed files with 59 additions and 22 deletions
@@ -58,4 +58,8 @@ public class EnumTest extends SingleFileTranslationTest {
public void testEquals() throws Exception {
checkFooBoxIsOk();
}
public void testInitializationOrder() throws Exception {
checkFooBoxIsOk();
}
}
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.js.translate.general.Translation;
import org.jetbrains.kotlin.js.translate.general.TranslatorVisitor;
import org.jetbrains.kotlin.js.translate.initializer.ClassInitializerTranslator;
import org.jetbrains.kotlin.js.translate.utils.BindingUtils;
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.types.KotlinType;
@@ -69,14 +70,15 @@ public class DeclarationBodyVisitor extends TranslatorVisitor<Void> {
@Override
public Void visitEnumEntry(@NotNull KtEnumEntry enumEntry, TranslationContext data) {
JsExpression jsEnumEntryCreation;
ClassDescriptor descriptor = getClassDescriptor(data.bindingContext(), enumEntry);
List<KotlinType> supertypes = getSupertypesWithoutFakes(descriptor);
if (enumEntry.getBody() != null || supertypes.size() > 1) {
enumEntryList.addAll(ClassTranslator.translate(enumEntry, data).getProperties());
} else {
assert supertypes.size() == 1 : "Simple Enum entry must have one supertype";
jsEnumEntryCreation = new ClassInitializerTranslator(enumEntry, data).generateEnumEntryInstanceCreation(supertypes.get(0));
JsExpression jsEnumEntryCreation = new ClassInitializerTranslator(enumEntry, data)
.generateEnumEntryInstanceCreation(supertypes.get(0));
jsEnumEntryCreation = TranslationUtils.simpleReturnFunction(data.scope(), jsEnumEntryCreation);
enumEntryList.add(new JsPropertyInitializer(data.getNameForDescriptor(descriptor).makeRef(), jsEnumEntryCreation));
}
return null;
@@ -145,11 +145,15 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
private void mayBeAddCallToSuperMethod(JsFunction initializer, @NotNull ClassDescriptor descriptor) {
if (classDeclaration.hasModifier(KtTokens.ENUM_KEYWORD)) {
addCallToSuperMethod(Collections.<JsExpression>emptyList(), initializer);
return;
}
if (hasAncestorClass(bindingContext(), classDeclaration)) {
else if (hasAncestorClass(bindingContext(), classDeclaration)) {
ResolvedCall<FunctionDescriptor> superCall = getSuperCall(bindingContext(), classDeclaration);
if (superCall == null) return;
if (superCall == null) {
if (DescriptorUtils.isEnumEntry(descriptor)) {
addCallToSuperMethod(Collections.<JsExpression>emptyList(), initializer);
}
return;
}
if (classDeclaration instanceof KtEnumEntry) {
JsExpression expression = CallTranslator.translate(context(), superCall, null);
@@ -0,0 +1,33 @@
package foo
enum class E {
A,
B {
init {
log("init B")
}
},
C;
init {
log("init E")
}
}
var l = ""
fun log(s: String) {
l += s + ";"
}
fun box(): String {
log("get Ea.A")
E.A.toString()
log("get E.B")
E.B.toString()
log("get E.C")
E.C.toString()
if (l != "get Ea.A;init E;init E;init B;init E;get E.B;get E.C;") return "fail: '$l'"
return "OK"
}
+11 -17
View File
@@ -256,27 +256,21 @@ var Kotlin = {};
var values = [];
for (var entryName in enumEntryList) {
if (enumEntryList.hasOwnProperty(entryName)) {
var entryObject = enumEntryList[entryName];
var entryFactory = enumEntryList[entryName];
values.push(entryName);
if (typeof entryObject === 'function' && entryObject.type === Kotlin.TYPE.INIT_FUN) {
entryObject.className = entryName;
Object.defineProperty(cls, entryName, {
get: function(ordinal, name, obj) {
return function() {
var result = obj.apply(this);
result.ordinal$ = ordinal;
result.name$ = name;
return result;
}
}(i++, entryName, entryObject),
configurable: true
})
var entryObject;
if (typeof entryFactory === 'function' && entryFactory.type === Kotlin.TYPE.INIT_FUN) {
entryFactory.className = entryName;
entryObject = entryFactory.apply(cls);
}
else {
entryObject.ordinal$ = i++;
entryObject.name$ = entryName;
cls[entryName] = entryObject;
entryObject = entryFactory();
}
entryObject.ordinal$ = i++;
entryObject.name$ = entryName;
cls[entryName] = entryObject;
}
}
cls.valuesNames$ = values;