Added support for simple case of safe qualified access.

This commit is contained in:
Pavel Talanov
2011-11-17 14:56:06 +04:00
parent 57f5b2cc7d
commit ce39645ccd
5 changed files with 61 additions and 22 deletions
@@ -143,7 +143,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
@Override
@NotNull
public JsNode visitCallExpression(JetCallExpression expression, TranslationContext context) {
JsExpression callee = getCallee(expression, context);
JsExpression callee = translateCallee(expression, context);
List<JsExpression> arguments = translateArgumentList(expression.getValueArguments(), context);
if (isConstructorInvocation(expression, context)) {
JsNew constructorCall = new JsNew(callee);
@@ -165,7 +165,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
}
@NotNull
private JsExpression getCallee(@NotNull JetCallExpression expression, @NotNull TranslationContext context) {
private JsExpression translateCallee(@NotNull JetCallExpression expression, @NotNull TranslationContext context) {
JetExpression jetCallee = expression.getCalleeExpression();
if (jetCallee == null) {
throw new AssertionError("Call expression with no callee encountered!");
@@ -291,26 +291,30 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
@NotNull
public JsNode visitDotQualifiedExpression(@NotNull JetDotQualifiedExpression expression,
@NotNull TranslationContext context) {
return translateQualifiedExpression(expression, context);
}
@NotNull
private JsNode translateQualifiedExpression(@NotNull JetQualifiedExpression expression,
@NotNull TranslationContext context) {
JsInvocation getterCall = translateAsGetterCall(expression, context);
if (getterCall != null) {
return getterCall;
}
return translateAsQualifiedExpression(expression, context);
return translateAsQualifiedAccess(expression, context);
}
@Nullable
private JsInvocation translateAsGetterCall(@NotNull JetDotQualifiedExpression expression,
private JsInvocation translateAsGetterCall(@NotNull JetQualifiedExpression expression,
@NotNull TranslationContext context) {
return Translation.propertyAccessTranslator(context).resolveAsPropertyGet(expression);
}
@NotNull
private JsNode translateAsQualifiedExpression(@NotNull JetDotQualifiedExpression expression,
@NotNull TranslationContext context) {
JsExpression receiver = AstUtil.convertToExpression(expression.getReceiverExpression().accept(this, context));
JetExpression jetSelector = expression.getSelectorExpression();
assert jetSelector != null : "Selector should not be null in dot qualified expression.";
JsExpression selector = AstUtil.convertToExpression(jetSelector.accept(this, context));
private JsNode translateAsQualifiedAccess(@NotNull JetQualifiedExpression expression,
@NotNull TranslationContext context) {
JsExpression receiver = translateReceiver(expression, context);
JsExpression selector = translateSelector(expression, context);
assert (selector instanceof JsNameRef || selector instanceof JsInvocation)
: "Selector should be a name reference or a method invocation in dot qualified expression.";
if (selector instanceof JsInvocation) {
@@ -320,6 +324,20 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
}
}
@NotNull
private JsExpression translateSelector(@NotNull JetQualifiedExpression expression,
@NotNull TranslationContext context) {
JetExpression jetSelector = expression.getSelectorExpression();
assert jetSelector != null : "Selector should not be null in dot qualified expression.";
return AstUtil.convertToExpression(jetSelector.accept(this, context));
}
@NotNull
private JsExpression translateReceiver(@NotNull JetQualifiedExpression expression,
@NotNull TranslationContext context) {
return AstUtil.convertToExpression(expression.getReceiverExpression().accept(this, context));
}
@NotNull
private JsNode translateAsQualifiedNameReference(@NotNull JsExpression receiver, @NotNull JsNameRef selector) {
selector.setQualifier(receiver);
@@ -347,16 +365,8 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
public JsNode visitPostfixExpression(@NotNull JetPostfixExpression expression,
@NotNull TranslationContext context) {
return Translation.operationTranslator(context).translatePostfixOperation(expression);
}
// @Override
// @NotNull
// public JsNode visitBinaryWithTypeRHSExpression(@NotNull JetBinaryExpressionWithTypeRHS expression,
// @NotNull TranslationContext context) {
// return Translation.typeOperationTranslator(context).translate(expression);
// }
@Override
@NotNull
public JsNode visitIsExpression(@NotNull JetIsExpression expression,
@@ -364,5 +374,16 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
return Translation.typeOperationTranslator(context).translateIsExpression(expression);
}
@Override
@NotNull
public JsNode visitSafeQualifiedExpression(@NotNull JetSafeQualifiedExpression expression,
@NotNull TranslationContext context) {
JsExpression receiver = translateReceiver(expression, context);
JsBinaryOperation nullCheck = new JsBinaryOperation
(JsBinaryOperator.NEQ, receiver, context.program().getNullLiteral());
JsStatement thenStatement = AstUtil.convertToStatement(translateQualifiedExpression(expression, context));
return new JsIf(nullCheck, thenStatement, null);
}
}
@@ -13,6 +13,7 @@ import org.jetbrains.jet.lang.descriptors.PropertyGetterDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertySetterDescriptor;
import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetQualifiedExpression;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
@@ -33,7 +34,7 @@ public final class PropertyAccessTranslator extends AbstractTranslator {
}
@Nullable
public JsInvocation resolveAsPropertyGet(@NotNull JetDotQualifiedExpression expression) {
public JsInvocation resolveAsPropertyGet(@NotNull JetQualifiedExpression expression) {
JetExpression selectorExpression = expression.getSelectorExpression();
assert selectorExpression != null : "Selector should not be null.";
JsName getterName = getPropertyGetterName(selectorExpression);
@@ -54,9 +55,9 @@ public final class PropertyAccessTranslator extends AbstractTranslator {
@NotNull
private JsInvocation translateReceiverAndReturnAccessorInvocation
(@NotNull JetDotQualifiedExpression dotQualifiedExpression, @NotNull JsName accessorName) {
(@NotNull JetQualifiedExpression qualifiedExpression, @NotNull JsName accessorName) {
JsNode node = Translation.expressionTranslator(translationContext())
.translate(dotQualifiedExpression.getReceiverExpression());
.translate(qualifiedExpression.getReceiverExpression());
JsNameRef result = accessorName.makeRef();
result.setQualifier(AstUtil.convertToExpression(node));
return AstUtil.newInvocation(result);
@@ -39,6 +39,11 @@ public final class PropertyAccessorTest extends AbstractClassTest {
testFooBoxIsTrue("customSetter.kt");
}
@Test
public void safeCall() throws Exception {
testFooBoxIsTrue("safeCall.kt");
}
//TODO test
// @Test
// public void namespaceCustomAccessors() throws Exception {
@@ -23,5 +23,4 @@ public class RTTITest extends AbstractClassTest {
public void notIsOtherClass() throws Exception {
testFooBoxIsTrue("notIsOtherClass.kt");
}
}
@@ -0,0 +1,13 @@
namespace foo
class A() {
fun doSomething() {
}
}
fun box() : Boolean {
var a : A? = null;
a?.doSomething()
return true;
}