JS backend: fix access to enum entries by implicit receiver and explicit this.

This commit is contained in:
Zalim Bashorov
2014-03-17 21:00:23 +04:00
parent 6b72d44929
commit 8fd38e261f
5 changed files with 75 additions and 11 deletions
@@ -35,4 +35,7 @@ public class EnumTest extends SingleFileTranslationTest {
checkFooBoxIsOk();
}
public void testAccessing() throws Exception {
checkFooBoxIsOk();
}
}
@@ -219,7 +219,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
@NotNull
public JsExpression visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression,
@NotNull TranslationContext context) {
return ReferenceTranslator.translateSimpleName(expression, context).source(expression);
return ReferenceTranslator.translateSimpleNameWithQualifier(expression, null, context).source(expression);
}
@NotNull
@@ -27,7 +27,6 @@ import org.jetbrains.k2js.translate.utils.ErrorReportingUtils;
import static org.jetbrains.k2js.translate.general.Translation.translateAsExpression;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getDescriptorForReferenceExpression;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.setQualifier;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getNotNullSimpleNameSelector;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getSelector;
@@ -66,11 +65,7 @@ public final class QualifiedExpressionTranslator {
}
//TODO: never get there
if (selector instanceof JetSimpleNameExpression) {
JsExpression simpleName = ReferenceTranslator.translateSimpleName((JetSimpleNameExpression) selector, context);
if (receiver != null) { // TODO: hack for nested Object
setQualifier(simpleName, receiver);
}
return simpleName;
return ReferenceTranslator.translateSimpleNameWithQualifier((JetSimpleNameExpression) selector, receiver, context);
}
throw new AssertionError("Unexpected qualified expression: " + selector.getText());
}
@@ -19,17 +19,17 @@ package org.jetbrains.k2js.translate.reference;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.descriptors.*;
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.Namer;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.utils.BindingUtils;
import static org.jetbrains.jet.lang.psi.JetPsiUtil.isBackingFieldReference;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getDescriptorForReferenceExpression;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.setQualifier;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getSelectorAsSimpleName;
public final class ReferenceTranslator {
@@ -43,6 +43,31 @@ public final class ReferenceTranslator {
return getAccessTranslator(expression, context).translateAsGet();
}
@NotNull
public static JsExpression translateSimpleNameWithQualifier(
@NotNull JetSimpleNameExpression expression,
@Nullable JsExpression qualifier,
@NotNull TranslationContext context
) {
JsExpression simpleName = translateSimpleName(expression, context);
// Ignore qualifier if expression is EnumEntry and use always use FQ name.
DeclarationDescriptor descriptor = BindingUtils.getDescriptorForReferenceExpression(context.bindingContext(), expression);
if (descriptor instanceof ClassDescriptor) {
ClassDescriptor entryClass = (ClassDescriptor) descriptor;
if (entryClass.getKind() == ClassKind.ENUM_ENTRY) {
DeclarationDescriptor enumClass = entryClass.getContainingDeclaration();
qualifier = Namer.getClassObjectAccessor(translateAsFQReference(enumClass, context));
}
}
if (qualifier != null) { // TODO: hack for nested Object
setQualifier(simpleName, qualifier);
}
return simpleName;
}
@NotNull
public static JsExpression translateAsFQReference(@NotNull DeclarationDescriptor referencedDescriptor,
@NotNull TranslationContext context) {
@@ -0,0 +1,41 @@
package foo
enum class A {
FOO
BAR : A() {
fun explicitFromEntry() = A.FOO
//fun byThisFromEntry() = this.FOO
fun implicitFromEntry() = FOO
}
fun explicit() = A.FOO
fun byThis() = this.FOO
fun implicit() = FOO
}
fun A.extExplicit() = A.FOO
fun A.extByThis() = this.FOO
//fun A.extImplicit() = FOO
fun assertEquals<T>(expected: T, actual: T, id: String) {
if (expected != actual) throw Exception("Failed on $id, expected = '$expected', actual = '$actual'")
}
fun box(): String {
assertEquals(A.FOO, A.FOO.explicit(), "explicit access")
assertEquals(A.FOO, A.FOO.byThis(), "access by this")
assertEquals(A.FOO, A.FOO.implicit(), "implicit access")
assertEquals(A.FOO, A.FOO.explicit(), "explicit access from BAR")
// TODO uncoment when KT-4692 will be fixed
//assertEquals(A.FOO, A.FOO.byThis(), "access by this from BAR")
assertEquals(A.FOO, A.FOO.implicit(), "implicit access from BAR")
assertEquals(A.FOO, A.FOO.extExplicit(), "explicit access from ext fun")
assertEquals(A.FOO, A.FOO.extByThis(), "access by this from ext fun")
// TODO uncoment when KT-4692 will be fixed
//assertEquals(A.FOO, A.FOO.extImplicit(), "implicit access from ext fun")
return "OK"
}