Debugger: Handle closure receivers came from outer callables properly (KT-31709)

This commit is contained in:
Yan Zhulanow
2019-06-14 19:13:50 +09:00
parent 577f32740e
commit 188ed82081
13 changed files with 109 additions and 7 deletions
@@ -1118,9 +1118,20 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
KotlinType captureReceiver = closure.getCapturedReceiverFromOuterContext(); KotlinType captureReceiver = closure.getCapturedReceiverFromOuterContext();
if (captureReceiver != null) { if (captureReceiver != null) {
StackValue capturedReceiver = StackValue capturedReceiver = functionReferenceReceiver;
functionReferenceReceiver != null ? functionReferenceReceiver : if (capturedReceiver == null) {
generateExtensionReceiver(unwrapOriginalReceiverOwnerForSuspendLambda(context)); CallableDescriptor descriptor = unwrapOriginalReceiverOwnerForSuspendLambda(context);
if (descriptor.getExtensionReceiverParameter() != null) {
capturedReceiver = generateExtensionReceiver(descriptor);
}
}
if (capturedReceiver == null) {
CallableDescriptor descriptor = closure.getEnclosingCallableDescriptorWithReceiver();
if (descriptor != null) {
capturedReceiver = generateExtensionReceiver(descriptor);
}
}
assert capturedReceiver != null : "Captured receiver is null for closure " + closure;
callGenerator.putCapturedValueOnStack(capturedReceiver, capturedReceiver.type, paramIndex++); callGenerator.putCapturedValueOnStack(capturedReceiver, capturedReceiver.type, paramIndex++);
} }
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor; import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor;
import org.jetbrains.kotlin.config.LanguageVersionSettings; import org.jetbrains.kotlin.config.LanguageVersionSettings;
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
import org.jetbrains.kotlin.descriptors.ClassDescriptor; import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingContext;
@@ -52,4 +53,7 @@ public interface CalculatedClosure {
boolean isSuspend(); boolean isSuspend();
boolean isSuspendLambda(); boolean isSuspendLambda();
@Nullable
CallableDescriptor getEnclosingCallableDescriptorWithReceiver();
} }
@@ -92,7 +92,9 @@ public final class MutableClosure implements CalculatedClosure {
} }
if (captureEnclosingReceiver) { if (captureEnclosingReceiver) {
ReceiverParameterDescriptor parameter = getEnclosingReceiverDescriptor(); CallableDescriptor descriptor = getEnclosingCallableDescriptorWithReceiver();
assert descriptor != null : "Receiver callable descriptor should exist";
ReceiverParameterDescriptor parameter = descriptor.getExtensionReceiverParameter();
assert parameter != null : "Receiver parameter should exist in " + enclosingFunWithReceiverDescriptor; assert parameter != null : "Receiver parameter should exist in " + enclosingFunWithReceiverDescriptor;
return parameter.getType(); return parameter.getType();
} }
@@ -190,7 +192,8 @@ public final class MutableClosure implements CalculatedClosure {
} }
@Nullable @Nullable
public ReceiverParameterDescriptor getEnclosingReceiverDescriptor() { @Override
return enclosingFunWithReceiverDescriptor != null ? enclosingFunWithReceiverDescriptor.getExtensionReceiverParameter() : null; public CallableDescriptor getEnclosingCallableDescriptorWithReceiver() {
return enclosingFunWithReceiverDescriptor;
} }
} }
@@ -138,7 +138,10 @@ public interface LocalLookup {
MutableClosure closure, MutableClosure closure,
Type classType Type classType
) { ) {
ReceiverParameterDescriptor enclosingReceiverDescriptor = closure.getEnclosingReceiverDescriptor(); CallableDescriptor enclosingCallableWithReceiver = closure.getEnclosingCallableDescriptorWithReceiver();
ReceiverParameterDescriptor enclosingReceiverDescriptor =
enclosingCallableWithReceiver != null ? enclosingCallableWithReceiver.getExtensionReceiverParameter() : null;
if (enclosingReceiverDescriptor != d) { if (enclosingReceiverDescriptor != d) {
return null; return null;
} }
@@ -0,0 +1,25 @@
//WITH_RUNTIME
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
class Environment(
val fieldAccessedInsideChild: Int,
val how: Environment.() -> Unit
)
fun box(): String {
Environment(
3,
{
class Child {
val a = fieldAccessedInsideChild
}
class Parent {
val children: List<Child> =
(0..4).map { Child() }
}
}
)
return "OK"
}
@@ -10616,6 +10616,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/extensionFunctions/kt1953_class.kt"); runTest("compiler/testData/codegen/box/extensionFunctions/kt1953_class.kt");
} }
@TestMetadata("kt23675.kt")
public void testKt23675() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/kt23675.kt");
}
@TestMetadata("kt3285.kt") @TestMetadata("kt3285.kt")
public void testKt3285() throws Exception { public void testKt3285() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/kt3285.kt"); runTest("compiler/testData/codegen/box/extensionFunctions/kt3285.kt");
@@ -10616,6 +10616,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/extensionFunctions/kt1953_class.kt"); runTest("compiler/testData/codegen/box/extensionFunctions/kt1953_class.kt");
} }
@TestMetadata("kt23675.kt")
public void testKt23675() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/kt23675.kt");
}
@TestMetadata("kt3285.kt") @TestMetadata("kt3285.kt")
public void testKt3285() throws Exception { public void testKt3285() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/kt3285.kt"); runTest("compiler/testData/codegen/box/extensionFunctions/kt3285.kt");
@@ -9501,6 +9501,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/extensionFunctions/kt1953_class.kt"); runTest("compiler/testData/codegen/box/extensionFunctions/kt1953_class.kt");
} }
@TestMetadata("kt23675.kt")
public void testKt23675() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/kt23675.kt");
}
@TestMetadata("kt3285.kt") @TestMetadata("kt3285.kt")
public void testKt3285() throws Exception { public void testKt3285() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/kt3285.kt"); runTest("compiler/testData/codegen/box/extensionFunctions/kt3285.kt");
@@ -0,0 +1,13 @@
package kt31709
data class A(val a: Int)
fun main() {
with(A(2)) {
//Breakpoint!
listOf(1, 2, 3, 4, 5).filter { it > a }
}
}
// EXPRESSION: listOf(1, 2, 3, 4, 5).filter { it > a }
// RESULT: instance of java.util.ArrayList(id=ID): Ljava/util/ArrayList;
@@ -0,0 +1,13 @@
LineBreakpoint created at kt31709.kt:8
Run Java
Connected to the target VM
kt31709.kt:8
Compile bytecode for listOf(1, 2, 3, 4, 5).filter { it > a }
kt31709.kt:8
resuming kt31709.kt:8
resuming kt31709.kt:8
resuming kt31709.kt:8
resuming kt31709.kt:8
Disconnected from the target VM
Process finished with exit code 0
@@ -286,6 +286,11 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt29179.kt"); runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt29179.kt");
} }
@TestMetadata("kt31709.kt")
public void testKt31709() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt31709.kt");
}
@TestMetadata("kt5554OnlyIntsShouldBeCoerced.kt") @TestMetadata("kt5554OnlyIntsShouldBeCoerced.kt")
public void testKt5554OnlyIntsShouldBeCoerced() throws Exception { public void testKt5554OnlyIntsShouldBeCoerced() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt5554OnlyIntsShouldBeCoerced.kt"); runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt5554OnlyIntsShouldBeCoerced.kt");
@@ -8241,6 +8241,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/extensionFunctions/kt1953_class.kt"); runTest("compiler/testData/codegen/box/extensionFunctions/kt1953_class.kt");
} }
@TestMetadata("kt23675.kt")
public void testKt23675() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/kt23675.kt");
}
@TestMetadata("kt3285.kt") @TestMetadata("kt3285.kt")
public void testKt3285() throws Exception { public void testKt3285() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/kt3285.kt"); runTest("compiler/testData/codegen/box/extensionFunctions/kt3285.kt");
@@ -9326,6 +9326,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/extensionFunctions/kt1953_class.kt"); runTest("compiler/testData/codegen/box/extensionFunctions/kt1953_class.kt");
} }
@TestMetadata("kt23675.kt")
public void testKt23675() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/kt23675.kt");
}
@TestMetadata("kt3285.kt") @TestMetadata("kt3285.kt")
public void testKt3285() throws Exception { public void testKt3285() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/kt3285.kt"); runTest("compiler/testData/codegen/box/extensionFunctions/kt3285.kt");