Hide synthetic variables for local functions and destructured lambda parameters (Kotlin variables)

This commit is contained in:
Yan Zhulanow
2019-01-14 22:07:45 +03:00
parent ed88020a84
commit d039e3b1c0
9 changed files with 76 additions and 2 deletions
@@ -118,6 +118,8 @@ public class AsmUtil {
// For non-inlined callable references ('kotlin.jvm.internal.CallableReference' has a 'receiver' field)
public static final String BOUND_REFERENCE_RECEIVER = "receiver";
public static final String LOCAL_FUNCTION_VARIABLE_PREFIX = "$fun$";
private static final ImmutableMap<Integer, JvmPrimitiveType> primitiveTypeByAsmSort;
private static final ImmutableMap<Type, Type> primitiveTypeByBoxedType;
@@ -1434,7 +1434,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
String functionIndex = StringsKt.substringAfterLast(type.getInternalName(), '$', "");
assert !functionIndex.isEmpty();
String localVariableName = "$fun$"
String localVariableName = AsmUtil.LOCAL_FUNCTION_VARIABLE_PREFIX
+ VariableAsmNameManglingUtils.mangleNameIfNeeded(functionDescriptor.getName().asString())
+ "$" + functionIndex;
@@ -10,11 +10,13 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.resolve.jvm.checkers.isValidDalvikCharacter
const val DESTRUCTURED_LAMBDA_ARGUMENT_VARIABLE_PREFIX = "\$dstr\$"
fun getNameForDestructuredParameterOrNull(valueParameterDescriptor: ValueParameterDescriptor): String? {
val variables = ValueParameterDescriptorImpl.getDestructuringVariablesOrNull(valueParameterDescriptor) ?: return null
@Suppress("SpellCheckingInspection")
return "\$dstr\$" + variables.joinToString(separator = "$") { descriptor ->
return DESTRUCTURED_LAMBDA_ARGUMENT_VARIABLE_PREFIX + variables.joinToString(separator = "$") { descriptor ->
val name = descriptor.name
mangleNameIfNeeded(
when {
@@ -30,6 +30,7 @@ import com.sun.jdi.ReferenceType
import com.sun.jdi.Type
import com.sun.jdi.Value
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.DESTRUCTURED_LAMBDA_ARGUMENT_VARIABLE_PREFIX
import org.jetbrains.kotlin.codegen.coroutines.CONTINUATION_PARAMETER_NAME
import org.jetbrains.kotlin.codegen.inline.INLINE_FUN_VAR_SUFFIX
import org.jetbrains.kotlin.codegen.inline.isFakeLocalVariableForInline
@@ -206,6 +207,8 @@ class KotlinStackFrame(frame: StackFrameProxyImpl) : JavaStackFrame(StackFrameDe
private fun isHidden(variable: LocalVariableProxyImpl, inlineDepth: Int): Boolean {
val name = variable.name()
return isFakeLocalVariableForInline(name)
|| name.startsWith(DESTRUCTURED_LAMBDA_ARGUMENT_VARIABLE_PREFIX)
|| name.startsWith(AsmUtil.LOCAL_FUNCTION_VARIABLE_PREFIX)
|| VariableFinder.getInlineDepth(variable.name()) != inlineDepth
|| name == CONTINUATION_VARIABLE_NAME
}
@@ -0,0 +1,20 @@
package lambdaParameterMangling
private data class Foo(val a: String, val b: Int)
private fun foo(foo: Foo, block: (Foo) -> Unit) {
block(foo)
}
fun main() {
foo(Foo("a", 5)) { (a, b) ->
//Breakpoint!
val c = 5
}
}
// SHOW_KOTLIN_VARIABLES
// PRINT_FRAME
// EXPRESSION: a.length + b
// RESULT: 6: I
@@ -0,0 +1,14 @@
LineBreakpoint created at lambdaParameterMangling.kt:12
Run Java
Connected to the target VM
lambdaParameterMangling.kt:12
Compile bytecode for a.length + b
frame = invoke:12, LambdaParameterManglingKt$main$1 {lambdaParameterMangling}
local = a: java.lang.String = a (sp = lambdaParameterMangling.kt, 10)
field = value: char[] = {char[1]@uniqueID} (sp = String.!EXT!)
element = 0 = 'a' 97
field = hash: int = 0 (sp = String.!EXT!)
local = b: int = 5 (sp = lambdaParameterMangling.kt, 10)
Disconnected from the target VM
Process finished with exit code 0
@@ -0,0 +1,14 @@
package localFunctionMangling
fun main() {
fun foo() {}
//Breakpoint!
val a = 5
}
// SHOW_KOTLIN_VARIABLES
// PRINT_FRAME
// EXPRESSION: 1
// RESULT: 1: I
@@ -0,0 +1,9 @@
LineBreakpoint created at localFunctionMangling.kt:7
Run Java
Connected to the target VM
localFunctionMangling.kt:7
Compile bytecode for 1
frame = main:7, LocalFunctionManglingKt {localFunctionMangling}
Disconnected from the target VM
Process finished with exit code 0
@@ -745,6 +745,16 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/hideSyntheticThis.kt");
}
@TestMetadata("lambdaParameterMangling.kt")
public void testLambdaParameterMangling() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/lambdaParameterMangling.kt");
}
@TestMetadata("localFunctionMangling.kt")
public void testLocalFunctionMangling() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/localFunctionMangling.kt");
}
@TestMetadata("remapThis.kt")
public void testRemapThis() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/remapThis.kt");