diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index e35a91b9c12..585220fa7e4 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -6,14 +6,12 @@
-
-
-
+
+
-
-
+
@@ -117,47 +115,29 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
+
-
+
-
-
+
+
@@ -165,10 +145,28 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -214,19 +212,37 @@
-
+
-
+
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -235,7 +251,7 @@
-
+
@@ -277,28 +293,10 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -325,7 +323,6 @@
@@ -795,11 +793,11 @@
+
-
@@ -1044,7 +1042,7 @@
-
+
@@ -1058,9 +1056,9 @@
-
+
-
+
@@ -1098,7 +1096,7 @@
-
+
@@ -1111,7 +1109,6 @@
-
@@ -1136,6 +1133,7 @@
+
@@ -1145,23 +1143,16 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -1173,6 +1164,13 @@
+
+
+
+
+
+
+
@@ -1182,77 +1180,77 @@
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/translator/src/org/jetbrains/k2js/translate/BindingUtils.java b/translator/src/org/jetbrains/k2js/translate/BindingUtils.java
index ead6477d4e1..42e183eb81b 100644
--- a/translator/src/org/jetbrains/k2js/translate/BindingUtils.java
+++ b/translator/src/org/jetbrains/k2js/translate/BindingUtils.java
@@ -2,6 +2,7 @@ package org.jetbrains.k2js.translate;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
@@ -103,12 +104,7 @@ public final class BindingUtils {
static public boolean hasAncestorClass(@NotNull BindingContext context, @NotNull JetClass classDeclaration) {
List superclassDescriptors = getSuperclassDescriptors(context, classDeclaration);
- for (ClassDescriptor descriptor : superclassDescriptors) {
- if (descriptor.getKind() == ClassKind.CLASS) {
- return true;
- }
- }
- return false;
+ return (findAncestorClass(superclassDescriptors) != null);
}
static public boolean isStatement(@NotNull BindingContext context, @NotNull JetExpression expression) {
@@ -122,4 +118,14 @@ public final class BindingUtils {
return !superClassDescriptor.getName().equals("Any");
}
+ //TODO move unrelated utils to other class
+ @Nullable
+ public static ClassDescriptor findAncestorClass(@NotNull List superclassDescriptors) {
+ for (ClassDescriptor descriptor : superclassDescriptors) {
+ if (descriptor.getKind() == ClassKind.CLASS) {
+ return descriptor;
+ }
+ }
+ return null;
+ }
}
diff --git a/translator/src/org/jetbrains/k2js/translate/ClassTranslator.java b/translator/src/org/jetbrains/k2js/translate/ClassTranslator.java
index c9e9901d099..3857087688e 100644
--- a/translator/src/org/jetbrains/k2js/translate/ClassTranslator.java
+++ b/translator/src/org/jetbrains/k2js/translate/ClassTranslator.java
@@ -3,7 +3,9 @@ package org.jetbrains.k2js.translate;
import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
+import org.jetbrains.jet.lang.descriptors.ClassKind;
import org.jetbrains.jet.lang.psi.JetClass;
import java.util.ArrayList;
@@ -37,13 +39,15 @@ public final class ClassTranslator extends AbstractTranslator {
}
}
+ @NotNull
private JsStatement translateAsStatelessTrait(@NotNull JetClass classDeclaration) {
JsObjectLiteral traitLiteral = translateClassDeclarations(classDeclaration);
return AstUtil.convertToStatement
(AstUtil.newAssignment(namespaceQualifiedClassNameReference(classDeclaration), traitLiteral));
}
- private JsStatement translateAsClassWithState(JetClass jetClassDeclaration) {
+ @NotNull
+ private JsStatement translateAsClassWithState(@NotNull JetClass jetClassDeclaration) {
JsInvocation jsClassDeclaration = createMethodInvocation();
addSuperclassReferences(jetClassDeclaration, jsClassDeclaration);
addClassOwnDeclarations(jetClassDeclaration, jsClassDeclaration);
@@ -64,7 +68,8 @@ public final class ClassTranslator extends AbstractTranslator {
(namespaceQualifiedClassNameReference(classDeclaration), jsClassDeclaration));
}
- private JsNameRef namespaceQualifiedClassNameReference(JetClass classDeclaration) {
+ @NotNull
+ private JsNameRef namespaceQualifiedClassNameReference(@NotNull JetClass classDeclaration) {
return translationContext().getNamespaceQualifiedReference
(translationContext().getNameForElement(classDeclaration));
}
@@ -85,15 +90,45 @@ public final class ClassTranslator extends AbstractTranslator {
@NotNull
private List getSuperclassNameReferences(@NotNull JetClass classDeclaration) {
List superclassReferences = new ArrayList();
- for (ClassDescriptor superClassDescriptor :
- BindingUtils.getSuperclassDescriptors(translationContext().bindingContext(), classDeclaration)) {
- //TODO should get a full class name here
- superclassReferences.add(translationContext().getNamespaceQualifiedReference
- (translationContext().getNameForDescriptor(superClassDescriptor)));
- }
+ List superclassDescriptors =
+ BindingUtils.getSuperclassDescriptors(translationContext().bindingContext(), classDeclaration);
+ addAncestorClass(superclassReferences, superclassDescriptors);
+ addTraits(superclassReferences, superclassDescriptors);
return superclassReferences;
}
+ private void addTraits(@NotNull List superclassReferences,
+ @NotNull List superclassDescriptors) {
+ for (ClassDescriptor superClassDescriptor :
+ superclassDescriptors) {
+ assert (superClassDescriptor.getKind() == ClassKind.TRAIT) : "Only traits are expected here";
+ superclassReferences.add(getClassReference(superClassDescriptor));
+ }
+ }
+
+ private void addAncestorClass(@NotNull List superclassReferences,
+ @NotNull List superclassDescriptors) {
+ //here we remove ancestor class from the list
+ ClassDescriptor ancestorClass = findAndRemoveAncestorClass(superclassDescriptors);
+ if (ancestorClass != null) {
+ superclassReferences.add(getClassReference(ancestorClass));
+ }
+ }
+
+ @NotNull
+ private JsNameRef getClassReference(@NotNull ClassDescriptor superClassDescriptor) {
+ //TODO should get a full class name here
+ return translationContext().getNamespaceQualifiedReference
+ (translationContext().getNameForDescriptor(superClassDescriptor));
+ }
+
+ @Nullable
+ private ClassDescriptor findAndRemoveAncestorClass(@NotNull List superclassDescriptors) {
+ ClassDescriptor ancestorClass = BindingUtils.findAncestorClass(superclassDescriptors);
+ superclassDescriptors.remove(ancestorClass);
+ return ancestorClass;
+ }
+
@NotNull
private JsObjectLiteral translateClassDeclarations(@NotNull JetClass classDeclaration) {
List propertyList = new ArrayList();
diff --git a/translator/test/org/jetbrains/k2js/test/TraitTest.java b/translator/test/org/jetbrains/k2js/test/TraitTest.java
index 4fb3576c8d1..7ca25dc8305 100644
--- a/translator/test/org/jetbrains/k2js/test/TraitTest.java
+++ b/translator/test/org/jetbrains/k2js/test/TraitTest.java
@@ -23,4 +23,14 @@ public final class TraitTest extends AbstractClassTest {
public void traitAddsFunctionsToClass() throws Exception {
testFooBoxIsTrue("traitAddsFunctionsToClass.kt");
}
+
+ @Test
+ public void classDerivesFromClassAndTrait() throws Exception {
+ testFooBoxIsTrue("classDerivesFromClassAndTrait.kt");
+ }
+
+ @Test
+ public void classDerivesFromTraitAndClass() throws Exception {
+ testFooBoxIsTrue("classDerivesFromTraitAndClass.kt");
+ }
}
diff --git a/translator/testFiles/trait/cases/classDerivesFromClassAndTrait.kt b/translator/testFiles/trait/cases/classDerivesFromClassAndTrait.kt
new file mode 100644
index 00000000000..1e02ef4f80e
--- /dev/null
+++ b/translator/testFiles/trait/cases/classDerivesFromClassAndTrait.kt
@@ -0,0 +1,21 @@
+namespace foo
+
+
+open class A() {
+ val value = "BAR"
+}
+
+trait Test {
+ fun addFoo(s:String) : String {
+ return s + "FOO"
+ }
+}
+
+
+class B() : A(), Test {
+ fun eval() : String {
+ return addFoo(value);
+ }
+}
+
+fun box() = B().eval() == "BARFOO"
\ No newline at end of file
diff --git a/translator/testFiles/trait/cases/classDerivesFromTraitAndClass.kt b/translator/testFiles/trait/cases/classDerivesFromTraitAndClass.kt
new file mode 100644
index 00000000000..82a586cc491
--- /dev/null
+++ b/translator/testFiles/trait/cases/classDerivesFromTraitAndClass.kt
@@ -0,0 +1,21 @@
+namespace foo
+
+
+open class A() {
+ val value = "BAR"
+}
+
+trait Test {
+ fun addFoo(s:String) : String {
+ return s + "FOO"
+ }
+}
+
+
+class B() : Test, A() {
+ fun eval() : String {
+ return addFoo(value);
+ }
+}
+
+fun box() = B().eval() == "BARFOO"
\ No newline at end of file