Debugger: Hide call-site 'this' in inline functions in Kotlin variables mode (KT-30610)
This commit is contained in:
@@ -104,6 +104,8 @@ public class AsmUtil {
|
||||
|
||||
public static final String LABELED_THIS_FIELD = THIS + "_";
|
||||
|
||||
public static final String INLINE_DECLARATION_SITE_THIS = "this_";
|
||||
|
||||
public static final String LABELED_THIS_PARAMETER = "$" + THIS + "$";
|
||||
|
||||
public static final String CAPTURED_THIS_FIELD = "this$0";
|
||||
|
||||
@@ -487,7 +487,7 @@ class MethodInliner(
|
||||
) {
|
||||
if (isInliningLambda || GENERATE_DEBUG_INFO) {
|
||||
val varSuffix = if (inliningContext.isRoot && !isFakeLocalVariableForInline(name)) INLINE_FUN_VAR_SUFFIX else ""
|
||||
val varName = if (!varSuffix.isEmpty() && name == "this") name + "_" else name
|
||||
val varName = if (!varSuffix.isEmpty() && name == AsmUtil.THIS) AsmUtil.INLINE_DECLARATION_SITE_THIS else name
|
||||
super.visitLocalVariable(varName + varSuffix, desc, signature, start, end, getNewIndex(index))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,6 +111,24 @@ class KotlinStackFrame(frame: StackFrameProxyImpl) : JavaStackFrame(StackFrameDe
|
||||
return true
|
||||
}
|
||||
|
||||
return removeCallSiteThisInInlineFunction(evaluationContext, children)
|
||||
}
|
||||
|
||||
private fun removeCallSiteThisInInlineFunction(evaluationContext: EvaluationContextImpl, children: XValueChildrenList): Boolean {
|
||||
val frameProxy = evaluationContext.frameProxy
|
||||
|
||||
val variables = frameProxy?.safeVisibleVariables() ?: return false
|
||||
val inlineDepth = VariableFinder.getInlineDepth(variables)
|
||||
val declarationSiteThis = variables.firstOrNull { v ->
|
||||
val name = v.name()
|
||||
name.endsWith(INLINE_FUN_VAR_SUFFIX) && name.dropInlineSuffix() == AsmUtil.INLINE_DECLARATION_SITE_THIS
|
||||
}
|
||||
|
||||
if (inlineDepth > 0 && declarationSiteThis != null) {
|
||||
ExistingInstanceThis.find(children)?.remove()
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
+1
-4
@@ -75,10 +75,7 @@ class VariableFinder(private val context: ExecutionContext) {
|
||||
return EvaluateExceptionUtil.createEvaluateException(message)
|
||||
}
|
||||
|
||||
// org.jetbrains.kotlin.codegen.inline.MethodInliner.prepareNode
|
||||
private const val OUTER_THIS_FOR_INLINE = AsmUtil.THIS + '_'
|
||||
|
||||
val inlinedThisRegex = getLocalVariableNameRegexInlineAware(OUTER_THIS_FOR_INLINE)
|
||||
val inlinedThisRegex = getLocalVariableNameRegexInlineAware(AsmUtil.INLINE_DECLARATION_SITE_THIS)
|
||||
|
||||
private fun getCapturedVariableNameRegex(capturedName: String): Regex {
|
||||
val escapedName = Regex.escape(capturedName)
|
||||
|
||||
-2
@@ -7,8 +7,6 @@ frameInlineFunCallInsideInlineFunKotlinVariables.kt:8
|
||||
Compile bytecode for element
|
||||
Compile bytecode for this.prop
|
||||
frame = bar:8, C {frameInlineFunCallInsideInlineFunKotlinVariables}
|
||||
this = this = {frameInlineFunCallInsideInlineFunKotlinVariables.C@uniqueID}
|
||||
- Class has no fields
|
||||
local = this: frameInlineFunCallInsideInlineFunKotlinVariables.A = {frameInlineFunCallInsideInlineFunKotlinVariables.A@uniqueID} (sp = null)
|
||||
field = prop: int = 1 (sp = frameInlineFunCallInsideInlineFunKotlinVariables.kt, 11)
|
||||
local = element: double = 1.0 (sp = frameInlineFunCallInsideInlineFunKotlinVariables.kt, 7)
|
||||
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
package inlineFunThisKotlinVariables
|
||||
|
||||
class Same {
|
||||
fun useInline() {
|
||||
Different().inlineFun()
|
||||
}
|
||||
}
|
||||
|
||||
class Different {
|
||||
inline fun inlineFun() {
|
||||
//Breakpoint!
|
||||
println(1)
|
||||
}
|
||||
}
|
||||
|
||||
fun main() {
|
||||
Same().useInline()
|
||||
}
|
||||
|
||||
// PRINT_FRAME
|
||||
// SHOW_KOTLIN_VARIABLES
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
LineBreakpoint created at inlineFunThisKotlinVariables.kt:12
|
||||
Run Java
|
||||
Connected to the target VM
|
||||
inlineFunThisKotlinVariables.kt:12
|
||||
frame = useInline:12, Same {inlineFunThisKotlinVariables}
|
||||
local = this: inlineFunThisKotlinVariables.Different = {inlineFunThisKotlinVariables.Different@uniqueID} (sp = null)
|
||||
- Class has no fields
|
||||
Disconnected from the target VM
|
||||
|
||||
Process finished with exit code 0
|
||||
1
|
||||
Generated
+5
@@ -800,6 +800,11 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat
|
||||
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/hideSyntheticThis.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineFunThisKotlinVariables.kt")
|
||||
public void testInlineFunThisKotlinVariables() throws Exception {
|
||||
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/inlineFunThisKotlinVariables.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaFun1.kt")
|
||||
public void testLambdaFun1() throws Exception {
|
||||
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/lambdaFun1.kt");
|
||||
|
||||
Reference in New Issue
Block a user