diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/MiscTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/MiscTest.java index c1bdd076918..1df84eedfa6 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/MiscTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/MiscTest.java @@ -73,6 +73,14 @@ public final class MiscTest extends AbstractExpressionTest { checkFooBoxIsOk("KT-740-2.kt"); } + public void testKt1361_1() throws Exception { + checkFooBoxIsTrue("KT-1361-1.kt"); + } + + public void testKt1361_2() throws Exception { + checkFooBoxIsTrue("KT-1361-2.kt"); + } + //TODO: depends on KT-1198 //TODO: look into BindingContext.VARIABLE_REASSIGNMENT // public void testKt740_3() throws Exception { diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java index 5dfc6d2292d..fcb225ec13d 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java @@ -24,7 +24,9 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassKind; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.psi.JetClassOrObject; +import org.jetbrains.jet.lang.psi.JetObjectLiteralExpression; import org.jetbrains.jet.lang.psi.JetParameter; +import org.jetbrains.k2js.translate.context.TemporaryVariable; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.general.AbstractTranslator; import org.jetbrains.k2js.translate.general.Translation; @@ -33,11 +35,12 @@ import org.jetbrains.k2js.translate.utils.JsAstUtils; import java.util.ArrayList; import java.util.List; +import static com.google.dart.compiler.util.AstUtil.newSequence; import static org.jetbrains.k2js.translate.utils.BindingUtils.getClassDescriptor; import static org.jetbrains.k2js.translate.utils.BindingUtils.getPropertyDescriptorForConstructorParameter; -import static org.jetbrains.k2js.translate.utils.DescriptorUtils.findAncestorClass; -import static org.jetbrains.k2js.translate.utils.DescriptorUtils.getSuperclassDescriptors; +import static org.jetbrains.k2js.translate.utils.DescriptorUtils.*; import static org.jetbrains.k2js.translate.utils.PsiUtils.getPrimaryConstructorParameters; +import static org.jetbrains.k2js.translate.utils.TranslationUtils.getThisObject; /** * @author Pavel Talanov @@ -57,7 +60,13 @@ public final class ClassTranslator extends AbstractTranslator { @NotNull public static JsInvocation generateClassCreationExpression(@NotNull JetClassOrObject classDeclaration, @NotNull TranslationContext context) { - return (new ClassTranslator(classDeclaration, context)).translateClass(); + return (new ClassTranslator(classDeclaration, context)).translateClassOrObjectCreation(); + } + + @NotNull + public static JsExpression generateObjectLiteralExpression(@NotNull JetObjectLiteralExpression objectLiteralExpression, + @NotNull TranslationContext context) { + return (new ClassTranslator(objectLiteralExpression.getObjectDeclaration(), context)).translateObjectLiteralExpression(); } @NotNull @@ -76,7 +85,25 @@ public final class ClassTranslator extends AbstractTranslator { } @NotNull - private JsInvocation translateClass() { + private JsExpression translateObjectLiteralExpression() { + ClassDescriptor containingClass = getContainingClass(descriptor); + if (containingClass == null) { + return translateClassOrObjectCreation(); + } + return translateAsObjectCreationExpressionWithEnclosingThisSaved(containingClass); + } + + @NotNull + private JsExpression translateAsObjectCreationExpressionWithEnclosingThisSaved(@NotNull ClassDescriptor containingClass) { + TemporaryVariable thisAlias = context().declareTemporary(getThisObject(context(), containingClass)); + aliaser().setAliasForThis(containingClass, thisAlias.name()); + JsBinaryOperation result = newSequence(thisAlias.assignmentExpression(), translateClassOrObjectCreation()); + aliaser().removeAliasForThis(containingClass); + return result; + } + + @NotNull + private JsInvocation translateClassOrObjectCreation() { JsInvocation jsClassDeclaration = classCreateMethodInvocation(); addSuperclassReferences(jsClassDeclaration); addClassOwnDeclarations(jsClassDeclaration); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java index 9798eaadff7..fd670f6d94c 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java @@ -399,7 +399,7 @@ public final class ExpressionVisitor extends TranslatorVisitor { @NotNull public JsNode visitObjectLiteralExpression(@NotNull JetObjectLiteralExpression expression, @NotNull TranslationContext context) { - return ClassTranslator.generateClassCreationExpression(expression.getObjectDeclaration(), context); + return ClassTranslator.generateObjectLiteralExpression(expression, context); } @Override diff --git a/js/js.translator/testFiles/expression/misc/cases/KT-1361-1.kt b/js/js.translator/testFiles/expression/misc/cases/KT-1361-1.kt new file mode 100644 index 00000000000..c8b1513a002 --- /dev/null +++ b/js/js.translator/testFiles/expression/misc/cases/KT-1361-1.kt @@ -0,0 +1,21 @@ +//This is not treated correctly when object is created. + +package foo + +class B { + + val d = true + + fun f() : Boolean { + val c = object { + fun foo() : Boolean { + return d + } + } + return c.foo() + } +} + +fun box() : Boolean { + return B().f() +} \ No newline at end of file diff --git a/js/js.translator/testFiles/expression/misc/cases/KT-1361-2.kt b/js/js.translator/testFiles/expression/misc/cases/KT-1361-2.kt new file mode 100644 index 00000000000..809c2e0907a --- /dev/null +++ b/js/js.translator/testFiles/expression/misc/cases/KT-1361-2.kt @@ -0,0 +1,52 @@ +package foo + +class Data(val rawData : Array, val width : Int, val height : Int) { + fun get(x : Int, y : Int) : ColorLike { + return object : ColorLike { + override val red: Int = rawData[(y * width + x) * 4 + 0]; + override val green: Int = rawData[(y * width + x) * 4 + 1]; + override val blue: Int = rawData[(y * width + x) * 4 + 2]; + } + } + + fun set(x : Int, y : Int, color : ColorLike) { + rawData[(y * width + x) * 4 + 0] = color.red; + rawData[(y * width + x) * 4 + 1] = color.green; + rawData[(y * width + x) * 4 + 2] = color.blue; + } + + fun each(block : (x : Int, y : Int)->Unit) { + for (x in 0..width - 1) { + for (y in 0..height - 1) { + block(x, y) + } + } + } +} + +class Color(r : Int, g : Int, b : Int) : ColorLike { + override val red: Int = r + override val green: Int = g + override val blue: Int = b +} + +trait ColorLike { + val red : Int; + val green : Int; + val blue : Int; +} + + +fun box() : Boolean { + val d = Data(Array(4) {0}, 1, 1) + if (d[0, 0].red != 0) { + return false + } + if (d[0, 0].green != 0) { + return false + } + if (d[0, 0].blue != 0) { + return false + } + return true +} \ No newline at end of file