Hide synthetic variables for local functions and destructured lambda parameters (Kotlin variables)
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
Vendored
+20
@@ -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
|
||||
Vendored
+14
@@ -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
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
package localFunctionMangling
|
||||
|
||||
fun main() {
|
||||
fun foo() {}
|
||||
|
||||
//Breakpoint!
|
||||
val a = 5
|
||||
}
|
||||
|
||||
// SHOW_KOTLIN_VARIABLES
|
||||
// PRINT_FRAME
|
||||
|
||||
// EXPRESSION: 1
|
||||
// RESULT: 1: I
|
||||
Vendored
+9
@@ -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
|
||||
Generated
+10
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user