diff --git a/.idea/misc.xml b/.idea/misc.xml index b60725bcb96..e09964cae49 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,11 +1,9 @@ - - + - + + + + + + + + + + @@ -24,68 +33,23 @@ + + + org.jetbrains.k2js.declarations.* + org.jetbrains.k2js.generate.* + org.jetbrains.k2js.translate.* + org.jetbrains.k2js.utils.* + + - - - - - - - - - + - + - - + + - - - - - - - - - - - - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + + + + + + + + + + @@ -237,91 +199,46 @@ - - + + - + - - + + - + - - + + - + - - + + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -348,22 +265,22 @@ @@ -406,6 +323,21 @@ + + + + + + + + + + + @@ -452,7 +384,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - @@ -781,6 +552,7 @@ + @@ -792,21 +564,22 @@ + + - - - + + + + + + + + + + + + + + + + + + + + + + + - + + + + + - + + + + + - + + + + + + + + + + + + + - - - - - - - @@ -936,6 +767,14 @@ + + + + + + + + + + + + - - - - - + + + + + localhost @@ -1041,25 +893,27 @@ - + - + - - - + + + + + + + - - - - + + - - + + @@ -1092,8 +946,14 @@ @@ -1140,122 +1000,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/translator/src/org/jetbrains/k2js/translate/BindingUtils.java b/translator/src/org/jetbrains/k2js/translate/BindingUtils.java index c23af55bffb..cea0f6f2076 100644 --- a/translator/src/org/jetbrains/k2js/translate/BindingUtils.java +++ b/translator/src/org/jetbrains/k2js/translate/BindingUtils.java @@ -19,6 +19,7 @@ import java.util.List; * This class contains some code related to BindingContext use. Intention is not to pollute other classes. */ public final class BindingUtils { + private BindingUtils() { } diff --git a/translator/src/org/jetbrains/k2js/translate/ExpressionVisitor.java b/translator/src/org/jetbrains/k2js/translate/ExpressionVisitor.java index 32530e12aae..22dfd364f83 100644 --- a/translator/src/org/jetbrains/k2js/translate/ExpressionVisitor.java +++ b/translator/src/org/jetbrains/k2js/translate/ExpressionVisitor.java @@ -44,7 +44,7 @@ public final class ExpressionVisitor extends TranslatorVisitor { public JsNode visitBlockExpression(@NotNull JetBlockExpression jetBlock, @NotNull TranslationContext context) { List statements = jetBlock.getStatements(); JsBlock jsBlock = new JsBlock(); - TranslationContext newContext = context.newBlock(); + TranslationContext newContext = context.newBlock(jsBlock); for (JetElement statement : statements) { assert statement instanceof JetExpression : "Elements in JetBlockExpression " + "should be of type JetExpression"; diff --git a/translator/src/org/jetbrains/k2js/translate/OperationTranslator.java b/translator/src/org/jetbrains/k2js/translate/OperationTranslator.java index 8a16ccd3af6..f4a6efdb004 100644 --- a/translator/src/org/jetbrains/k2js/translate/OperationTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/OperationTranslator.java @@ -26,16 +26,24 @@ public final class OperationTranslator extends AbstractTranslator { } @NotNull - JsPostfixOperation translatePostfixOperation(@NotNull JetPostfixExpression expression) { - JsUnaryOperator operator = OperatorTable.getUnaryOperator(getOperationToken(expression)); + JsExpression translatePostfixOperation(@NotNull JetPostfixExpression expression) { JsExpression baseExpression = translateBaseExpression(expression); + JsNameRef operationReference = getOverloadedOperationReference(expression); + if (operationReference != null) { + return overloadedMethodInvocation(baseExpression, operationReference); + } + JsUnaryOperator operator = OperatorTable.getUnaryOperator(getOperationToken(expression)); return new JsPostfixOperation(operator, baseExpression); } @NotNull - JsPrefixOperation translatePrefixOperation(@NotNull JetPrefixExpression expression) { - JsUnaryOperator operator = OperatorTable.getUnaryOperator(getOperationToken(expression)); + JsExpression translatePrefixOperation(@NotNull JetPrefixExpression expression) { JsExpression baseExpression = translateBaseExpression(expression); + JsNameRef operationReference = getOverloadedOperationReference(expression); + if (operationReference != null) { + return overloadedMethodInvocation(baseExpression, operationReference); + } + JsUnaryOperator operator = OperatorTable.getUnaryOperator(getOperationToken(expression)); return new JsPrefixOperation(operator, baseExpression); } @@ -46,6 +54,12 @@ public final class OperationTranslator extends AbstractTranslator { return Translation.translateAsExpression(baseExpression, translationContext()); } + @NotNull + private JsExpression overloadedMethodInvocation(@NotNull JsExpression base, @NotNull JsNameRef operationReference) { + AstUtil.setQualifier(operationReference, base); + return AstUtil.newInvocation(operationReference); + } + @NotNull private JetToken getOperationToken(@NotNull JetUnaryExpression expression) { JetSimpleNameExpression operationExpression = expression.getOperationSign(); @@ -104,14 +118,13 @@ public final class OperationTranslator extends AbstractTranslator { } private JsExpression overloadedMethodInvocation(JsExpression left, JsExpression right, JsNameRef operationReference) { - operationReference.setQualifier(left); + AstUtil.setQualifier(operationReference, left); return AstUtil.newInvocation(operationReference, right); } @Nullable - private JsNameRef getOverloadedOperationReference(@NotNull JetBinaryExpression expression) { - DeclarationDescriptor operationDescriptor = BindingUtils.getDescriptorForReferenceExpression - (translationContext().bindingContext(), expression.getOperationReference()); + private JsNameRef getOverloadedOperationReference(@NotNull JetExpression expression) { + DeclarationDescriptor operationDescriptor = getOperationDescriptor(expression); if (operationDescriptor == null) { return null; } @@ -121,6 +134,20 @@ public final class OperationTranslator extends AbstractTranslator { return translationContext().getNameForDescriptor(operationDescriptor).makeRef(); } + @Nullable + private DeclarationDescriptor getOperationDescriptor(@NotNull JetExpression expression) { + JetSimpleNameExpression operationReference = null; + if (expression instanceof JetBinaryExpression) { + operationReference = ((JetBinaryExpression) expression).getOperationReference(); + } + if (expression instanceof JetUnaryExpression) { + operationReference = ((JetUnaryExpression) expression).getOperationSign(); + } + assert operationReference != null : "should be applied only to unary or binary operations"; + return BindingUtils.getDescriptorForReferenceExpression + (translationContext().bindingContext(), operationReference); + } + @NotNull private JsExpression translateRightExpression(@NotNull JetBinaryExpression expression) { JetExpression rightExpression = expression.getRight(); diff --git a/translator/src/org/jetbrains/k2js/translate/Translation.java b/translator/src/org/jetbrains/k2js/translate/Translation.java index 27b8e3631ab..0ce9bc0f75b 100644 --- a/translator/src/org/jetbrains/k2js/translate/Translation.java +++ b/translator/src/org/jetbrains/k2js/translate/Translation.java @@ -89,7 +89,7 @@ public final class Translation { public static void generateAst(@NotNull JsProgram result, @NotNull BindingContext bindingContext, @NotNull Declarations declarations, @NotNull JetNamespace namespace) { JsBlock block = result.getFragmentBlock(0); - TranslationContext context = TranslationContext.rootContext(result, bindingContext, declarations); + TranslationContext context = TranslationContext.rootContext(result, bindingContext, declarations, block); block.addStatement(Translation.translateNamespace(namespace, context)); } diff --git a/translator/src/org/jetbrains/k2js/translate/TranslationContext.java b/translator/src/org/jetbrains/k2js/translate/TranslationContext.java index 76244da762f..79df53a37ce 100644 --- a/translator/src/org/jetbrains/k2js/translate/TranslationContext.java +++ b/translator/src/org/jetbrains/k2js/translate/TranslationContext.java @@ -1,9 +1,6 @@ package org.jetbrains.k2js.translate; -import com.google.dart.compiler.backend.js.ast.JsName; -import com.google.dart.compiler.backend.js.ast.JsNameRef; -import com.google.dart.compiler.backend.js.ast.JsProgram; -import com.google.dart.compiler.backend.js.ast.JsScope; +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; @@ -35,10 +32,10 @@ public final class TranslationContext { @NotNull public static TranslationContext rootContext(@NotNull JsProgram program, @NotNull BindingContext bindingContext, - @NotNull Declarations extractor) { + @NotNull Declarations extractor, @NotNull JsBlock block) { JsScope rootScope = program.getRootScope(); Scopes scopes = new Scopes(rootScope, rootScope, rootScope); - return new TranslationContext(null, program, bindingContext, scopes, extractor); + return new TranslationContext(null, program, bindingContext, scopes, extractor, block); } @NotNull @@ -51,16 +48,19 @@ public final class TranslationContext { private final JsName namespaceName; @NotNull private final Declarations declarations; + @NotNull + private final JsBlock block; private TranslationContext(@Nullable JsName namespaceName, @NotNull JsProgram program, @NotNull BindingContext bindingContext, @NotNull Scopes scopes, - @NotNull Declarations declarations) { + @NotNull Declarations declarations, @NotNull JsBlock block) { this.program = program; this.bindingContext = bindingContext; this.namespaceName = namespaceName; this.scopes = scopes; this.declarations = declarations; + this.block = block; } @NotNull @@ -73,14 +73,14 @@ public final class TranslationContext { JsScope namespaceScope = declarations.getScope(descriptor); JsName namespaceName = scopes.enclosingScope.findExistingName(descriptor.getName()); Scopes newScopes = new Scopes(namespaceScope, namespaceScope, namespaceScope); - return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations); + return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations, block); } @NotNull - public TranslationContext newBlock() { + public TranslationContext newBlock(@NotNull JsBlock newBlock) { Scopes newScopes = new Scopes(new JsScope (scopes.enclosingScope, "Scope for a block"), scopes.classScope, scopes.namespaceScope); - return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations); + return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations, newBlock); } @NotNull @@ -92,7 +92,7 @@ public final class TranslationContext { public TranslationContext newClass(@NotNull ClassDescriptor descriptor) { JsScope classScope = declarations.getScope(descriptor); Scopes newScopes = new Scopes(classScope, classScope, scopes.namespaceScope); - return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations); + return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations, block); } @NotNull @@ -114,20 +114,20 @@ public final class TranslationContext { public TranslationContext newFunctionDeclaration(@NotNull FunctionDescriptor descriptor) { JsScope functionScope = declarations.getScope(descriptor); Scopes newScopes = new Scopes(functionScope, scopes.classScope, scopes.namespaceScope); - return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations); + return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations, block); } @NotNull public TranslationContext newFunctionLiteral(@NotNull JsScope correspondingScope) { Scopes newScopes = new Scopes(correspondingScope, scopes.classScope, scopes.namespaceScope); - return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations); + return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations, block); } // Note: Should be used if and only if scope has no corresponding descriptor @NotNull public TranslationContext newEnclosingScope(@NotNull JsScope enclosingScope) { Scopes newScopes = new Scopes(enclosingScope, scopes.classScope, scopes.namespaceScope); - return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations); + return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations, block); } diff --git a/translator/test/org/jetbrains/k2js/test/OperatorOverloadingTest.java b/translator/test/org/jetbrains/k2js/test/OperatorOverloadingTest.java index 2c72d645120..01e57d2b0cc 100644 --- a/translator/test/org/jetbrains/k2js/test/OperatorOverloadingTest.java +++ b/translator/test/org/jetbrains/k2js/test/OperatorOverloadingTest.java @@ -18,4 +18,14 @@ public class OperatorOverloadingTest extends TranslationTest { public void plusOverload() throws Exception { testFooBoxIsTrue("plusOverload.kt"); } + + @Test + public void postfixInc() throws Exception { + testFooBoxIsTrue("postfixIncOverload.kt"); + } + + @Test + public void prefixInc() throws Exception { + testFooBoxIsTrue("prefixDecOverload.kt"); + } } diff --git a/translator/testFiles/operatorOverloading/cases/postfixIncOverload.kt b/translator/testFiles/operatorOverloading/cases/postfixIncOverload.kt new file mode 100644 index 00000000000..184031c4a84 --- /dev/null +++ b/translator/testFiles/operatorOverloading/cases/postfixIncOverload.kt @@ -0,0 +1,16 @@ +namespace foo + +class MyInt() { + var b = 0 + + fun inc() { + b = b + 1; + } +} + + +fun box() : Boolean { + var c = MyInt() + c++; + return (c.b == 1); +} \ No newline at end of file diff --git a/translator/testFiles/operatorOverloading/cases/prefixDecOverload.kt b/translator/testFiles/operatorOverloading/cases/prefixDecOverload.kt new file mode 100644 index 00000000000..f3f674e8ee0 --- /dev/null +++ b/translator/testFiles/operatorOverloading/cases/prefixDecOverload.kt @@ -0,0 +1,16 @@ +namespace foo + +class MyInt() { + var b = 0 + + fun dec() { + b = b + 1; + } +} + + +fun box() : Boolean { + var c = MyInt() + --c; + return (c.b == 1); +} \ No newline at end of file