Support increment and '+=' on local delegated properties in JS backend

This commit is contained in:
Mikhael Bogdanov
2016-05-06 16:16:44 +03:00
parent ec632c37ab
commit e207b56009
6 changed files with 61 additions and 8 deletions
@@ -35,6 +35,14 @@ public class DelegatePropertyTest extends SingleFileTranslationTest {
checkFooBoxIsOk();
}
public void testLocalVarInc() throws Exception {
checkFooBoxIsOk();
}
public void testLocalVarPlusAssign() throws Exception {
checkFooBoxIsOk();
}
public void testCapturedLocalVal() throws Exception {
checkFooBoxIsOk();
}
@@ -21,13 +21,14 @@ import com.google.dart.compiler.backend.js.ast.JsBinaryOperator;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
import org.jetbrains.kotlin.lexer.KtToken;
import org.jetbrains.kotlin.psi.KtBinaryExpression;
import org.jetbrains.kotlin.psi.KtSimpleNameExpression;
import org.jetbrains.kotlin.types.expressions.OperatorConventions;
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.getOperationToken;
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.isAssignment;
import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.isSimpleNameExpressionNotDelegatedLocalVar;
public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
@@ -53,7 +54,7 @@ public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
@NotNull
private JsExpression translateAsAssignmentOperation() {
if (expression.getLeft() instanceof KtSimpleNameExpression) {
if (isSimpleNameExpressionNotDelegatedLocalVar(expression.getLeft(), context())) {
return translateAsPlainAssignmentOperation();
}
return translateAsAssignToCounterpart();
@@ -21,11 +21,11 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.lexer.KtToken;
import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.psi.KtSimpleNameExpression;
import org.jetbrains.kotlin.psi.KtUnaryExpression;
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.getOperationToken;
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.isPrefix;
import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.isSimpleNameExpressionNotDelegatedLocalVar;
public final class IntrinsicIncrementTranslator extends IncrementTranslator {
@@ -44,16 +44,12 @@ public final class IntrinsicIncrementTranslator extends IncrementTranslator {
@NotNull
private JsExpression translate() {
if (isPrimitiveExpressionIncrement()) {
if (isSimpleNameExpressionNotDelegatedLocalVar(expression.getBaseExpression(), context())) {
return primitiveExpressionIncrement();
}
return translateIncrementExpression();
}
private boolean isPrimitiveExpressionIncrement() {
return expression.getBaseExpression() instanceof KtSimpleNameExpression;
}
@NotNull
private JsExpression primitiveExpressionIncrement() {
JsUnaryOperator operator = OperatorTable.getUnaryOperator(getOperationToken(expression));
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.js.translate.context.TemporaryConstVariable;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.general.Translation;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.types.KotlinType;
@@ -295,4 +296,12 @@ public final class TranslationUtils {
}
return suggestedName;
}
public static boolean isSimpleNameExpressionNotDelegatedLocalVar(@Nullable KtExpression expression, @NotNull TranslationContext context) {
if (!(expression instanceof KtSimpleNameExpression)) {
return false;
}
DeclarationDescriptor descriptor = context.bindingContext().get(BindingContext.REFERENCE_TARGET, ((KtSimpleNameExpression) expression));
return !(descriptor instanceof LocalVariableDescriptor) || !((LocalVariableDescriptor) descriptor).isDelegated();
}
}
@@ -0,0 +1,19 @@
package foo
import kotlin.reflect.KProperty
class Delegate {
var inner = 1
operator fun getValue(t: Any?, p: KProperty<*>): Int = inner
operator fun setValue(t: Any?, p: KProperty<*>, i: Int) {
inner = i
}
}
fun box(): String {
var prop: Int by Delegate()
var result = prop++
if (result != 1) return "fail increment result: $prop"
if (prop != 2) return "fail increment: $prop"
return "OK"
}
@@ -0,0 +1,20 @@
//TODO: reuse same tests from JVM backend
package foo
import kotlin.reflect.KProperty
class Delegate {
var inner = 1
operator fun getValue(t: Any?, p: KProperty<*>): Int = inner
operator fun setValue(t: Any?, p: KProperty<*>, i: Int) {
inner = i
}
}
fun box(): String {
var prop: Int by Delegate()
prop += 1
if (prop != 2) return "fail : $prop"
return "OK"
}