Support references to local extensions in codegen
This commit is contained in:
@@ -2507,6 +2507,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
Call call = CallMaker.makeCall(fakeExpression, NO_RECEIVER, null, fakeExpression, fakeArguments);
|
Call call = CallMaker.makeCall(fakeExpression, NO_RECEIVER, null, fakeExpression, fakeArguments);
|
||||||
Callable callable = codegen.resolveToCallable(codegen.accessibleFunctionDescriptor(referencedFunction), false);
|
Callable callable = codegen.resolveToCallable(codegen.accessibleFunctionDescriptor(referencedFunction), false);
|
||||||
StackValue receiver = generateCallee(codegen, callable);
|
StackValue receiver = generateCallee(codegen, callable);
|
||||||
|
if (extensionReceiver.exists()) {
|
||||||
|
receiver = StackValue.composed(receiver, receiverParameterStackValue(signature));
|
||||||
|
}
|
||||||
result = codegen.invokeFunctionWithCalleeOnStack(call, receiver, fakeResolvedCall, callable);
|
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;
|
if (receiver == null) return NO_RECEIVER;
|
||||||
|
|
||||||
JetExpression receiverExpression = JetPsiFactory.createExpression(state.getProject(), "callableReferenceFakeReceiver");
|
JetExpression receiverExpression = JetPsiFactory.createExpression(state.getProject(), "callableReferenceFakeReceiver");
|
||||||
|
codegen.tempVariables.put(receiverExpression, receiverParameterStackValue(signature));
|
||||||
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));
|
|
||||||
|
|
||||||
return new ExpressionReceiver(receiverExpression, receiver.getType());
|
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
|
@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");
|
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")
|
@TestMetadata("genericMember.kt")
|
||||||
public void testGenericMember() throws Exception {
|
public void testGenericMember() throws Exception {
|
||||||
doTest("compiler/testData/codegen/box/callableReference/local/genericMember.kt");
|
doTest("compiler/testData/codegen/box/callableReference/local/genericMember.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user