Rewrote reference translation a bit. Added support for when call expression.
This commit is contained in:
@@ -289,4 +289,34 @@ public class AstUtil {
|
||||
public static JsBinaryOperation or(JsExpression op1, JsExpression op2) {
|
||||
return new JsBinaryOperation(JsBinaryOperator.OR, op1, op2);
|
||||
}
|
||||
|
||||
public static void setQualifier(JsExpression selector, JsExpression receiver) {
|
||||
if (selector instanceof JsInvocation) {
|
||||
setQualifier(((JsInvocation) selector).getQualifier(), receiver);
|
||||
return;
|
||||
}
|
||||
if (selector instanceof JsNameRef) {
|
||||
JsNameRef nameRef = (JsNameRef) selector;
|
||||
JsExpression qualifier = nameRef.getQualifier();
|
||||
if (qualifier == null) {
|
||||
nameRef.setQualifier(receiver);
|
||||
} else {
|
||||
setQualifier(qualifier, receiver);
|
||||
}
|
||||
return;
|
||||
}
|
||||
throw new AssertionError("Set qualifier should be applied only to JsInvocation or JsNameRef instances");
|
||||
}
|
||||
|
||||
public static JsExpression equals(JsExpression arg1, JsExpression arg2) {
|
||||
return new JsBinaryOperation(JsBinaryOperator.REF_EQ, arg1, arg2);
|
||||
}
|
||||
|
||||
public static JsExpression equalsTrue(JsExpression expression, JsProgram program) {
|
||||
return equals(expression, program.getTrueLiteral());
|
||||
}
|
||||
|
||||
public static void thisQualify(JsExpression expression) {
|
||||
setQualifier(expression, new JsThisRef());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,9 +78,7 @@ public final class ClassBodyVisitor extends TranslatorVisitor<List<JsPropertyIni
|
||||
@NotNull
|
||||
private JsFunction generateDefaultGetterFunction(@NotNull JetProperty expression,
|
||||
@NotNull TranslationContext context) {
|
||||
JsNameRef backingFieldRef = getBackingFieldName(getPropertyName(expression), context).makeRef();
|
||||
backingFieldRef.setQualifier(new JsThisRef());
|
||||
JsReturn returnExpression = new JsReturn(backingFieldRef);
|
||||
JsReturn returnExpression = new JsReturn(backingFieldReference(expression, context));
|
||||
return AstUtil.newFunction
|
||||
(context.enclosingScope(), null, new ArrayList<JsParameter>(), AstUtil.convertToBlock(returnExpression));
|
||||
}
|
||||
@@ -108,13 +106,9 @@ public final class ClassBodyVisitor extends TranslatorVisitor<List<JsPropertyIni
|
||||
|
||||
@NotNull
|
||||
private JsBinaryOperation assignmentToBackingFieldFromDefaultParameter
|
||||
(@NotNull JetProperty expression, @NotNull TranslationContext context, @NotNull JsParameter defaultParameter) {
|
||||
JsNameRef backingFieldRef = getBackingFieldName(getPropertyName(expression), context).makeRef();
|
||||
backingFieldRef.setQualifier(new JsThisRef());
|
||||
JsBinaryOperation assignExpression = new JsBinaryOperation(JsBinaryOperator.ASG);
|
||||
assignExpression.setArg1(backingFieldRef);
|
||||
assignExpression.setArg2(defaultParameter.getName().makeRef());
|
||||
return assignExpression;
|
||||
(@NotNull JetProperty expression, @NotNull TranslationContext context,
|
||||
@NotNull JsParameter defaultParameter) {
|
||||
return AstUtil.newAssignment(backingFieldReference(expression, context), defaultParameter.getName().makeRef());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -249,6 +249,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
||||
return null;
|
||||
}
|
||||
|
||||
//TODO: refactor and possibly move somewhere
|
||||
@Override
|
||||
@NotNull
|
||||
public JsNode visitDotQualifiedExpression(@NotNull JetDotQualifiedExpression expression,
|
||||
@@ -343,7 +344,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
||||
JsExpression receiver = translateReceiver(expression, context);
|
||||
JsNullLiteral nullLiteral = context.program().getNullLiteral();
|
||||
JsExpression thenExpression = translateQualifiedExpression(expression, context);
|
||||
return new JsConditional(TranslationUtils.notNullCheck(receiver, context),
|
||||
return new JsConditional(TranslationUtils.notNullCheck(context, receiver),
|
||||
thenExpression, nullLiteral);
|
||||
}
|
||||
|
||||
|
||||
@@ -128,12 +128,8 @@ public class InitializerVisitor extends TranslatorVisitor<List<JsStatement>> {
|
||||
@NotNull
|
||||
JsStatement assignmentToBackingField(@NotNull JetProperty property, @NotNull JsExpression initExpression,
|
||||
@NotNull TranslationContext context) {
|
||||
String propertyName = property.getName();
|
||||
assert propertyName != null : "Named property expected.";
|
||||
JsName backingFieldName = getBackingFieldName(propertyName, context);
|
||||
JsNameRef backingFieldRef = backingFieldName.makeRef();
|
||||
backingFieldRef.setQualifier(new JsThisRef());
|
||||
return AstUtil.newAssignmentStatement(backingFieldRef, initExpression);
|
||||
|
||||
return AstUtil.newAssignmentStatement(backingFieldReference(property, context), initExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -72,7 +72,7 @@ public final class OperationTranslator extends AbstractTranslator {
|
||||
}
|
||||
JetExpression leftExpression = expression.getLeft();
|
||||
JsInvocation setterCall = Translation.propertyAccessTranslator(translationContext()).
|
||||
resolveAsPropertySetterCall(leftExpression);
|
||||
translateAsPropertySetterCall(leftExpression);
|
||||
if (setterCall == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ public final class PatternTranslator extends AbstractTranslator {
|
||||
|
||||
@NotNull
|
||||
private JsExpression addNullCheck(@NotNull JsExpression expressionToMatch, @NotNull JsInvocation isCheck) {
|
||||
return AstUtil.or(TranslationUtils.isNullCheck(expressionToMatch, translationContext()), isCheck);
|
||||
return AstUtil.or(TranslationUtils.isNullCheck(translationContext(), expressionToMatch), isCheck);
|
||||
}
|
||||
|
||||
private boolean isNullable(JetTypePattern pattern) {
|
||||
|
||||
@@ -49,7 +49,9 @@ public final class PropertyAccessTranslator extends AbstractTranslator {
|
||||
if (getterName == null) {
|
||||
return null;
|
||||
}
|
||||
return AstUtil.newInvocation(AstUtil.thisQualifiedReference(getterName));
|
||||
JsNameRef getterReference =
|
||||
TranslationUtils.generateCorrectReference(translationContext(), expression, getterName);
|
||||
return AstUtil.newInvocation(getterReference);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -58,12 +60,12 @@ public final class PropertyAccessTranslator extends AbstractTranslator {
|
||||
JsExpression qualifier = Translation.translateAsExpression
|
||||
(qualifiedExpression.getReceiverExpression(), translationContext());
|
||||
JsNameRef result = accessorName.makeRef();
|
||||
result.setQualifier(qualifier);
|
||||
AstUtil.setQualifier(result, qualifier);
|
||||
return AstUtil.newInvocation(result);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JsInvocation resolveAsPropertySetterCall(@NotNull JetExpression expression) {
|
||||
public JsInvocation translateAsPropertySetterCall(@NotNull JetExpression expression) {
|
||||
if (expression instanceof JetDotQualifiedExpression) {
|
||||
return resolveAsPropertySet((JetDotQualifiedExpression) expression);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package org.jetbrains.k2js.translate;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||
import com.google.dart.compiler.backend.js.ast.JsInvocation;
|
||||
import com.google.dart.compiler.backend.js.ast.JsName;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
/**
|
||||
* @author Talanov Pavel
|
||||
@@ -55,47 +56,16 @@ public class ReferenceTranslator extends AbstractTranslator {
|
||||
return null;
|
||||
}
|
||||
JsName referencedName = translationContext().getNameForDescriptor(referencedDescriptor);
|
||||
return generateCorrectReference(expression, referencedName);
|
||||
return TranslationUtils.generateCorrectReference(translationContext(), expression, referencedName);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JsExpression resolveAsLocalReference(@NotNull JetSimpleNameExpression expression) {
|
||||
JsName localReferencedName = getLocalReferencedName(expression);
|
||||
JsName localReferencedName = TranslationUtils.getLocalReferencedName(translationContext(), expression);
|
||||
if (localReferencedName == null) {
|
||||
return null;
|
||||
}
|
||||
return generateCorrectReference(expression, localReferencedName);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsNameRef generateCorrectReference(@NotNull JetSimpleNameExpression expression,
|
||||
@NotNull JsName referencedName) {
|
||||
JsNameRef result;
|
||||
if (requiresNamespaceQualifier(referencedName)) {
|
||||
result = translationContext().getNamespaceQualifiedReference(referencedName);
|
||||
} else {
|
||||
result = referencedName.makeRef();
|
||||
if (requiresThisQualifier(expression)) {
|
||||
result.setQualifier(new JsThisRef());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean requiresNamespaceQualifier(@NotNull JsName referencedName) {
|
||||
return translationContext().namespaceScope().ownsName(referencedName);
|
||||
}
|
||||
|
||||
private boolean requiresThisQualifier(@NotNull JetSimpleNameExpression expression) {
|
||||
boolean isClassMember = translationContext().classScope().ownsName(getLocalReferencedName(expression));
|
||||
boolean isBackingFieldAccess = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER;
|
||||
return isClassMember || isBackingFieldAccess;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JsName getLocalReferencedName(@NotNull JetSimpleNameExpression expression) {
|
||||
String referencedName = expression.getReferencedName();
|
||||
return translationContext().enclosingScope().findExistingName(referencedName);
|
||||
return TranslationUtils.generateCorrectReference(translationContext(), expression, localReferencedName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package org.jetbrains.k2js.translate;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.JsBinaryOperation;
|
||||
import com.google.dart.compiler.backend.js.ast.JsBinaryOperator;
|
||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||
import com.google.dart.compiler.backend.js.ast.JsNullLiteral;
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
/**
|
||||
* @author Talanov Pavel
|
||||
@@ -12,19 +13,53 @@ import org.jetbrains.annotations.NotNull;
|
||||
public final class TranslationUtils {
|
||||
|
||||
@NotNull
|
||||
static public JsBinaryOperation notNullCheck(@NotNull JsExpression expressionToCheck,
|
||||
@NotNull TranslationContext context) {
|
||||
static public JsBinaryOperation notNullCheck(@NotNull TranslationContext context,
|
||||
@NotNull JsExpression expressionToCheck) {
|
||||
JsNullLiteral nullLiteral = context.program().getNullLiteral();
|
||||
return new JsBinaryOperation
|
||||
(JsBinaryOperator.NEQ, expressionToCheck, nullLiteral);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static public JsBinaryOperation isNullCheck(@NotNull JsExpression expressionToCheck,
|
||||
@NotNull TranslationContext context) {
|
||||
static public JsBinaryOperation isNullCheck(@NotNull TranslationContext context,
|
||||
@NotNull JsExpression expressionToCheck) {
|
||||
JsNullLiteral nullLiteral = context.program().getNullLiteral();
|
||||
return new JsBinaryOperation
|
||||
(JsBinaryOperator.REF_EQ, expressionToCheck, nullLiteral);
|
||||
}
|
||||
|
||||
//TODO: make logic clear
|
||||
@NotNull
|
||||
static public JsNameRef generateCorrectReference(@NotNull TranslationContext context,
|
||||
@NotNull JetSimpleNameExpression expression,
|
||||
@NotNull JsName referencedName) {
|
||||
if (requiresNamespaceQualifier(context, referencedName)) {
|
||||
return context.getNamespaceQualifiedReference(referencedName);
|
||||
} else if (requiresThisQualifier(context, expression, referencedName)) {
|
||||
return AstUtil.thisQualifiedReference(referencedName);
|
||||
}
|
||||
return referencedName.makeRef();
|
||||
}
|
||||
|
||||
static private boolean requiresNamespaceQualifier(@NotNull TranslationContext context,
|
||||
@NotNull JsName referencedName) {
|
||||
return context.namespaceScope().ownsName(referencedName);
|
||||
}
|
||||
|
||||
static private boolean requiresThisQualifier(@NotNull TranslationContext context,
|
||||
@NotNull JetSimpleNameExpression expression,
|
||||
@NotNull JsName referencedName) {
|
||||
JsName name = context.enclosingScope().findExistingName(referencedName.getIdent());
|
||||
boolean isClassMember = context.classScope().ownsName(name);
|
||||
boolean isBackingFieldAccess = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER;
|
||||
return isClassMember || isBackingFieldAccess;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static public JsName getLocalReferencedName(@NotNull TranslationContext context,
|
||||
@NotNull JetSimpleNameExpression expression) {
|
||||
String referencedName = expression.getReferencedName();
|
||||
return context.enclosingScope().findExistingName(referencedName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package org.jetbrains.k2js.translate;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||
import com.google.dart.compiler.backend.js.ast.JsName;
|
||||
import com.google.dart.compiler.backend.js.ast.JsNameRef;
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
@@ -22,6 +24,11 @@ public class TranslatorVisitor<T> extends JetVisitor<T, TranslationContext> {
|
||||
throw new RuntimeException("Unsupported expression encountered:" + expression.toString());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected JsNameRef backingFieldReference(@NotNull JetProperty expression, @NotNull TranslationContext context) {
|
||||
return AstUtil.thisQualifiedReference(getBackingFieldName(getPropertyName(expression), context));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected String getPropertyName(@NotNull JetProperty expression) {
|
||||
String propertyName = expression.getName();
|
||||
@@ -32,7 +39,7 @@ public class TranslatorVisitor<T> extends JetVisitor<T, TranslationContext> {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected JsName getBackingFieldName(@NotNull String propertyName, @NotNull TranslationContext context) {
|
||||
private JsName getBackingFieldName(@NotNull String propertyName, @NotNull TranslationContext context) {
|
||||
String backingFieldName = Namer.getKotlinBackingFieldName(propertyName);
|
||||
return context.enclosingScope().findExistingName(backingFieldName);
|
||||
}
|
||||
|
||||
@@ -138,9 +138,27 @@ public class WhenTranslator extends AbstractTranslator {
|
||||
if (condition instanceof JetWhenConditionIsPattern) {
|
||||
return translatePatternCondition((JetWhenConditionIsPattern) condition);
|
||||
}
|
||||
if (condition instanceof JetWhenConditionCall) {
|
||||
return translateCallCondition((JetWhenConditionCall) condition);
|
||||
}
|
||||
throw new AssertionError("Unsupported when condition " + condition.getClass());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsExpression translateCallCondition(@NotNull JetWhenConditionCall condition) {
|
||||
JsExpression suffixExpression =
|
||||
Translation.translateAsExpression(getSuffixExpression(condition), translationContext());
|
||||
AstUtil.setQualifier(suffixExpression, expressionToMatch);
|
||||
return AstUtil.equalsTrue(suffixExpression, translationContext().program());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JetExpression getSuffixExpression(@NotNull JetWhenConditionCall condition) {
|
||||
JetExpression suffixExpression = condition.getCallSuffixExpression();
|
||||
assert suffixExpression != null : "When call condition should have suffix expression";
|
||||
return suffixExpression;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsBlock addDummyBreak(@NotNull JsStatement statement) {
|
||||
return AstUtil.newBlock(statement, new JsBreak());
|
||||
|
||||
@@ -44,4 +44,9 @@ public class BasicClassTest extends IncludeLibraryTest {
|
||||
public void complexExpressionAsConstructorParameter() throws Exception {
|
||||
testFooBoxIsTrue("complexExpressionAsConstructorParameter.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertyAccess() throws Exception {
|
||||
testFooBoxIsTrue("propertyAccess.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,4 +54,14 @@ public final class PatternMatchingTest extends IncludeLibraryTest {
|
||||
testFooBoxIsTrue("matchNullableType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenConditionMethodCall() throws Exception {
|
||||
testFooBoxIsTrue("whenConditionMethodCall.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenConditionPropertyAccess() throws Exception {
|
||||
testFooBoxIsTrue("whenConditionPropertyAccess.kt");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace foo
|
||||
|
||||
class Test() {
|
||||
val p = true
|
||||
}
|
||||
|
||||
fun box() : Boolean {
|
||||
return Test().p
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace foo
|
||||
|
||||
class A() {
|
||||
fun p() = true
|
||||
}
|
||||
|
||||
fun box() : Boolean {
|
||||
var a = 0
|
||||
when(A()) {
|
||||
.p() => a--
|
||||
is A? => a++;
|
||||
is A => a++;
|
||||
else => a++;
|
||||
}
|
||||
return (a == -1)
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace foo
|
||||
|
||||
class A() {
|
||||
val pp = true
|
||||
fun p() = true
|
||||
}
|
||||
|
||||
fun box() : Boolean {
|
||||
var a = 0
|
||||
when(A()) {
|
||||
.pp => a -=2
|
||||
.p() => a--
|
||||
is A? => a++;
|
||||
is A => a++;
|
||||
else => a++;
|
||||
}
|
||||
return (a == -2)
|
||||
}
|
||||
Reference in New Issue
Block a user