Generate debug information for 'when' subject variable
NB debugger tests currently don't support language version or individual language feature settings.
This commit is contained in:
@@ -4513,11 +4513,12 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
|
||||
int subjectLocal;
|
||||
Type subjectType;
|
||||
VariableDescriptor subjectVariableDescriptor = null;
|
||||
if (subjectVariable != null) {
|
||||
VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, subjectVariable);
|
||||
assert variableDescriptor != null : "Unresolved subject variable: " + subjectVariable.getName();
|
||||
subjectType = asmType(variableDescriptor.getType());
|
||||
subjectLocal = myFrameMap.enter(variableDescriptor, subjectType);
|
||||
subjectVariableDescriptor = bindingContext.get(BindingContext.VARIABLE, subjectVariable);
|
||||
assert subjectVariableDescriptor != null : "Unresolved subject variable: " + subjectVariable.getName();
|
||||
subjectType = asmType(subjectVariableDescriptor.getType());
|
||||
subjectLocal = myFrameMap.enter(subjectVariableDescriptor, subjectType);
|
||||
visitProperty(subjectVariable, null);
|
||||
tempVariables.put(subjectExpression, StackValue.local(subjectLocal, subjectType));
|
||||
}
|
||||
@@ -4533,6 +4534,9 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
subjectType = Type.VOID_TYPE;
|
||||
}
|
||||
|
||||
Label begin = new Label();
|
||||
v.mark(begin);
|
||||
|
||||
Label end = new Label();
|
||||
boolean hasElse = KtPsiUtil.checkWhenExpressionHasSingleElse(expression);
|
||||
|
||||
@@ -4572,7 +4576,16 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
markLineNumber(expression, isStatement);
|
||||
v.mark(end);
|
||||
|
||||
myFrameMap.leaveTemp(subjectType);
|
||||
if (subjectVariableDescriptor != null) {
|
||||
myFrameMap.leave(subjectVariableDescriptor);
|
||||
v.visitLocalVariable(
|
||||
subjectVariableDescriptor.getName().asString(), subjectType.getDescriptor(), null,
|
||||
begin, end, subjectLocal
|
||||
);
|
||||
}
|
||||
else {
|
||||
myFrameMap.leaveTemp(subjectType);
|
||||
}
|
||||
tempVariables.remove(subjectExpression);
|
||||
return null;
|
||||
});
|
||||
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.codegen.`when`
|
||||
import org.jetbrains.kotlin.cfg.WhenChecker
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtWhenExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||
@@ -69,6 +70,9 @@ abstract class SwitchCodegen(
|
||||
generateSubjectValue()
|
||||
generateSubjectValueToIndex()
|
||||
|
||||
val beginLabel = Label()
|
||||
v.mark(beginLabel)
|
||||
|
||||
generateSwitchInstructionByTransitionsTable()
|
||||
|
||||
generateEntries()
|
||||
@@ -81,6 +85,13 @@ abstract class SwitchCodegen(
|
||||
|
||||
codegen.markLineNumber(expression, isStatement)
|
||||
v.mark(endLabel)
|
||||
|
||||
subjectVariableDescriptor?.let {
|
||||
v.visitLocalVariable(
|
||||
it.name.asString(), subjectType.descriptor, null,
|
||||
beginLabel, endLabel, subjectLocal
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -115,19 +126,23 @@ abstract class SwitchCodegen(
|
||||
}
|
||||
}
|
||||
|
||||
private var subjectVariableDescriptor: VariableDescriptor? = null
|
||||
|
||||
/**
|
||||
* Generates subject value on top of the stack.
|
||||
* If the subject is a variable, it's stored and loaded.
|
||||
*/
|
||||
private fun generateSubjectValue() {
|
||||
if (subjectVariable != null) {
|
||||
val variableDescriptor = bindingContext[BindingContext.VARIABLE, subjectVariable]
|
||||
val mySubjectVariable = bindingContext[BindingContext.VARIABLE, subjectVariable]
|
||||
?: throw AssertionError("Unresolved subject variable: $expression")
|
||||
subjectLocal = codegen.frameMap.enter(variableDescriptor, subjectType)
|
||||
subjectLocal = codegen.frameMap.enter(mySubjectVariable, subjectType)
|
||||
codegen.visitProperty(subjectVariable, null)
|
||||
StackValue.local(subjectLocal, subjectType).put(subjectType, codegen.v)
|
||||
subjectVariableDescriptor = mySubjectVariable
|
||||
} else {
|
||||
codegen.gen(subjectExpression, subjectType)
|
||||
subjectVariableDescriptor = null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// !LANGUAGE: +VariableDeclarationInWhenSubject
|
||||
|
||||
fun test(a: Any) =
|
||||
when (val subject = a) {
|
||||
is Int -> "Int $subject"
|
||||
is String -> "String ${subject.length}"
|
||||
else -> "other"
|
||||
}
|
||||
|
||||
// 1 LOCALVARIABLE subject Ljava/lang/Object;
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// !LANGUAGE: +VariableDeclarationInWhenSubject
|
||||
|
||||
enum class X { A, B, C }
|
||||
|
||||
fun test(a: X) =
|
||||
when (val subject = a) {
|
||||
X.A -> 0
|
||||
X.B -> 1
|
||||
X.C -> 2
|
||||
}
|
||||
|
||||
// 1 LOCALVARIABLE subject
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// !LANGUAGE: +VariableDeclarationInWhenSubject
|
||||
|
||||
fun test(a: Int) =
|
||||
when (val subject = a) {
|
||||
1 -> 0
|
||||
2 -> 1
|
||||
3 -> 2
|
||||
else -> -1
|
||||
}
|
||||
|
||||
// 1 LOCALVARIABLE subject
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// !LANGUAGE: +VariableDeclarationInWhenSubject
|
||||
|
||||
fun test(a: String) =
|
||||
when (val subject = a) {
|
||||
"" -> 0
|
||||
"a" -> 1
|
||||
else -> -1
|
||||
}
|
||||
|
||||
// 1 LOCALVARIABLE subject
|
||||
@@ -2811,6 +2811,26 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
||||
runTest("compiler/testData/codegen/bytecodeText/when/simpleConstValsInsideWhen.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("subjectValHasLocalVariableSlot.kt")
|
||||
public void testSubjectValHasLocalVariableSlot() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/when/subjectValHasLocalVariableSlot.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("subjectValInEnumWhenHasLocalVariableSlot.kt")
|
||||
public void testSubjectValInEnumWhenHasLocalVariableSlot() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/when/subjectValInEnumWhenHasLocalVariableSlot.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("subjectValInIntWhenHasLocalVariableSlot.kt")
|
||||
public void testSubjectValInIntWhenHasLocalVariableSlot() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/when/subjectValInIntWhenHasLocalVariableSlot.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("subjectValInStringWhenHasLocalVariableSlot.kt")
|
||||
public void testSubjectValInStringWhenHasLocalVariableSlot() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/when/subjectValInStringWhenHasLocalVariableSlot.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("whenNull.kt")
|
||||
public void testWhenNull() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/when/whenNull.kt");
|
||||
|
||||
Reference in New Issue
Block a user