diff --git a/js/js.translator/js.translator.iml b/js/js.translator/js.translator.iml
index a827f7758ae..3ec26a8e82c 100644
--- a/js/js.translator/js.translator.iml
+++ b/js/js.translator/js.translator.iml
@@ -10,6 +10,7 @@
+
diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java
index a26837b4bcb..03fb98ebfb1 100644
--- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java
+++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java
@@ -20,7 +20,6 @@ import com.google.dart.compiler.backend.js.ast.*;
import com.intellij.openapi.util.Pair;
import com.intellij.util.SmartList;
import gnu.trove.THashMap;
-import gnu.trove.TLinkable;
import gnu.trove.TLinkableAdaptor;
import gnu.trove.TLinkedList;
import org.jetbrains.annotations.NotNull;
@@ -29,19 +28,20 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.Modality;
import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.psi.JetClassOrObject;
+import org.jetbrains.jet.lang.types.JetType;
+import org.jetbrains.jet.utils.DFS;
import org.jetbrains.k2js.translate.LabelGenerator;
import org.jetbrains.k2js.translate.context.Namer;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.initializer.InitializerUtils;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
import static com.google.dart.compiler.backend.js.ast.JsVars.JsVar;
+import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getClassDescriptorForType;
import static org.jetbrains.k2js.translate.general.Translation.translateClassDeclaration;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getClassDescriptor;
-import static org.jetbrains.k2js.translate.utils.ErrorReportingUtils.message;
/**
* Generates a big block where are all the classes(objects representing them) are created.
@@ -55,6 +55,9 @@ public final class ClassDeclarationTranslator extends AbstractTranslator {
private final TLinkedList openList = new TLinkedList();
private final List> finalList = new ArrayList>();
+ @NotNull
+ private final ClassDescriptorToLabel classDescriptorToLabel = new ClassDescriptorToLabel();
+
@NotNull
private final JsFunction dummyFunction;
@@ -70,7 +73,7 @@ public final class ClassDeclarationTranslator extends AbstractTranslator {
declarationsObjectRef = declarationsObject.makeRef();
}
- private final class OpenClassRefProvider implements ClassAliasingMap {
+ private final class ClassDescriptorToLabel implements ClassAliasingMap {
@Override
@Nullable
public JsNameRef get(ClassDescriptor descriptor, ClassDescriptor referencedDescriptor) {
@@ -80,20 +83,8 @@ public final class ClassDeclarationTranslator extends AbstractTranslator {
return null;
}
- addAfter(item, openClassDescriptorToItem.get(referencedDescriptor));
return item.label;
}
-
- private void addAfter(@NotNull FinalListItem item, @NotNull FinalListItem referencedItem) {
- for (TLinkable link = item.getNext(); link != null; link = link.getNext()) {
- if (link == referencedItem) {
- return;
- }
- }
-
- openList.remove(referencedItem);
- openList.addBefore((FinalListItem) item.getNext(), referencedItem);
- }
}
private static class FinalListItem extends TLinkableAdaptor {
@@ -101,8 +92,6 @@ public final class ClassDeclarationTranslator extends AbstractTranslator {
private final JsNameRef label;
private final JsNameRef qualifiedLabel;
- private JsExpression translatedDeclaration;
-
private FinalListItem(JetClass declaration, JsNameRef label, JsNameRef qualifiedLabel) {
this.declaration = declaration;
this.label = label;
@@ -134,17 +123,35 @@ public final class ClassDeclarationTranslator extends AbstractTranslator {
}
private void generateOpenClassDeclarations(@NotNull List vars, @NotNull List propertyInitializers) {
- ClassAliasingMap classAliasingMap = new OpenClassRefProvider();
// first pass: set up list order
- for (FinalListItem item : openList) {
- item.translatedDeclaration = translateClassDeclaration(item.declaration, classAliasingMap, context());
- }
+ LinkedList sortedOpenClasses =
+ (LinkedList) DFS.topologicalOrder(openList, new DFS.Neighbors() {
+ @NotNull
+ @Override
+ public Iterable getNeighbors(FinalListItem current) {
+ TLinkedList parents = new TLinkedList();
+ ClassDescriptor classDescriptor = getClassDescriptor(context().bindingContext(), current.declaration);
+ Collection superTypes = classDescriptor.getTypeConstructor().getSupertypes();
+
+ for (JetType type : superTypes) {
+ ClassDescriptor descriptor = getClassDescriptorForType(type);
+ FinalListItem item = openClassDescriptorToItem.get(descriptor);
+ if (item == null) {
+ continue;
+ }
+
+ parents.add(item);
+ }
+
+ return parents;
+ }
+ });
+
// second pass: generate
- for (FinalListItem item : openList) {
- JsExpression translatedDeclaration = item.translatedDeclaration;
- if (translatedDeclaration == null) {
- throw new IllegalStateException(message(item.declaration, "Could not translate class declaration)"));
- }
+ Iterator it = sortedOpenClasses.descendingIterator();
+ while (it.hasNext()) {
+ FinalListItem item = it.next();
+ JsExpression translatedDeclaration = translateClassDeclaration(item.declaration, classDescriptorToLabel, context());
generate(item, propertyInitializers, translatedDeclaration, vars);
}
}
diff --git a/js/js.translator/testFiles/inheritance/cases/definitionOrder.kt b/js/js.translator/testFiles/inheritance/cases/definitionOrder.kt
index 12e3f7b045c..10d2673d36e 100644
--- a/js/js.translator/testFiles/inheritance/cases/definitionOrder.kt
+++ b/js/js.translator/testFiles/inheritance/cases/definitionOrder.kt
@@ -24,7 +24,7 @@ open class B() : A() {
}
}
-open class A() {
+open class A() : G() {
var order = ""
{
@@ -32,6 +32,13 @@ open class A() {
}
}
+// KT-3437
+abstract class G : H()
+abstract class K : H()
+abstract class L
+abstract class H : L()
+abstract class Dummy
+
fun box() : Boolean {
return (C().order == "ABC") && (D().order == "ABD") && (E().order == "AE")
}
\ No newline at end of file
diff --git a/js/js.translator/testFiles/trait/cases/definitionOrder.kt b/js/js.translator/testFiles/trait/cases/definitionOrder.kt
index b8508c7a9d0..f7dd2bbed6f 100644
--- a/js/js.translator/testFiles/trait/cases/definitionOrder.kt
+++ b/js/js.translator/testFiles/trait/cases/definitionOrder.kt
@@ -32,10 +32,17 @@ open class A() : F {
}
}
-trait F {
+trait F : G {
fun bar() = "F"
}
+// KT-3437
+trait G : H
+trait K : H
+trait L
+trait H : L
+trait Dummy
+
fun box() : Boolean {
return (C().order == "ABC") && (D().order == "ABD") && (E().order == "AE") && (C().bar() == "F") && (A().bar() == "F")
}
\ No newline at end of file