KT-11030 Initialization order of enum entries in JS now conforms to JVM backend
This commit is contained in:
@@ -58,4 +58,8 @@ public class EnumTest extends SingleFileTranslationTest {
|
|||||||
public void testEquals() throws Exception {
|
public void testEquals() throws Exception {
|
||||||
checkFooBoxIsOk();
|
checkFooBoxIsOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testInitializationOrder() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-2
@@ -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.general.TranslatorVisitor;
|
||||||
import org.jetbrains.kotlin.js.translate.initializer.ClassInitializerTranslator;
|
import org.jetbrains.kotlin.js.translate.initializer.ClassInitializerTranslator;
|
||||||
import org.jetbrains.kotlin.js.translate.utils.BindingUtils;
|
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.psi.*;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
|
|
||||||
@@ -69,14 +70,15 @@ public class DeclarationBodyVisitor extends TranslatorVisitor<Void> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visitEnumEntry(@NotNull KtEnumEntry enumEntry, TranslationContext data) {
|
public Void visitEnumEntry(@NotNull KtEnumEntry enumEntry, TranslationContext data) {
|
||||||
JsExpression jsEnumEntryCreation;
|
|
||||||
ClassDescriptor descriptor = getClassDescriptor(data.bindingContext(), enumEntry);
|
ClassDescriptor descriptor = getClassDescriptor(data.bindingContext(), enumEntry);
|
||||||
List<KotlinType> supertypes = getSupertypesWithoutFakes(descriptor);
|
List<KotlinType> supertypes = getSupertypesWithoutFakes(descriptor);
|
||||||
if (enumEntry.getBody() != null || supertypes.size() > 1) {
|
if (enumEntry.getBody() != null || supertypes.size() > 1) {
|
||||||
enumEntryList.addAll(ClassTranslator.translate(enumEntry, data).getProperties());
|
enumEntryList.addAll(ClassTranslator.translate(enumEntry, data).getProperties());
|
||||||
} else {
|
} else {
|
||||||
assert supertypes.size() == 1 : "Simple Enum entry must have one supertype";
|
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));
|
enumEntryList.add(new JsPropertyInitializer(data.getNameForDescriptor(descriptor).makeRef(), jsEnumEntryCreation));
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
+7
-3
@@ -145,11 +145,15 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
|||||||
private void mayBeAddCallToSuperMethod(JsFunction initializer, @NotNull ClassDescriptor descriptor) {
|
private void mayBeAddCallToSuperMethod(JsFunction initializer, @NotNull ClassDescriptor descriptor) {
|
||||||
if (classDeclaration.hasModifier(KtTokens.ENUM_KEYWORD)) {
|
if (classDeclaration.hasModifier(KtTokens.ENUM_KEYWORD)) {
|
||||||
addCallToSuperMethod(Collections.<JsExpression>emptyList(), initializer);
|
addCallToSuperMethod(Collections.<JsExpression>emptyList(), initializer);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (hasAncestorClass(bindingContext(), classDeclaration)) {
|
else if (hasAncestorClass(bindingContext(), classDeclaration)) {
|
||||||
ResolvedCall<FunctionDescriptor> superCall = getSuperCall(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) {
|
if (classDeclaration instanceof KtEnumEntry) {
|
||||||
JsExpression expression = CallTranslator.translate(context(), superCall, null);
|
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
@@ -256,27 +256,21 @@ var Kotlin = {};
|
|||||||
var values = [];
|
var values = [];
|
||||||
for (var entryName in enumEntryList) {
|
for (var entryName in enumEntryList) {
|
||||||
if (enumEntryList.hasOwnProperty(entryName)) {
|
if (enumEntryList.hasOwnProperty(entryName)) {
|
||||||
var entryObject = enumEntryList[entryName];
|
var entryFactory = enumEntryList[entryName];
|
||||||
values.push(entryName);
|
values.push(entryName);
|
||||||
if (typeof entryObject === 'function' && entryObject.type === Kotlin.TYPE.INIT_FUN) {
|
|
||||||
entryObject.className = entryName;
|
var entryObject;
|
||||||
Object.defineProperty(cls, entryName, {
|
if (typeof entryFactory === 'function' && entryFactory.type === Kotlin.TYPE.INIT_FUN) {
|
||||||
get: function(ordinal, name, obj) {
|
entryFactory.className = entryName;
|
||||||
return function() {
|
entryObject = entryFactory.apply(cls);
|
||||||
var result = obj.apply(this);
|
|
||||||
result.ordinal$ = ordinal;
|
|
||||||
result.name$ = name;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}(i++, entryName, entryObject),
|
|
||||||
configurable: true
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
entryObject.ordinal$ = i++;
|
entryObject = entryFactory();
|
||||||
entryObject.name$ = entryName;
|
|
||||||
cls[entryName] = entryObject;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entryObject.ordinal$ = i++;
|
||||||
|
entryObject.name$ = entryName;
|
||||||
|
cls[entryName] = entryObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cls.valuesNames$ = values;
|
cls.valuesNames$ = values;
|
||||||
|
|||||||
Reference in New Issue
Block a user