Refactor mysterious code in ExpressionCodegen
'super' receiver is now generated in visitSuperExpression()
This commit is contained in:
@@ -291,14 +291,20 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
|
||||
@Override
|
||||
public StackValue visitSuperExpression(JetSuperExpression expression, StackValue data) {
|
||||
final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
|
||||
if (descriptor instanceof ClassDescriptor) {
|
||||
return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor, true);
|
||||
}
|
||||
else {
|
||||
JetType type = context.getThisDescriptor().getDefaultType();
|
||||
return StackValue.local(0, asmType(type));
|
||||
return StackValue.thisOrOuter(this, getSuperCallLabelTarget(expression), true);
|
||||
}
|
||||
|
||||
private ClassDescriptor getSuperCallLabelTarget(JetSuperExpression expression) {
|
||||
PsiElement labelPsi = bindingContext.get(BindingContext.LABEL_TARGET, expression.getTargetLabel());
|
||||
ClassDescriptor labelTarget = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, labelPsi);
|
||||
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
|
||||
// "super<descriptor>@labelTarget"
|
||||
if (labelTarget != null) {
|
||||
return labelTarget;
|
||||
}
|
||||
assert descriptor instanceof ClassDescriptor : "Don't know how to generate super-call to not a class";
|
||||
ClassDescriptor target = getParentContextSubclassOf((ClassDescriptor) descriptor).getThisDescriptor();
|
||||
return target;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -1738,38 +1744,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
ResolvedCall<? extends CallableDescriptor> resolvedCall
|
||||
) {
|
||||
FunctionDescriptor fd = (FunctionDescriptor) resolvedCall.getResultingDescriptor();
|
||||
boolean superCall = false;
|
||||
ReceiverValue explicitReceiver = call.getExplicitReceiver();
|
||||
if (explicitReceiver instanceof ExpressionReceiver) {
|
||||
final JetExpression receiverExpression = ((ExpressionReceiver) explicitReceiver).getExpression();
|
||||
if (receiverExpression instanceof JetSuperExpression) {
|
||||
superCall = true;
|
||||
receiver = StackValue.thisOrOuter(this, context.getThisDescriptor(), true);
|
||||
JetSuperExpression superExpression = (JetSuperExpression) receiverExpression;
|
||||
PsiElement enclosingElement = bindingContext.get(BindingContext.LABEL_TARGET, superExpression.getTargetLabel());
|
||||
ClassDescriptor enclosed = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, enclosingElement);
|
||||
if (!isInterface(fd.getContainingDeclaration())) {
|
||||
if (enclosed == null) {
|
||||
enclosed = (ClassDescriptor) fd.getContainingDeclaration();
|
||||
}
|
||||
if (enclosed != context.getThisDescriptor()) {
|
||||
CodegenContext c = context;
|
||||
//noinspection ConstantConditions
|
||||
while (true) {
|
||||
if ((c instanceof ClassContext || c instanceof AnonymousClassContext) &&
|
||||
DescriptorUtils.isSubclass(c.getThisDescriptor(), enclosed)) {
|
||||
break;
|
||||
}
|
||||
c = c.getParentContext();
|
||||
assert c != null;
|
||||
}
|
||||
fd = unwrapFakeOverride(fd);
|
||||
fd = (FunctionDescriptor) c.getAccessor(fd);
|
||||
superCall = false;
|
||||
receiver = StackValue.thisOrOuter(this, enclosed, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean superCall = isSuperCall(call);
|
||||
|
||||
if (superCall && !isInterface(fd.getContainingDeclaration())) {
|
||||
CodegenContext c = getParentContextSubclassOf((ClassDescriptor) fd.getContainingDeclaration());
|
||||
fd = (FunctionDescriptor) c.getAccessor(unwrapFakeOverride(fd));
|
||||
}
|
||||
|
||||
fd = accessableFunctionDescriptor(fd);
|
||||
@@ -1801,6 +1780,35 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static JetSuperExpression getSuperCallExpression(Call call) {
|
||||
ReceiverValue explicitReceiver = call.getExplicitReceiver();
|
||||
if (explicitReceiver instanceof ExpressionReceiver) {
|
||||
JetExpression receiverExpression = ((ExpressionReceiver) explicitReceiver).getExpression();
|
||||
if (receiverExpression instanceof JetSuperExpression) {
|
||||
return (JetSuperExpression) receiverExpression;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isSuperCall(Call call) {
|
||||
return getSuperCallExpression(call) != null;
|
||||
}
|
||||
|
||||
// Find the first parent of the current context which corresponds to a subclass of a given class
|
||||
private CodegenContext getParentContextSubclassOf(ClassDescriptor descriptor) {
|
||||
CodegenContext c = context;
|
||||
while (true) {
|
||||
if ((c instanceof ClassContext || c instanceof AnonymousClassContext) &&
|
||||
DescriptorUtils.isSubclass(c.getThisDescriptor(), descriptor)) {
|
||||
return c;
|
||||
}
|
||||
c = c.getParentContext();
|
||||
assert c != null;
|
||||
}
|
||||
}
|
||||
|
||||
private StackValue returnValueAsStackValue(FunctionDescriptor fd, Type callReturnType) {
|
||||
if (callReturnType != Type.VOID_TYPE) {
|
||||
JetType type = fd.getReturnType();
|
||||
@@ -2200,7 +2208,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
|
||||
@Override
|
||||
public StackValue visitDotQualifiedExpression(JetDotQualifiedExpression expression, StackValue receiver) {
|
||||
return genQualified(StackValue.none(), expression.getSelectorExpression());
|
||||
JetExpression receiverExpression = expression.getReceiverExpression();
|
||||
StackValue receiverValue = receiverExpression instanceof JetSuperExpression ? gen(receiverExpression) : StackValue.none();
|
||||
return genQualified(receiverValue, expression.getSelectorExpression());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
trait BK {
|
||||
fun foo(): String
|
||||
fun bar(): String
|
||||
}
|
||||
|
||||
trait K : BK {
|
||||
override fun foo() = bar()
|
||||
}
|
||||
|
||||
class A : K {
|
||||
override fun foo() = "A.foo"
|
||||
override fun bar() = "A.bar"
|
||||
|
||||
class B : K {
|
||||
override fun foo() = "B.foo"
|
||||
override fun bar() = "B.bar"
|
||||
|
||||
fun test1() = super<K>@A.foo()
|
||||
fun test2() = super<K>@B.foo()
|
||||
fun test3() = super<K>.foo()
|
||||
fun test4() = super@A.foo()
|
||||
fun test5() = super@B.foo()
|
||||
fun test6() = super.foo()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val b = A().B()
|
||||
if (b.test1() != "A.bar") return "test1 ${b.test1()}"
|
||||
if (b.test2() != "B.bar") return "test2 ${b.test2()}"
|
||||
if (b.test3() != "B.bar") return "test3 ${b.test3()}"
|
||||
if (b.test4() != "A.bar") return "test4 ${b.test4()}"
|
||||
if (b.test5() != "B.bar") return "test5 ${b.test5()}"
|
||||
if (b.test6() != "B.bar") return "test6 ${b.test6()}"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
trait Base {
|
||||
val foo: String
|
||||
fun bar(): String
|
||||
}
|
||||
|
||||
abstract class K : Base {
|
||||
override val foo = bar()
|
||||
}
|
||||
|
||||
class A : K() {
|
||||
override val foo = "A.foo"
|
||||
override fun bar() = "A.bar"
|
||||
|
||||
class B : K() {
|
||||
override val foo = "B.foo"
|
||||
override fun bar() = "B.bar"
|
||||
|
||||
fun test1() = super<K>@A.foo
|
||||
fun test2() = super<K>@B.foo
|
||||
fun test3() = super<K>.foo
|
||||
fun test4() = super@A.foo
|
||||
fun test5() = super@B.foo
|
||||
fun test6() = super.foo
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val b = A().B()
|
||||
if (b.test1() != "A.bar") return "test1 ${b.test1()}"
|
||||
if (b.test2() != "B.bar") return "test2 ${b.test2()}"
|
||||
if (b.test3() != "B.bar") return "test3 ${b.test3()}"
|
||||
if (b.test4() != "A.bar") return "test4 ${b.test4()}"
|
||||
if (b.test5() != "B.bar") return "test5 ${b.test5()}"
|
||||
if (b.test6() != "B.bar") return "test6 ${b.test6()}"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
trait T1 {
|
||||
fun foo() = "O"
|
||||
}
|
||||
|
||||
trait T2 {
|
||||
fun foo() = "K"
|
||||
}
|
||||
|
||||
class A : T1, T2 {
|
||||
override fun foo() = super<T1>.foo() + super<T2>.foo()
|
||||
}
|
||||
|
||||
fun box() = A().foo()
|
||||
@@ -46,6 +46,18 @@ public class SuperGenTest extends CodegenTestCase {
|
||||
// System.out.println(generateToText());
|
||||
}
|
||||
|
||||
public void testInnerClassLabeledSuper() {
|
||||
blackBoxFile("super/innerClassLabeledSuper.kt");
|
||||
}
|
||||
|
||||
public void testInnerClassLabeledSuperProperty() {
|
||||
blackBoxFile("super/innerClassLabeledSuperProperty.kt");
|
||||
}
|
||||
|
||||
public void testMultipleSuperTraits() {
|
||||
blackBoxFile("super/multipleSuperTraits.kt");
|
||||
}
|
||||
|
||||
public void testEnclosedFun () {
|
||||
blackBoxFile("/super/enclosedFun.jet");
|
||||
// System.out.println(generateToText());
|
||||
|
||||
Reference in New Issue
Block a user