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();
|
checkFooBoxIsOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testPropertyAssignment() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
protected List<String> additionalJsFiles(@NotNull EcmaVersion ecmaVersion) {
|
protected List<String> additionalJsFiles(@NotNull EcmaVersion ecmaVersion) {
|
||||||
|
|||||||
+10
-6
@@ -359,13 +359,12 @@ public class TranslationContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isConstructorOrDirectScope(DeclarationDescriptor descriptor) {
|
private boolean isConstructorOrDirectScope(DeclarationDescriptor descriptor) {
|
||||||
if (descriptor == declarationDescriptor) {
|
if (declarationDescriptor instanceof ClassDescriptor && !DescriptorUtils.isCompanionObject(declarationDescriptor)) {
|
||||||
return true;
|
return descriptor == declarationDescriptor;
|
||||||
}
|
}
|
||||||
if (declarationDescriptor instanceof ConstructorDescriptor) {
|
else {
|
||||||
return descriptor == declarationDescriptor.getContainingDeclaration();
|
return declarationDescriptor != null && descriptor == DescriptorUtils.getContainingClass(declarationDescriptor);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -392,7 +391,7 @@ public class TranslationContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private DefinitionPlace getDefinitionPlace() {
|
public DefinitionPlace getDefinitionPlace() {
|
||||||
if (definitionPlace != null) return definitionPlace;
|
if (definitionPlace != null) return definitionPlace;
|
||||||
if (parent != null) return parent.getDefinitionPlace();
|
if (parent != null) return parent.getDefinitionPlace();
|
||||||
|
|
||||||
@@ -430,4 +429,9 @@ public class TranslationContext {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public DeclarationDescriptor getDeclarationDescriptor() {
|
||||||
|
return declarationDescriptor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -108,6 +108,7 @@ public class DeclarationBodyVisitor extends TranslatorVisitor<Void> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context = context.newDeclaration(descriptor, context.getDefinitionPlace());
|
||||||
JsPropertyInitializer methodAsPropertyInitializer = Translation.functionTranslator(expression, context).translateAsMethod();
|
JsPropertyInitializer methodAsPropertyInitializer = Translation.functionTranslator(expression, context).translateAsMethod();
|
||||||
result.add(methodAsPropertyInitializer);
|
result.add(methodAsPropertyInitializer);
|
||||||
return null;
|
return null;
|
||||||
@@ -116,6 +117,7 @@ public class DeclarationBodyVisitor extends TranslatorVisitor<Void> {
|
|||||||
@Override
|
@Override
|
||||||
public Void visitProperty(@NotNull KtProperty expression, TranslationContext context) {
|
public Void visitProperty(@NotNull KtProperty expression, TranslationContext context) {
|
||||||
PropertyDescriptor propertyDescriptor = BindingUtils.getPropertyDescriptor(context.bindingContext(), expression);
|
PropertyDescriptor propertyDescriptor = BindingUtils.getPropertyDescriptor(context.bindingContext(), expression);
|
||||||
|
context.newDeclaration(propertyDescriptor, context.getDefinitionPlace());
|
||||||
PropertyTranslatorKt.translateAccessors(propertyDescriptor, expression, result, context);
|
PropertyTranslatorKt.translateAccessors(propertyDescriptor, expression, result, context);
|
||||||
return null;
|
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.JsBlock;
|
||||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||||
import org.jetbrains.annotations.NotNull;
|
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.DeclarationDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
|
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.context.TranslationContext;
|
||||||
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
|
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
|
||||||
import org.jetbrains.kotlin.js.translate.reference.AccessTranslationUtils;
|
import org.jetbrains.kotlin.js.translate.reference.AccessTranslationUtils;
|
||||||
import org.jetbrains.kotlin.js.translate.reference.AccessTranslator;
|
import org.jetbrains.kotlin.js.translate.reference.AccessTranslator;
|
||||||
import org.jetbrains.kotlin.js.translate.reference.BackingFieldAccessTranslator;
|
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.getDescriptorForReferenceExpression;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.isVariableReassignment;
|
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.isVariableReassignment;
|
||||||
@@ -72,7 +72,7 @@ public abstract class AssignmentTranslator extends AbstractTranslator {
|
|||||||
JsBlock rightBlock = new JsBlock();
|
JsBlock rightBlock = new JsBlock();
|
||||||
this.right = translateRightExpression(context, expression, rightBlock);
|
this.right = translateRightExpression(context, expression, rightBlock);
|
||||||
|
|
||||||
if (isValProperty(left, context)) {
|
if (isReferenceToBackingFieldFromConstructor(left, context)) {
|
||||||
KtSimpleNameExpression simpleName = getSimpleName(left);
|
KtSimpleNameExpression simpleName = getSimpleName(left);
|
||||||
assert simpleName != null;
|
assert simpleName != null;
|
||||||
this.accessTranslator = BackingFieldAccessTranslator.newInstance(simpleName, context);
|
this.accessTranslator = BackingFieldAccessTranslator.newInstance(simpleName, context);
|
||||||
@@ -83,17 +83,45 @@ public abstract class AssignmentTranslator extends AbstractTranslator {
|
|||||||
context.addStatementsToCurrentBlockFrom(rightBlock);
|
context.addStatementsToCurrentBlockFrom(rightBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isValProperty(
|
private static boolean isReferenceToBackingFieldFromConstructor(
|
||||||
@NotNull KtExpression expression,
|
@NotNull KtExpression expression,
|
||||||
@NotNull TranslationContext context
|
@NotNull TranslationContext context
|
||||||
) {
|
) {
|
||||||
KtSimpleNameExpression simpleNameExpression = getSimpleName(expression);
|
if (expression instanceof KtSimpleNameExpression) {
|
||||||
|
KtSimpleNameExpression nameExpression = (KtSimpleNameExpression) expression;
|
||||||
if (simpleNameExpression != null) {
|
DeclarationDescriptor descriptor = getDescriptorForReferenceExpression(context.bindingContext(), nameExpression);
|
||||||
DeclarationDescriptor descriptor = getDescriptorForReferenceExpression(context.bindingContext(), simpleNameExpression);
|
return isReferenceToBackingFieldFromConstructor(descriptor, context);
|
||||||
return descriptor instanceof PropertyDescriptor && !((PropertyDescriptor) descriptor).isVar();
|
}
|
||||||
|
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;
|
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