Added support for simple case of safe qualified access.
This commit is contained in:
@@ -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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user