implement CallType logic

This commit is contained in:
Pavel Talanov
2012-02-10 22:34:34 +04:00
parent 893d983861
commit 254ed6de14
16 changed files with 173 additions and 142 deletions
@@ -126,6 +126,14 @@ public class StaticContext {
@Nullable
public JsNameRef getQualifierForDescriptor(@NotNull DeclarationDescriptor descriptor) {
//TODO: refactor
if (descriptor instanceof PropertyDescriptor) {
return null;
}
if (isVariableAsFunction(descriptor)) {
return null;
}
//TODO: hack!
if (AnnotationsUtils.isNativeObject(descriptor)) {
return null;
@@ -17,10 +17,7 @@ import org.jetbrains.k2js.translate.general.TranslatorVisitor;
import org.jetbrains.k2js.translate.operation.BinaryOperationTranslator;
import org.jetbrains.k2js.translate.operation.IncrementTranslator;
import org.jetbrains.k2js.translate.operation.UnaryOperationTranslator;
import org.jetbrains.k2js.translate.reference.AccessTranslator;
import org.jetbrains.k2js.translate.reference.CallTranslator;
import org.jetbrains.k2js.translate.reference.QualifiedExpressionTranslator;
import org.jetbrains.k2js.translate.reference.ReferenceTranslator;
import org.jetbrains.k2js.translate.reference.*;
import org.jetbrains.k2js.translate.utils.BindingUtils;
import org.jetbrains.k2js.translate.utils.TranslationUtils;
@@ -135,7 +132,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
@NotNull
public JsNode visitCallExpression(@NotNull JetCallExpression expression,
@NotNull TranslationContext context) {
return CallTranslator.translate(expression, null, context);
return CallTranslator.translate(expression, null, CallType.NORMAL, context);
}
@Override
@@ -260,7 +257,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
@NotNull
public JsNode visitDotQualifiedExpression(@NotNull JetDotQualifiedExpression expression,
@NotNull TranslationContext context) {
return QualifiedExpressionTranslator.translateDotQualifiedExpression(expression, context);
return QualifiedExpressionTranslator.translateQualifiedExpression(expression, context);
}
@Override
@@ -289,7 +286,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
@NotNull
public JsNode visitSafeQualifiedExpression(@NotNull JetSafeQualifiedExpression expression,
@NotNull TranslationContext context) {
return QualifiedExpressionTranslator.translateSafeQualifiedExpression(expression, context);
return QualifiedExpressionTranslator.translateQualifiedExpression(expression, context);
}
@Override
@@ -13,6 +13,7 @@ import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.general.Translation;
import org.jetbrains.k2js.translate.reference.CallTranslator;
import org.jetbrains.k2js.translate.reference.CallType;
import static org.jetbrains.k2js.translate.utils.BindingUtils.*;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopBody;
@@ -66,13 +67,13 @@ public final class ForTranslator extends AbstractTranslator {
@NotNull
private JsExpression nextMethodInvocation(@NotNull TemporaryVariable iterator) {
FunctionDescriptor nextFunction = getNextFunction(context().bindingContext(), getLoopRange());
return CallTranslator.translate(iterator.nameReference(), nextFunction, context());
return CallTranslator.translate(iterator.nameReference(), nextFunction, CallType.NORMAL, context());
}
@NotNull
private JsExpression hasNextMethodInvocation(@NotNull TemporaryVariable iterator) {
CallableDescriptor hasNextFunction = getHasNextCallable(context().bindingContext(), getLoopRange());
return CallTranslator.translate(iterator.nameReference(), hasNextFunction, context());
return CallTranslator.translate(iterator.nameReference(), hasNextFunction, CallType.NORMAL, context());
}
@NotNull
@@ -80,7 +81,7 @@ public final class ForTranslator extends AbstractTranslator {
JetExpression rangeExpression = getLoopRange();
JsExpression range = Translation.translateAsExpression(rangeExpression, context());
FunctionDescriptor iteratorFunction = getIteratorFunction(context().bindingContext(), rangeExpression);
return CallTranslator.translate(range, iteratorFunction, context());
return CallTranslator.translate(range, iteratorFunction, CallType.NORMAL, context());
}
@NotNull
@@ -24,7 +24,8 @@ public abstract class AccessTranslator extends AbstractTranslator {
return QualifiedExpressionTranslator.getAccessTranslator((JetQualifiedExpression) referenceExpression, context);
}
assert referenceExpression instanceof JetSimpleNameExpression;
return PropertyAccessTranslator.newInstance((JetSimpleNameExpression) referenceExpression, null, context);
return PropertyAccessTranslator.newInstance((JetSimpleNameExpression) referenceExpression,
null, CallType.NORMAL, context);
}
if (referenceExpression instanceof JetArrayAccessExpression) {
return ArrayAccessTranslator.newInstance((JetArrayAccessExpression) referenceExpression, context);
@@ -44,7 +44,7 @@ public final class ArrayAccessTranslator extends AccessTranslator {
ResolvedCall<?> resolvedCall = BindingUtils.getResolvedCall(context().bindingContext(), expression);
List<JsExpression> arguments = translateIndexExpressions();
return CallTranslator.translate(translateArrayExpression(), arguments, resolvedCall,
methodDescriptor, context());
methodDescriptor, CallType.NORMAL, context());
}
@Override
@@ -54,7 +54,7 @@ public final class ArrayAccessTranslator extends AccessTranslator {
List<JsExpression> arguments = translateIndexExpressions();
arguments.add(expression);
return CallTranslator.translate(translateArrayExpression(), arguments, resolvedCall,
methodDescriptor, context());
methodDescriptor, CallType.NORMAL, context());
}
@NotNull
@@ -33,6 +33,19 @@ import static org.jetbrains.k2js.translate.utils.TranslationUtils.*;
//TODO: reorder methods properly
public final class CallTranslator extends AbstractTranslator {
private static class CallParameters {
public CallParameters(@Nullable JsExpression receiver, @NotNull JsExpression functionReference) {
this.receiver = receiver;
this.functionReference = functionReference;
}
@Nullable
public /*var*/ JsExpression receiver;
@NotNull
public /*var*/ JsExpression functionReference;
}
private static final class Builder {
@NotNull
@@ -48,7 +61,7 @@ public final class CallTranslator extends AbstractTranslator {
List<JsExpression> arguments = Collections.emptyList();
ResolvedCall<?> resolvedCall =
getResolvedCall(context.bindingContext(), unaryExpression.getOperationReference());
return new CallTranslator(receiver, null, arguments, resolvedCall, null, context);
return new CallTranslator(receiver, null, arguments, resolvedCall, null, CallType.NORMAL, context);
}
//TODO: method too long
@@ -71,19 +84,20 @@ public final class CallTranslator extends AbstractTranslator {
ResolvedCall<?> resolvedCall =
getResolvedCall(context.bindingContext(), binaryExpression.getOperationReference());
return new CallTranslator(receiver, null, arguments, resolvedCall, null, context);
return new CallTranslator(receiver, null, arguments, resolvedCall, null, CallType.NORMAL, context);
}
@NotNull
private CallTranslator buildFromCallExpression(@NotNull JetCallExpression callExpression,
@Nullable JsExpression receiver) {
@Nullable JsExpression receiver,
@NotNull CallType callType) {
ResolvedCall<?> resolvedCall = getResolvedCallForCallExpression(context.bindingContext(), callExpression);
List<JsExpression> arguments = translateArgumentsForCallExpression(callExpression, context);
JsExpression callee = null;
if (resolvedCall.getCandidateDescriptor() instanceof ExpressionAsFunctionDescriptor) {
callee = Translation.translateAsExpression(getCallee(callExpression), context);
}
return new CallTranslator(receiver, callee, arguments, resolvedCall, null, context);
return new CallTranslator(receiver, callee, arguments, resolvedCall, null, callType, context);
}
@NotNull
@@ -130,25 +144,29 @@ public final class CallTranslator extends AbstractTranslator {
@NotNull
public static JsExpression translate(@Nullable JsExpression receiver,
@NotNull CallableDescriptor descriptor,
@NotNull CallType callType,
@NotNull TranslationContext context) {
return translate(receiver, Collections.<JsExpression>emptyList(),
ResolvedCallImpl.create(descriptor), null, context);
ResolvedCallImpl.create(descriptor), null, callType, context);
}
@NotNull
public static JsExpression translate(@Nullable JsExpression receiver,
@NotNull ResolvedCall<?> resolvedCall,
@Nullable CallableDescriptor descriptorToCall,
@NotNull CallType callType,
@NotNull TranslationContext context) {
return translate(receiver, Collections.<JsExpression>emptyList(), resolvedCall, descriptorToCall, context);
return (new CallTranslator(receiver, null, Collections.<JsExpression>emptyList(), resolvedCall,
descriptorToCall, CallType.SAFE, context)).translate();
}
@NotNull
public static JsExpression translate(@Nullable JsExpression receiver, @NotNull List<JsExpression> arguments,
@NotNull ResolvedCall<?> resolvedCall,
@Nullable CallableDescriptor descriptorToCall,
@NotNull CallType callType,
@NotNull TranslationContext context) {
return (new CallTranslator(receiver, null, arguments, resolvedCall, descriptorToCall, context)).translate();
return (new CallTranslator(receiver, null, arguments, resolvedCall, descriptorToCall, callType, context)).translate();
}
@NotNull
@@ -160,8 +178,9 @@ public final class CallTranslator extends AbstractTranslator {
@NotNull
public static JsExpression translate(@NotNull JetCallExpression callExpression,
@Nullable JsExpression receiver,
@NotNull CallType callType,
@NotNull TranslationContext context) {
return (new Builder(context).buildFromCallExpression(callExpression, receiver)).translate();
return (new Builder(context).buildFromCallExpression(callExpression, receiver, callType)).translate();
}
@NotNull
@@ -200,15 +219,20 @@ public final class CallTranslator extends AbstractTranslator {
@NotNull
private final CallableDescriptor descriptor;
@NotNull
private final CallType callType;
private CallTranslator(@Nullable JsExpression receiver, @Nullable JsExpression callee,
@NotNull List<JsExpression> arguments,
@NotNull ResolvedCall<? extends CallableDescriptor> resolvedCall,
@Nullable CallableDescriptor descriptorToCall,
@NotNull CallType callType,
@NotNull TranslationContext context) {
super(context);
this.receiver = receiver;
this.arguments = arguments;
this.resolvedCall = resolvedCall;
this.callType = callType;
if (descriptorToCall != null) {
this.descriptor = descriptorToCall;
} else {
@@ -234,8 +258,16 @@ public final class CallTranslator extends AbstractTranslator {
return methodCall();
}
private boolean isExtensionFunctionLiteral() {
boolean isLiteral = descriptor instanceof VariableAsFunctionDescriptor
|| descriptor instanceof ExpressionAsFunctionDescriptor;
return isExtensionFunction() && isLiteral;
}
@NotNull
private JsExpression extensionFunctionLiteralCall() {
//TODO: call type
receiver = getExtensionFunctionCallReceiver();
List<JsExpression> callArguments = generateExtensionCallArgumentList();
JsInvocation callMethodInvocation = generateCallMethodInvocation();
@@ -247,21 +279,17 @@ public final class CallTranslator extends AbstractTranslator {
JsNameRef callMethodNameRef = AstUtil.newQualifiedNameRef("call");
JsInvocation callMethodInvocation = new JsInvocation();
callMethodInvocation.setQualifier(callMethodNameRef);
AstUtil.setQualifier(callMethodInvocation, calleeReference());
AstUtil.setQualifier(callMethodInvocation, callParameters().functionReference);
return callMethodInvocation;
}
private boolean isExtensionFunctionLiteral() {
boolean isLiteral = descriptor instanceof VariableAsFunctionDescriptor
|| descriptor instanceof ExpressionAsFunctionDescriptor;
return isExtensionFunction() && isLiteral;
}
@NotNull
private JsExpression extensionFunctionCall() {
receiver = getExtensionFunctionCallReceiver();
List<JsExpression> argumentList = generateExtensionCallArgumentList();
return AstUtil.newInvocation(calleeReference(), argumentList);
JsExpression functionReference = callParameters().functionReference;
AstUtil.setQualifier(functionReference, callParameters().receiver);
return AstUtil.newInvocation(functionReference, argumentList);
}
@NotNull
@@ -295,13 +323,24 @@ public final class CallTranslator extends AbstractTranslator {
assert descriptor instanceof FunctionDescriptor;
FunctionIntrinsic functionIntrinsic =
context().intrinsics().getFunctionIntrinsic((FunctionDescriptor) descriptor);
JsExpression receiverExpression = thisObject();
JsExpression receiverExpression = resolveThisObject(/*do not get qualifier*/false);
return functionIntrinsic.apply(receiverExpression, arguments, context());
}
@NotNull
private JsInvocation methodCall() {
return AstUtil.newInvocation(calleeReference(), arguments);
private JsExpression methodCall() {
final CallParameters callParameters = callParameters();
return callType.constructCall(callParameters.receiver, new CallType.CallConstructor() {
@NotNull
@Override
public JsExpression construct(@Nullable JsExpression receiver) {
JsExpression functionReference = callParameters.functionReference;
if (receiver != null) {
AstUtil.setQualifier(functionReference, receiver);
}
return AstUtil.newInvocation(functionReference, arguments);
}
}, context());
}
private boolean isConstructor() {
@@ -313,54 +352,59 @@ public final class CallTranslator extends AbstractTranslator {
}
@NotNull
private JsExpression calleeReference() {
private CallParameters callParameters() {
if (callee != null) {
return callee;
return new CallParameters(null, callee);
}
if (isVariableDescriptor(descriptor)) {
//TODO: write tests on this cases
VariableDescriptor variableDescriptor =
getVariableDescriptorForVariableAsFunction((VariableAsFunctionDescriptor) descriptor);
if (variableDescriptor instanceof PropertyDescriptor) {
return getterCall((PropertyDescriptor) variableDescriptor);
}
return qualifiedMethodReference(variableDescriptor);
JsExpression thisObject = resolveThisObject(/*just get qualifier if null*/ true);
JsExpression functionReference = functionReference();
return new CallParameters(thisObject, functionReference);
}
@NotNull
private JsExpression functionReference() {
if (!isVariableAsFunction(descriptor)) {
return ReferenceTranslator.translateAsLocalNameReference(descriptor, context());
}
return qualifiedMethodReference(descriptor);
VariableDescriptor variableDescriptor =
getVariableDescriptorForVariableAsFunction((VariableAsFunctionDescriptor) descriptor);
if (variableDescriptor instanceof PropertyDescriptor) {
return getterCall((PropertyDescriptor) variableDescriptor);
}
return ReferenceTranslator.translateAsLocalNameReference(variableDescriptor, context());
}
@NotNull
private JsExpression getterCall(@NotNull PropertyDescriptor variableDescriptor) {
//TODO: call type?
return PropertyAccessTranslator.translateAsPropertyGetterCall(variableDescriptor, resolvedCall, context());
}
@NotNull
private JsExpression qualifiedMethodReference(@NotNull DeclarationDescriptor descriptor) {
JsExpression thisObject = thisObject();
if (thisObject == null) {
return ReferenceTranslator.translateAsFQReference(descriptor, context());
}
JsExpression methodReference = ReferenceTranslator.translateAsLocalNameReference(descriptor, context());
AstUtil.setQualifier(methodReference, thisObject);
return methodReference;
private JsExpression translateAsFunctionWithNoThisObject(@NotNull DeclarationDescriptor descriptor) {
return ReferenceTranslator.translateAsFQReference(descriptor, context());
}
//TODO: refactor
@Nullable
private JsExpression thisObject() {
private JsExpression resolveThisObject(boolean getQualifierIfNull) {
if (receiver != null) {
return receiver;
}
ReceiverDescriptor thisObject = resolvedCall.getThisObject();
if (!thisObject.exists()) {
return null;
if (thisObject.exists()) {
DeclarationDescriptor expectedThisDescriptor = getDeclarationDescriptorForReceiver(thisObject);
return TranslationUtils.getThisObject(context(), expectedThisDescriptor);
}
DeclarationDescriptor expectedThisDescriptor = getDeclarationDescriptorForReceiver(thisObject);
return TranslationUtils.getThisObject(context(), expectedThisDescriptor);
if (getQualifierIfNull) {
return context().getQualifierForDescriptor(descriptor);
}
return null;
}
@NotNull
private JsExpression constructorCall() {
JsExpression constructorReference = ReferenceTranslator.translateAsFQReference(descriptor, context());
JsExpression constructorReference = translateAsFunctionWithNoThisObject(descriptor);
JsNew constructorCall = new JsNew(constructorReference);
constructorCall.setArguments(arguments);
return constructorCall;
@@ -6,6 +6,7 @@ import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsNullLiteral;
import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression;
import org.jetbrains.jet.lang.psi.JetQualifiedExpression;
import org.jetbrains.jet.lang.psi.JetSafeQualifiedExpression;
@@ -21,20 +22,16 @@ public enum CallType {
SAFE {
@NotNull
@Override
JsExpression mutateSelector(@NotNull JsExpression selector, @NotNull TranslationContext context) {
TemporaryVariable temporaryVariable = context.declareTemporary(selector);
return newSequence(temporaryVariable.assignmentExpression(), temporaryVariable.nameReference());
}
@NotNull
@Override
JsExpression mutateExpression(@NotNull JsExpression mutatedSelector,
@NotNull JsExpression expressionWithMutatedSelector,
@NotNull TranslationContext context) {
JsExpression constructCall(@Nullable JsExpression receiver, @NotNull CallConstructor constructor,
@NotNull TranslationContext context) {
assert receiver != null;
TemporaryVariable temporaryVariable = context.declareTemporary(receiver);
JsNullLiteral nullLiteral = context.program().getNullLiteral();
//TODO: find similar not null checks
JsBinaryOperation notNullCheck = AstUtil.notEqual(expressionWithMutatedSelector, nullLiteral);
return new JsConditional(notNullCheck, expressionWithMutatedSelector, nullLiteral);
JsBinaryOperation notNullCheck = AstUtil.notEqual(temporaryVariable.nameReference(), nullLiteral);
JsConditional callMethodIfNotNullElseNull =
new JsConditional(notNullCheck, constructor.construct(temporaryVariable.nameReference()), nullLiteral);
return newSequence(temporaryVariable.assignmentExpression(), callMethodIfNotNullElseNull);
}
},
//TODO: bang qualifier is not implemented in frontend for now
@@ -42,31 +39,18 @@ public enum CallType {
NORMAL {
@NotNull
@Override
JsExpression mutateSelector(@NotNull JsExpression selector, @NotNull TranslationContext context) {
// do not mutate
return selector;
}
@NotNull
@Override
JsExpression mutateExpression(@NotNull JsExpression mutatedSelector,
@NotNull JsExpression expression,
@NotNull TranslationContext context) {
// do not mutate
return expression;
JsExpression constructCall(@Nullable JsExpression receiver, @NotNull CallConstructor constructor,
@NotNull TranslationContext context) {
return constructor.construct(receiver);
}
};
@NotNull
abstract JsExpression mutateSelector(@NotNull JsExpression selector, @NotNull TranslationContext context);
abstract JsExpression constructCall(@Nullable JsExpression receiver, @NotNull CallConstructor constructor,
@NotNull TranslationContext context);
@NotNull
abstract JsExpression mutateExpression(@NotNull JsExpression mutatedSelector,
@NotNull JsExpression expression,
@NotNull TranslationContext context);
@NotNull
public static CallType getCallTypeForQualifierExpression(@NotNull JetQualifiedExpression expression) {
public static CallType getCallTypeForQualifiedExpression(@NotNull JetQualifiedExpression expression) {
if (expression instanceof JetSafeQualifiedExpression) {
return SAFE;
}
@@ -74,4 +58,9 @@ public enum CallType {
return NORMAL;
}
public interface CallConstructor {
@NotNull
JsExpression construct(@Nullable JsExpression receiver);
}
}
@@ -37,24 +37,15 @@ public final class KotlinPropertyAccessTranslator extends PropertyAccessTranslat
@Override
@NotNull
public JsExpression translateAsGet() {
return getterCall();
}
@NotNull
private JsExpression getterCall() {
return CallTranslator.translate(qualifier, resolvedCall, propertyDescriptor.getGetter(), context());
return CallTranslator.translate(qualifier, resolvedCall, propertyDescriptor.getGetter(), getCallType(), context());
}
@Override
@NotNull
public JsExpression translateAsSet(@NotNull JsExpression toSetTo) {
return setterCall(toSetTo);
return CallTranslator.translate(qualifier, Arrays.asList(toSetTo),
resolvedCall, propertyDescriptor.getSetter(), getCallType(), context());
}
@NotNull
private JsExpression setterCall(@NotNull JsExpression toSetTo) {
return CallTranslator.translate(qualifier, Arrays.asList(toSetTo),
resolvedCall, propertyDescriptor.getSetter(), context());
}
}
@@ -36,13 +36,18 @@ public abstract class PropertyAccessTranslator extends AccessTranslator {
@NotNull
public static PropertyAccessTranslator newInstance(@NotNull JetSimpleNameExpression expression,
@Nullable JsExpression qualifier,
@NotNull CallType callType,
@NotNull TranslationContext context) {
PropertyAccessTranslator result;
PropertyDescriptor propertyDescriptor = getPropertyDescriptor(expression, context);
if (isNativeObject(propertyDescriptor) || isBackingFieldReference(expression)) {
return new NativePropertyAccessTranslator(propertyDescriptor, qualifier, context);
result = new NativePropertyAccessTranslator(propertyDescriptor, qualifier, context);
} else {
ResolvedCall<?> resolvedCall = getResolvedCall(context.bindingContext(), expression);
result = new KotlinPropertyAccessTranslator(propertyDescriptor, qualifier, resolvedCall, context);
}
ResolvedCall<?> resolvedCall = getResolvedCall(context.bindingContext(), expression);
return new KotlinPropertyAccessTranslator(propertyDescriptor, qualifier, resolvedCall, context);
result.setCallType(callType);
return result;
}
@NotNull
@@ -67,8 +72,9 @@ public abstract class PropertyAccessTranslator extends AccessTranslator {
@NotNull
public static JsExpression translateAsPropertyGetterCall(@NotNull JetSimpleNameExpression expression,
@Nullable JsExpression qualifier,
@NotNull CallType callType,
@NotNull TranslationContext context) {
return (newInstance(expression, qualifier, context))
return (newInstance(expression, qualifier, callType, context))
.translateAsGet();
}
@@ -1,18 +1,16 @@
package org.jetbrains.k2js.translate.reference;
import com.google.dart.compiler.backend.js.ast.JsConditional;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsNullLiteral;
import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.k2js.translate.context.TemporaryVariable;
import org.jetbrains.jet.lang.psi.JetCallExpression;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetQualifiedExpression;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.k2js.translate.context.TranslationContext;
import static org.jetbrains.k2js.translate.general.Translation.translateAsExpression;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getNotNullSimpleNameSelector;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getSelector;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.notNullCheck;
/**
* @author Pavel Talanov
@@ -28,44 +26,38 @@ public final class QualifiedExpressionTranslator {
JsExpression receiver = translateReceiver(expression, context);
PropertyAccessTranslator result =
PropertyAccessTranslator.newInstance(getNotNullSimpleNameSelector(expression), receiver, context);
result.setCallType(CallType.getCallTypeForQualifierExpression(expression));
PropertyAccessTranslator.newInstance(getNotNullSimpleNameSelector(expression), receiver,
CallType.getCallTypeForQualifiedExpression(expression), context);
result.setCallType(CallType.getCallTypeForQualifiedExpression(expression));
return result;
}
@NotNull
public static JsExpression translateSafeQualifiedExpression(@NotNull JetSafeQualifiedExpression expression,
@NotNull TranslationContext context) {
TemporaryVariable receiver = context.declareTemporary(translateReceiver(expression, context));
JsNullLiteral nullLiteral = context.program().getNullLiteral();
JetExpression selector = getSelector(expression);
JsExpression thenExpression = translate(receiver.nameReference(), selector, context);
JsConditional callMethodIfNotNullConditional
= new JsConditional(notNullCheck(context, receiver.nameReference()), thenExpression, nullLiteral);
return AstUtil.newSequence(receiver.assignmentExpression(), callMethodIfNotNullConditional);
}
@NotNull
public static JsExpression translateDotQualifiedExpression(@NotNull JetDotQualifiedExpression expression,
@NotNull TranslationContext context) {
public static JsExpression translateQualifiedExpression(@NotNull JetQualifiedExpression expression,
@NotNull TranslationContext context) {
JsExpression receiver = translateReceiver(expression, context);
JetExpression selector = getSelector(expression);
return translate(receiver, selector, context);
CallType callType = CallType.getCallTypeForQualifiedExpression(expression);
return dispatchToCorrectTranslator(receiver, selector, callType, context);
}
@NotNull
private static JsExpression translate(@NotNull JsExpression receiver, @NotNull JetExpression selector,
@NotNull TranslationContext context) {
private static JsExpression dispatchToCorrectTranslator(@NotNull JsExpression receiver,
@NotNull JetExpression selector,
@NotNull CallType callType,
@NotNull TranslationContext context) {
if (PropertyAccessTranslator.canBePropertyGetterCall(selector, context)) {
assert selector instanceof JetSimpleNameExpression : "Selectors for properties must be simple names.";
return PropertyAccessTranslator.translateAsPropertyGetterCall
((JetSimpleNameExpression) selector, receiver, context);
((JetSimpleNameExpression) selector, receiver, callType, context);
}
if (selector instanceof JetCallExpression) {
return CallTranslator.translate((JetCallExpression) selector, receiver, context);
return CallTranslator.translate((JetCallExpression) selector, receiver, callType, context);
}
throw new AssertionError("Unexpected qualified expression");
}
//TODO: if has duplications
@NotNull
private static JsExpression translateReceiver(@NotNull JetQualifiedExpression expression,
@NotNull TranslationContext context) {
@@ -19,7 +19,7 @@ public final class ReferenceTranslator {
public static JsExpression translateSimpleName(@NotNull JetSimpleNameExpression expression,
@NotNull TranslationContext context) {
if (PropertyAccessTranslator.canBePropertyGetterCall(expression, context)) {
return PropertyAccessTranslator.translateAsPropertyGetterCall(expression, null, context);
return PropertyAccessTranslator.translateAsPropertyGetterCall(expression, null, CallType.NORMAL, context);
}
DeclarationDescriptor referencedDescriptor =
getDescriptorForReferenceExpression(context.bindingContext(), expression);
@@ -16,7 +16,7 @@ import java.util.Collection;
import java.util.List;
import static org.jetbrains.k2js.translate.utils.DescriptorUtils.getVariableDescriptorForVariableAsFunction;
import static org.jetbrains.k2js.translate.utils.DescriptorUtils.isVariableDescriptor;
import static org.jetbrains.k2js.translate.utils.DescriptorUtils.isVariableAsFunction;
/**
* @author Pavel Talanov
@@ -191,7 +191,7 @@ public final class BindingUtils {
private static DeclarationDescriptor getNullableDescriptorForReferenceExpression(@NotNull BindingContext context,
@NotNull JetReferenceExpression reference) {
DeclarationDescriptor referencedDescriptor = context.get(BindingContext.REFERENCE_TARGET, reference);
if (isVariableDescriptor(referencedDescriptor)) {
if (isVariableAsFunction(referencedDescriptor)) {
assert referencedDescriptor != null;
return getVariableDescriptorForVariableAsFunction((VariableAsFunctionDescriptor) referencedDescriptor);
}
@@ -111,7 +111,7 @@ public final class DescriptorUtils {
}
public static boolean isVariableDescriptor(@Nullable DeclarationDescriptor referencedDescriptor) {
public static boolean isVariableAsFunction(@Nullable DeclarationDescriptor referencedDescriptor) {
return referencedDescriptor instanceof VariableAsFunctionDescriptor;
}
@@ -4,12 +4,15 @@ class A() {
var c = 3
}
fun box() {
fun box() : Boolean {
var a1 : A? = A()
var a2 : A? = null
a1?.c++
a2?.c++
a1?.c = 4
a2?.c = 5
if (a1?.c != 4) {
return false;
}
a2 = a1
a2?.c++
return (a2?.c == 5)
a2?.c = 5
return (a2?.c == 5) && (a1?.c == 5)
}
@@ -2,7 +2,6 @@ package foo
class A() {
fun doSomething() {
}
}
@@ -14,7 +14,7 @@ public final class MiscTest extends AbstractExpressionTest {
return MAIN;
}
public void testNamespaceProperties() throws Exception {
public void testLocalPropertys() throws Exception {
testFunctionOutput("localProperty.jet", "foo", "box", 50);
}