implement CallType logic
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
+3
-12
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
+10
-4
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
+19
-27
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user