KT-10785 Fixed. Change predicate that decides whether to dereference assignment target as a property accessor or as a backing field.
This commit is contained in:
@@ -98,6 +98,10 @@ public final class PropertyAccessTest extends SingleFileTranslationTest {
|
||||
checkFooBoxIsOk();
|
||||
}
|
||||
|
||||
public void testPropertyAssignment() throws Exception {
|
||||
checkFooBoxIsOk();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
protected List<String> additionalJsFiles(@NotNull EcmaVersion ecmaVersion) {
|
||||
|
||||
+10
-6
@@ -359,13 +359,12 @@ public class TranslationContext {
|
||||
}
|
||||
|
||||
private boolean isConstructorOrDirectScope(DeclarationDescriptor descriptor) {
|
||||
if (descriptor == declarationDescriptor) {
|
||||
return true;
|
||||
if (declarationDescriptor instanceof ClassDescriptor && !DescriptorUtils.isCompanionObject(declarationDescriptor)) {
|
||||
return descriptor == declarationDescriptor;
|
||||
}
|
||||
if (declarationDescriptor instanceof ConstructorDescriptor) {
|
||||
return descriptor == declarationDescriptor.getContainingDeclaration();
|
||||
else {
|
||||
return declarationDescriptor != null && descriptor == DescriptorUtils.getContainingClass(declarationDescriptor);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -392,7 +391,7 @@ public class TranslationContext {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private DefinitionPlace getDefinitionPlace() {
|
||||
public DefinitionPlace getDefinitionPlace() {
|
||||
if (definitionPlace != null) return definitionPlace;
|
||||
if (parent != null) return parent.getDefinitionPlace();
|
||||
|
||||
@@ -430,4 +429,9 @@ public class TranslationContext {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public DeclarationDescriptor getDeclarationDescriptor() {
|
||||
return declarationDescriptor;
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -108,6 +108,7 @@ public class DeclarationBodyVisitor extends TranslatorVisitor<Void> {
|
||||
return null;
|
||||
}
|
||||
|
||||
context = context.newDeclaration(descriptor, context.getDefinitionPlace());
|
||||
JsPropertyInitializer methodAsPropertyInitializer = Translation.functionTranslator(expression, context).translateAsMethod();
|
||||
result.add(methodAsPropertyInitializer);
|
||||
return null;
|
||||
@@ -116,6 +117,7 @@ public class DeclarationBodyVisitor extends TranslatorVisitor<Void> {
|
||||
@Override
|
||||
public Void visitProperty(@NotNull KtProperty expression, TranslationContext context) {
|
||||
PropertyDescriptor propertyDescriptor = BindingUtils.getPropertyDescriptor(context.bindingContext(), expression);
|
||||
context.newDeclaration(propertyDescriptor, context.getDefinitionPlace());
|
||||
PropertyTranslatorKt.translateAccessors(propertyDescriptor, expression, result, context);
|
||||
return null;
|
||||
}
|
||||
|
||||
+41
-13
@@ -19,18 +19,18 @@ package org.jetbrains.kotlin.js.translate.operation;
|
||||
import com.google.dart.compiler.backend.js.ast.JsBlock;
|
||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
|
||||
import org.jetbrains.kotlin.lexer.KtToken;
|
||||
import org.jetbrains.kotlin.psi.KtBinaryExpression;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression;
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions;
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
||||
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
|
||||
import org.jetbrains.kotlin.js.translate.reference.AccessTranslationUtils;
|
||||
import org.jetbrains.kotlin.js.translate.reference.AccessTranslator;
|
||||
import org.jetbrains.kotlin.js.translate.reference.BackingFieldAccessTranslator;
|
||||
import org.jetbrains.kotlin.lexer.KtToken;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions;
|
||||
|
||||
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getDescriptorForReferenceExpression;
|
||||
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.isVariableReassignment;
|
||||
@@ -72,7 +72,7 @@ public abstract class AssignmentTranslator extends AbstractTranslator {
|
||||
JsBlock rightBlock = new JsBlock();
|
||||
this.right = translateRightExpression(context, expression, rightBlock);
|
||||
|
||||
if (isValProperty(left, context)) {
|
||||
if (isReferenceToBackingFieldFromConstructor(left, context)) {
|
||||
KtSimpleNameExpression simpleName = getSimpleName(left);
|
||||
assert simpleName != null;
|
||||
this.accessTranslator = BackingFieldAccessTranslator.newInstance(simpleName, context);
|
||||
@@ -83,17 +83,45 @@ public abstract class AssignmentTranslator extends AbstractTranslator {
|
||||
context.addStatementsToCurrentBlockFrom(rightBlock);
|
||||
}
|
||||
|
||||
private static boolean isValProperty(
|
||||
private static boolean isReferenceToBackingFieldFromConstructor(
|
||||
@NotNull KtExpression expression,
|
||||
@NotNull TranslationContext context
|
||||
) {
|
||||
KtSimpleNameExpression simpleNameExpression = getSimpleName(expression);
|
||||
|
||||
if (simpleNameExpression != null) {
|
||||
DeclarationDescriptor descriptor = getDescriptorForReferenceExpression(context.bindingContext(), simpleNameExpression);
|
||||
return descriptor instanceof PropertyDescriptor && !((PropertyDescriptor) descriptor).isVar();
|
||||
if (expression instanceof KtSimpleNameExpression) {
|
||||
KtSimpleNameExpression nameExpression = (KtSimpleNameExpression) expression;
|
||||
DeclarationDescriptor descriptor = getDescriptorForReferenceExpression(context.bindingContext(), nameExpression);
|
||||
return isReferenceToBackingFieldFromConstructor(descriptor, context);
|
||||
}
|
||||
else if (expression instanceof KtDotQualifiedExpression) {
|
||||
KtDotQualifiedExpression qualifiedExpression = (KtDotQualifiedExpression) expression;
|
||||
if (qualifiedExpression.getReceiverExpression() instanceof KtThisExpression &&
|
||||
qualifiedExpression.getSelectorExpression() instanceof KtSimpleNameExpression) {
|
||||
KtSimpleNameExpression nameExpression = (KtSimpleNameExpression) qualifiedExpression.getSelectorExpression();
|
||||
DeclarationDescriptor descriptor = getDescriptorForReferenceExpression(context.bindingContext(), nameExpression);
|
||||
return isReferenceToBackingFieldFromConstructor(descriptor, context);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isReferenceToBackingFieldFromConstructor(
|
||||
@Nullable DeclarationDescriptor descriptor,
|
||||
@NotNull TranslationContext context
|
||||
) {
|
||||
if (!(descriptor instanceof PropertyDescriptor)) {
|
||||
return false;
|
||||
}
|
||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||
|
||||
if (!(context.getDeclarationDescriptor() instanceof ClassDescriptor)) {
|
||||
return false;
|
||||
}
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) context.getDeclarationDescriptor();
|
||||
|
||||
if (classDescriptor != propertyDescriptor.getContainingDeclaration()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !propertyDescriptor.isVar();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// See https://youtrack.jetbrains.com/issue/KT-10785
|
||||
package foo
|
||||
|
||||
class A(var x: Int) {
|
||||
operator fun plusAssign(other: A) {
|
||||
x += other.x
|
||||
}
|
||||
}
|
||||
|
||||
object B {
|
||||
private var holder = A(42)
|
||||
|
||||
val foo: A
|
||||
get() = holder
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
B.foo += A(23)
|
||||
if (B.foo.x != 65) return "failed: ${B.foo.x}"
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user