Support references to local extensions in codegen

This commit is contained in:
Alexander Udalov
2013-12-19 19:08:19 +04:00
parent d3a811aa7e
commit 571adf3acc
6 changed files with 56 additions and 5 deletions
@@ -2507,6 +2507,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
Call call = CallMaker.makeCall(fakeExpression, NO_RECEIVER, null, fakeExpression, fakeArguments);
Callable callable = codegen.resolveToCallable(codegen.accessibleFunctionDescriptor(referencedFunction), false);
StackValue receiver = generateCallee(codegen, callable);
if (extensionReceiver.exists()) {
receiver = StackValue.composed(receiver, receiverParameterStackValue(signature));
}
result = codegen.invokeFunctionWithCalleeOnStack(call, receiver, fakeResolvedCall, callable);
}
@@ -2574,13 +2577,15 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
if (receiver == null) return NO_RECEIVER;
JetExpression receiverExpression = JetPsiFactory.createExpression(state.getProject(), "callableReferenceFakeReceiver");
Type firstParameterType = signature.getAsmMethod().getArgumentTypes()[0];
// 0 is this (the closure class), 1 is the method's first parameter
codegen.tempVariables.put(receiverExpression, StackValue.local(1, firstParameterType));
codegen.tempVariables.put(receiverExpression, receiverParameterStackValue(signature));
return new ExpressionReceiver(receiverExpression, receiver.getType());
}
@NotNull
private static StackValue.Local receiverParameterStackValue(@NotNull JvmMethodSignature signature) {
// 0 is this (the callable reference class), 1 is the invoke() method's first parameter
return StackValue.local(1, signature.getAsmMethod().getArgumentTypes()[0]);
}
}
@Override
@@ -0,0 +1,6 @@
class A
fun box(): String {
fun A.foo() = "OK"
return A().(A::foo)()
}
@@ -0,0 +1,5 @@
fun box(): String {
class A
fun A.foo() = "OK"
return (::A)().(A::foo)()
}
@@ -0,0 +1,4 @@
fun box(): String {
fun Int.is42With(that: Int) = this + 2 * that == 42
return if (16.(Int::is42With)(13)) "OK" else "Fail"
}
@@ -0,0 +1,11 @@
class A
fun box(): String {
var result = "Fail"
fun A.ext() { result = "OK" }
val f = A::ext
A().f()
return result
}
@@ -767,6 +767,26 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest("compiler/testData/codegen/box/callableReference/local/enumExtendsTrait.kt");
}
@TestMetadata("extension.kt")
public void testExtension() throws Exception {
doTest("compiler/testData/codegen/box/callableReference/local/extension.kt");
}
@TestMetadata("extensionToLocalClass.kt")
public void testExtensionToLocalClass() throws Exception {
doTest("compiler/testData/codegen/box/callableReference/local/extensionToLocalClass.kt");
}
@TestMetadata("extensionToPrimitive.kt")
public void testExtensionToPrimitive() throws Exception {
doTest("compiler/testData/codegen/box/callableReference/local/extensionToPrimitive.kt");
}
@TestMetadata("extensionWithClosure.kt")
public void testExtensionWithClosure() throws Exception {
doTest("compiler/testData/codegen/box/callableReference/local/extensionWithClosure.kt");
}
@TestMetadata("genericMember.kt")
public void testGenericMember() throws Exception {
doTest("compiler/testData/codegen/box/callableReference/local/genericMember.kt");