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