[kotlin debugger] IDEA-357870 Reimplement evaluatable getters filtering using metadata helper

Previously, filtering of evaluatable getters in variables view relied on bytecode inspections. Because of this, in some cases incorrect getters were shown, and also filtering was disabled completely in Android Studio.

GitOrigin-RevId: 6b86d0307526c2ffa23cf49a14d579504bd5f810
This commit is contained in:
Nikita Nazarov
2025-03-25 11:25:03 +00:00
committed by intellij-monorepo-bot
parent b20a2c8b81
commit f241ee62a1
16 changed files with 342 additions and 32 deletions
@@ -7,6 +7,8 @@ import java.nio.charset.StandardCharsets;
import java.util.Arrays;
public class MetadataDebugHelper {
public static final String METADATA_SEPARATOR = "\n";
private static final String METADATA_CLASS_NAME = "kotlin.Metadata";
private static final String KIND = "kind";
@@ -36,8 +38,14 @@ public class MetadataDebugHelper {
* the debugger side. Any JDWP communication can be very expensive when debugging remotely,
* especially when debugging Android applications on a phone.
*/
@SuppressWarnings("unchecked")
public static String getDebugMetadataAsJson(Class<?> cls) {
StringBuilder sb = new StringBuilder();
appendDebugMetadataAsJson(sb, cls);
return sb.toString();
}
@SuppressWarnings("unchecked")
private static void appendDebugMetadataAsJson(StringBuilder sb, Class<?> cls) {
try {
Class<?> metadataClass = Class.forName(METADATA_CLASS_NAME, false, cls.getClassLoader());
Method kindMethod = metadataClass.getDeclaredMethod(KIND_METHOD_NAME);
@@ -50,7 +58,6 @@ public class MetadataDebugHelper {
Object metadata = cls.getAnnotation((Class<Annotation>)metadataClass);
StringBuilder sb = new StringBuilder();
sb.append("{");
int kind = (int)kindMethod.invoke(metadata);
@@ -75,13 +82,28 @@ public class MetadataDebugHelper {
appendAsJsonValueNoComma(sb, EXTRA_INT, extraInt);
sb.append("}");
return sb.toString();
} catch (Exception ex) {
return null;
} catch (Exception ignored) {
}
}
/*
* This function is used similarly to `getDebugMetadataAsJson`, when there is a need to
* fetch metadata for multiple classes.
*
* The return value is a concatenation of metadata JSON representations of given classes
* separated by MetadataDebugHelper.METADATA_SEPARATOR.
*/
public static String getDebugMetadataListAsJson(Class<?>... classes) {
StringBuilder sb = new StringBuilder();
for (Class<?> cls : classes) {
if (sb.length() != 0) {
sb.append(METADATA_SEPARATOR);
}
appendDebugMetadataAsJson(sb, cls);
}
return sb.toString();
}
private static void appendAsJsonValue(StringBuilder sb, String name, Object value) {
appendAsJsonValueNoComma(sb, name, value).append(',');
}
@@ -58,7 +58,10 @@
<orderEntry type="module" module-name="intellij.platform.statistics" />
<orderEntry type="module" module-name="intellij.platform.util" />
<orderEntry type="module" module-name="kotlin.base.resources" />
<orderEntry type="library" name="gson" level="project" />
<orderEntry type="module" module-name="intellij.java.debugger.impl.shared" />
<orderEntry type="module" module-name="intellij.platform.util.jdom" />
<orderEntry type="module" module-name="intellij.java.rt" />
<orderEntry type="library" name="kotlin-metadata" level="project" />
</component>
</module>
@@ -0,0 +1,142 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.debugger.core
import com.google.gson.Gson
import com.google.gson.JsonSyntaxException
import com.intellij.debugger.engine.evaluation.EvaluationContext
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
import com.intellij.debugger.impl.DebuggerUtilsImpl
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.getOrCreateUserData
import com.intellij.rt.debugger.JsonUtils
import com.intellij.rt.debugger.MetadataDebugHelper
import com.sun.jdi.ReferenceType
import com.sun.jdi.StringReference
import com.sun.jdi.Value
import org.jetbrains.kotlin.idea.debugger.base.util.wrapEvaluateException
import org.jetbrains.kotlin.idea.debugger.base.util.wrapIllegalArgumentException
import kotlin.io.encoding.Base64
import kotlin.io.encoding.ExperimentalEncodingApi
import kotlin.metadata.jvm.KotlinClassMetadata
object KotlinMetadataCacheService {
private val METADATA_CACHE_KEY = Key.create<KotlinMetadataCache?>("METADATA_CACHE_KEY")
fun getKotlinMetadata(refType: ReferenceType, context: EvaluationContext): KotlinClassMetadata? {
return getCache(context)?.fetchKotlinMetadata(refType, context)
}
fun getKotlinMetadataList(refTypes: Collection<ReferenceType>, context: EvaluationContext): List<KotlinClassMetadata>? {
return getCache(context)?.fetchKotlinMetadataList(refTypes, context)
}
private fun getCache(context: EvaluationContext): KotlinMetadataCache? {
val vmProxy = (context as? EvaluationContextImpl)?.virtualMachineProxy ?: return null
return vmProxy.getOrCreateUserData(METADATA_CACHE_KEY) {
KotlinMetadataCache()
}
}
}
private class KotlinMetadataCache {
private class MetadataAdapter(
val kind: Int,
val metadataVersion: Array<Int>,
val data1: Array<String>,
val data2: Array<String>,
val extraString: String,
val packageName: String,
val extraInt: Int,
) {
@OptIn(ExperimentalEncodingApi::class)
fun toMetadata(): Metadata {
return Metadata(
kind = kind,
metadataVersion = metadataVersion.toIntArray(),
data1 = data1.map { String(Base64.Default.decode(it)) }.toTypedArray(),
data2 = data2,
extraString = extraString,
packageName = packageName,
extraInt = extraInt
)
}
}
private val cache = mutableMapOf<ReferenceType, KotlinClassMetadata>()
fun fetchKotlinMetadata(refType: ReferenceType, context: EvaluationContext): KotlinClassMetadata? {
cache[refType]?.let { return it }
val metadataAsJson = callMethodFromHelper(
context, "getDebugMetadataAsJson", listOf(refType.classObject())
) ?: return null
val metadata = parseMetadataFromJson(metadataAsJson) ?: return null
cache[refType] = metadata
return metadata
}
fun fetchKotlinMetadataList(refTypes: Collection<ReferenceType>, context: EvaluationContext): List<KotlinClassMetadata>? {
val result = mutableListOf<KotlinClassMetadata>()
val toFetch = mutableListOf<ReferenceType>()
for (refType in refTypes) {
val metadata = cache[refType]
if (metadata != null) {
result.add(metadata)
} else {
toFetch.add(refType)
}
}
if (toFetch.isEmpty()) {
return result
}
val classObjects = toFetch.map { it.classObject() }
val concatenatedJsonMetadatas = callMethodFromHelper(
context, "getDebugMetadataListAsJson", classObjects
) ?: return null
val splitJsonMetadatas = concatenatedJsonMetadatas.split(MetadataDebugHelper.METADATA_SEPARATOR)
if (splitJsonMetadatas.size != toFetch.size) {
return null
}
for ((metadataAsJson, refType) in splitJsonMetadatas.zip(toFetch)) {
val metadata = parseMetadataFromJson(metadataAsJson) ?: return null
cache[refType] = metadata
result.add(metadata)
}
return result
}
private fun parseMetadataFromJson(metadataAsJson: String): KotlinClassMetadata? {
val metadata = wrapJsonSyntaxException {
Gson().fromJson(metadataAsJson, MetadataAdapter::class.java).toMetadata()
} ?: return null
val parsedMetadata = wrapIllegalArgumentException {
KotlinClassMetadata.readStrict(metadata)
} ?: return null
return parsedMetadata
}
private fun callMethodFromHelper(context: EvaluationContext, methodName: String, args: List<Value>): String? {
return wrapEvaluateException {
val value = DebuggerUtilsImpl.invokeHelperMethod(
context as EvaluationContextImpl,
MetadataDebugHelper::class.java,
methodName,
args,
true,
JsonUtils::class.java.name
)
(value as? StringReference)?.value()
}
}
}
private inline fun <T> wrapJsonSyntaxException(block: () -> T): T? {
return try {
block()
} catch (_: JsonSyntaxException) {
null
}
}
@@ -20,16 +20,22 @@ import com.intellij.debugger.ui.tree.render.ClassRenderer
import com.intellij.debugger.ui.tree.render.DescriptorLabelListener
import com.intellij.openapi.project.Project
import com.sun.jdi.*
import org.jetbrains.kotlin.idea.debugger.base.util.safeFields
import org.jetbrains.kotlin.idea.debugger.base.util.safeType
import org.jetbrains.kotlin.idea.debugger.base.util.isLateinitVariableGetter
import org.jetbrains.kotlin.idea.debugger.base.util.isSimpleGetter
import org.jetbrains.kotlin.idea.debugger.core.render.GetterDescriptor
import org.jetbrains.kotlin.idea.debugger.base.util.safeFields
import org.jetbrains.kotlin.idea.debugger.base.util.safeType
import org.jetbrains.kotlin.idea.debugger.core.KotlinDebuggerCoreBundle
import org.jetbrains.kotlin.idea.debugger.core.KotlinMetadataCacheService
import org.jetbrains.kotlin.idea.debugger.core.isInKotlinSources
import org.jetbrains.kotlin.idea.debugger.core.isInKotlinSourcesAsync
import org.jetbrains.kotlin.idea.debugger.core.render.GetterDescriptor
import org.jetbrains.kotlin.utils.addIfNotNull
import java.util.concurrent.CompletableFuture
import java.util.function.Function
import kotlin.metadata.KmProperty
import kotlin.metadata.isNotDefault
import kotlin.metadata.jvm.KotlinClassMetadata
import kotlin.metadata.jvm.getterSignature
class KotlinClassRenderer : ClassRenderer() {
init {
@@ -53,7 +59,10 @@ class KotlinClassRenderer : ClassRenderer() {
val nodeDescriptorFactory = builder.descriptorManager
val refType = value.referenceType()
val gettersFuture = DebuggerUtilsAsync.allMethods(refType)
.thenApply { methods -> methods.getters().createNodes(value, parentDescriptor.project, evaluationContext, nodeManager) }
.thenApply { methods ->
val getters = fetchGettersUsingMetadata(evaluationContext, methods) ?: methods.getters()
getters.createNodes(value, parentDescriptor.project, evaluationContext, nodeManager)
}
DebuggerUtilsAsync.allFields(refType).thenCombine(gettersFuture) { fields, getterNodes ->
if (fields.none { FieldVisibilityProvider.shouldDisplayField(it) } && getterNodes.isEmpty()) {
builder.setChildren(listOf(nodeManager.createMessageNode(KotlinDebuggerCoreBundle.message("message.class.has.no.properties"))))
@@ -78,6 +87,46 @@ class KotlinClassRenderer : ClassRenderer() {
}
}
private fun fetchGettersUsingMetadata(
context: EvaluationContext,
methods: List<Method>
): List<Method>? {
val gettersToShow = calculateGettersToShowUsingMetadata(methods, context) ?: return null
return methods
.filter { it.name() in gettersToShow }
.distinctBy { it.name() }
}
private fun calculateGettersToShowUsingMetadata(
methods: List<Method>,
context: EvaluationContext
): Set<String>? {
val uniqueKotlinDeclaringTypes = methods
.map { it.declaringType() }
.filter { it.isInKotlinSources() }
.toSet()
val metadataList = KotlinMetadataCacheService.getKotlinMetadataList(
uniqueKotlinDeclaringTypes, context
) ?: return null
val gettersToShow = mutableSetOf<String>()
for (metadata in metadataList) {
if (metadata !is KotlinClassMetadata.Class) {
continue
}
for (property in metadata.kmClass.properties) {
if (property.shouldBeVisibleInVariablesView()) {
gettersToShow.addIfNotNull(property.getterSignature?.name)
}
}
}
return gettersToShow
}
private fun KmProperty.shouldBeVisibleInVariablesView(): Boolean {
return getter.isNotDefault
}
override fun calcLabel(
descriptor: ValueDescriptor,
evaluationContext: EvaluationContext?,
@@ -872,6 +872,11 @@ public abstract class InlineScopesAndK2IdeK2CodeEvaluateExpressionTestGenerated
runTest("../testData/evaluation/singleBreakpoint/frame/delegatedPropertyInClassWoRenderer.kt");
}
@TestMetadata("evaluatableGetters.kt")
public void testEvaluatableGetters() throws Exception {
runTest("../testData/evaluation/singleBreakpoint/frame/evaluatableGetters.kt");
}
@TestMetadata("frameAnonymousObject.kt")
public void testFrameAnonymousObject() throws Exception {
runTest("../testData/evaluation/singleBreakpoint/frame/frameAnonymousObject.kt");
@@ -872,6 +872,11 @@ public abstract class K2IdeK2CodeKotlinEvaluateExpressionTestGenerated extends A
runTest("../testData/evaluation/singleBreakpoint/frame/delegatedPropertyInClassWoRenderer.kt");
}
@TestMetadata("evaluatableGetters.kt")
public void testEvaluatableGetters() throws Exception {
runTest("../testData/evaluation/singleBreakpoint/frame/evaluatableGetters.kt");
}
@TestMetadata("frameAnonymousObject.kt")
public void testFrameAnonymousObject() throws Exception {
runTest("../testData/evaluation/singleBreakpoint/frame/frameAnonymousObject.kt");
@@ -872,6 +872,11 @@ public abstract class IndyLambdaIrKotlinEvaluateExpressionTestGenerated extends
runTest("testData/evaluation/singleBreakpoint/frame/delegatedPropertyInClassWoRenderer.kt");
}
@TestMetadata("evaluatableGetters.kt")
public void testEvaluatableGetters() throws Exception {
runTest("testData/evaluation/singleBreakpoint/frame/evaluatableGetters.kt");
}
@TestMetadata("frameAnonymousObject.kt")
public void testFrameAnonymousObject() throws Exception {
runTest("testData/evaluation/singleBreakpoint/frame/frameAnonymousObject.kt");
@@ -872,6 +872,11 @@ public abstract class InlineScopesAndK1IdeK2CodeEvaluateExpressionTestGenerated
runTest("testData/evaluation/singleBreakpoint/frame/delegatedPropertyInClassWoRenderer.kt");
}
@TestMetadata("evaluatableGetters.kt")
public void testEvaluatableGetters() throws Exception {
runTest("testData/evaluation/singleBreakpoint/frame/evaluatableGetters.kt");
}
@TestMetadata("frameAnonymousObject.kt")
public void testFrameAnonymousObject() throws Exception {
runTest("testData/evaluation/singleBreakpoint/frame/frameAnonymousObject.kt");
@@ -872,6 +872,11 @@ public abstract class IrKotlinEvaluateExpressionInMppTestGenerated extends Abstr
runTest("testData/evaluation/singleBreakpoint/frame/delegatedPropertyInClassWoRenderer.kt");
}
@TestMetadata("evaluatableGetters.kt")
public void testEvaluatableGetters() throws Exception {
runTest("testData/evaluation/singleBreakpoint/frame/evaluatableGetters.kt");
}
@TestMetadata("frameAnonymousObject.kt")
public void testFrameAnonymousObject() throws Exception {
runTest("testData/evaluation/singleBreakpoint/frame/frameAnonymousObject.kt");
@@ -872,6 +872,11 @@ public abstract class IrKotlinEvaluateExpressionWithIRFragmentCompilerTestGenera
runTest("testData/evaluation/singleBreakpoint/frame/delegatedPropertyInClassWoRenderer.kt");
}
@TestMetadata("evaluatableGetters.kt")
public void testEvaluatableGetters() throws Exception {
runTest("testData/evaluation/singleBreakpoint/frame/evaluatableGetters.kt");
}
@TestMetadata("frameAnonymousObject.kt")
public void testFrameAnonymousObject() throws Exception {
runTest("testData/evaluation/singleBreakpoint/frame/frameAnonymousObject.kt");
@@ -872,6 +872,11 @@ public abstract class K1IdeK2CodeKotlinEvaluateExpressionInMppTestGenerated exte
runTest("testData/evaluation/singleBreakpoint/frame/delegatedPropertyInClassWoRenderer.kt");
}
@TestMetadata("evaluatableGetters.kt")
public void testEvaluatableGetters() throws Exception {
runTest("testData/evaluation/singleBreakpoint/frame/evaluatableGetters.kt");
}
@TestMetadata("frameAnonymousObject.kt")
public void testFrameAnonymousObject() throws Exception {
runTest("testData/evaluation/singleBreakpoint/frame/frameAnonymousObject.kt");
@@ -872,6 +872,11 @@ public abstract class K1IdeK2CodeKotlinEvaluateExpressionTestGenerated extends A
runTest("testData/evaluation/singleBreakpoint/frame/delegatedPropertyInClassWoRenderer.kt");
}
@TestMetadata("evaluatableGetters.kt")
public void testEvaluatableGetters() throws Exception {
runTest("testData/evaluation/singleBreakpoint/frame/evaluatableGetters.kt");
}
@TestMetadata("frameAnonymousObject.kt")
public void testFrameAnonymousObject() throws Exception {
runTest("testData/evaluation/singleBreakpoint/frame/frameAnonymousObject.kt");
@@ -0,0 +1,43 @@
package evaluatableGetters
interface I {
val i: Int get() = 1
}
abstract class Base {
val base: Int get() = 2
}
class X : Base(), I {
val a = 1
val b: Int
get() = 1 + 1
val c: String = ""
get() = field + ""
var d = ""
var e: Int = 1
get() = field + 1
set(value) { field = value + 1 }
lateinit var f: String
fun getG(): String = ""
val `😎`: Int
get() = 1
val `""`: Int
get() = 2
}
fun main() {
val x = X()
//Breakpoint!
println()
}
// PRINT_FRAME
@@ -0,0 +1,21 @@
LineBreakpoint created at evaluatableGetters.kt:40
Run Java
Connected to the target VM
evaluatableGetters.kt:40
KotlinStackFrame (evaluatableGetters.kt:40)
JavaValue[local] x: evaluatableGetters.X = evaluatableGetters.X@hashCode (evaluatableGetters.kt:38)
JavaValue[field] a: int = 1 (evaluatableGetters.kt:12)
JavaValue[field] c: java.lang.String (evaluatableGetters.kt:17)
JavaValue[getter] c: java.lang.String (evaluatableGetters.kt:17)
JavaValue[field] d: java.lang.String (evaluatableGetters.kt:20)
JavaValue[field] e: int = 1 (evaluatableGetters.kt:22)
JavaValue[getter] e: int (evaluatableGetters.kt:22)
JavaValue[field] f: java.lang.String = null (evaluatableGetters.kt:26)
JavaValue[getter] b: int (evaluatableGetters.kt:14)
JavaValue[getter] 😎: int (evaluatableGetters.kt:30)
JavaValue[getter] "": int (evaluatableGetters.kt:33)
JavaValue[getter] i: int (evaluatableGetters.kt:4)
JavaValue[getter] base: int (evaluatableGetters.kt:8)
Disconnected from the target VM
Process finished with exit code 0
@@ -4,17 +4,7 @@ Connected to the target VM
showPropertiesFromMethods.kt:35
KotlinStackFrame (showPropertiesFromMethods.kt:35)
JavaValue[local] instance: showPropertiesFromMethods.TestClass = showPropertiesFromMethods.TestClass@hashCode (showPropertiesFromMethods.kt:33)
DummyMessageValueNode = No fields to display
JavaValue[getter] value2: int (showPropertiesFromMethods.kt:19)
JavaValue[getter] value4: int (showPropertiesFromMethods.kt:21)
JavaValue[getter] value5: int (showPropertiesFromMethods.kt:23)
JavaValue[getter] isTestClass: boolean (showPropertiesFromMethods.kt:25)
JavaValue[getter] isIFromDerived: boolean (showPropertiesFromMethods.kt:27)
JavaValue[getter] isAFromDerived: boolean (showPropertiesFromMethods.kt:29)
JavaValue[getter] value1: int (showPropertiesFromMethods.kt:4)
JavaValue[getter] isI: boolean (showPropertiesFromMethods.kt:6)
JavaValue[getter] value3: int (showPropertiesFromMethods.kt:11)
JavaValue[getter] isA: boolean (showPropertiesFromMethods.kt:13)
DummyMessageValueNode = Class has no properties
Disconnected from the target VM
Process finished with exit code 0
@@ -18,7 +18,7 @@ KotlinStackFrame (evaluatableGetters.kt:114)
JavaValue[getter] x3: int (evaluatableGetters.kt:6)
JavaValue[getter] x2: int (evaluatableGetters.kt:5)
JavaValue[getter] x1: int (evaluatableGetters.kt:4)
Packets sent: 58, methods called: 4
Packets sent: 100, methods called: 7
evaluatableGetters.kt:114
KotlinStackFrame (evaluatableGetters.kt:114)
JavaValue[local] x: evaluatableGetters.X1 = evaluatableGetters.X20@hashCode (evaluatableGetters.kt:112)
@@ -43,7 +43,7 @@ KotlinStackFrame (evaluatableGetters.kt:114)
JavaValue[getter] x3: int (evaluatableGetters.kt:6)
JavaValue[getter] x2: int (evaluatableGetters.kt:5)
JavaValue[getter] x1: int (evaluatableGetters.kt:4)
Packets sent: 55, methods called: 3
Packets sent: 87, methods called: 5
evaluatableGetters.kt:114
KotlinStackFrame (evaluatableGetters.kt:114)
JavaValue[local] x: evaluatableGetters.X1 = evaluatableGetters.X30@hashCode (evaluatableGetters.kt:112)
@@ -78,7 +78,7 @@ KotlinStackFrame (evaluatableGetters.kt:114)
JavaValue[getter] x3: int (evaluatableGetters.kt:6)
JavaValue[getter] x2: int (evaluatableGetters.kt:5)
JavaValue[getter] x1: int (evaluatableGetters.kt:4)
Packets sent: 61, methods called: 4
Packets sent: 85, methods called: 5
evaluatableGetters.kt:114
KotlinStackFrame (evaluatableGetters.kt:114)
JavaValue[local] x: evaluatableGetters.X1 = evaluatableGetters.X40@hashCode (evaluatableGetters.kt:112)
@@ -123,7 +123,7 @@ KotlinStackFrame (evaluatableGetters.kt:114)
JavaValue[getter] x3: int (evaluatableGetters.kt:6)
JavaValue[getter] x2: int (evaluatableGetters.kt:5)
JavaValue[getter] x1: int (evaluatableGetters.kt:4)
Packets sent: 57, methods called: 4
Packets sent: 83, methods called: 4
evaluatableGetters.kt:114
KotlinStackFrame (evaluatableGetters.kt:114)
JavaValue[local] x: evaluatableGetters.X1 = evaluatableGetters.X50@hashCode (evaluatableGetters.kt:112)
@@ -178,7 +178,7 @@ KotlinStackFrame (evaluatableGetters.kt:114)
JavaValue[getter] x3: int (evaluatableGetters.kt:6)
JavaValue[getter] x2: int (evaluatableGetters.kt:5)
JavaValue[getter] x1: int (evaluatableGetters.kt:4)
Packets sent: 54, methods called: 3
Packets sent: 86, methods called: 5
evaluatableGetters.kt:114
KotlinStackFrame (evaluatableGetters.kt:114)
JavaValue[local] x: evaluatableGetters.X1 = evaluatableGetters.X60@hashCode (evaluatableGetters.kt:112)
@@ -243,7 +243,7 @@ KotlinStackFrame (evaluatableGetters.kt:114)
JavaValue[getter] x3: int (evaluatableGetters.kt:6)
JavaValue[getter] x2: int (evaluatableGetters.kt:5)
JavaValue[getter] x1: int (evaluatableGetters.kt:4)
Packets sent: 58, methods called: 4
Packets sent: 83, methods called: 4
evaluatableGetters.kt:114
KotlinStackFrame (evaluatableGetters.kt:114)
JavaValue[local] x: evaluatableGetters.X1 = evaluatableGetters.X70@hashCode (evaluatableGetters.kt:112)
@@ -318,7 +318,7 @@ KotlinStackFrame (evaluatableGetters.kt:114)
JavaValue[getter] x3: int (evaluatableGetters.kt:6)
JavaValue[getter] x2: int (evaluatableGetters.kt:5)
JavaValue[getter] x1: int (evaluatableGetters.kt:4)
Packets sent: 55, methods called: 3
Packets sent: 82, methods called: 4
evaluatableGetters.kt:114
KotlinStackFrame (evaluatableGetters.kt:114)
JavaValue[local] x: evaluatableGetters.X1 = evaluatableGetters.X80@hashCode (evaluatableGetters.kt:112)
@@ -403,7 +403,7 @@ KotlinStackFrame (evaluatableGetters.kt:114)
JavaValue[getter] x3: int (evaluatableGetters.kt:6)
JavaValue[getter] x2: int (evaluatableGetters.kt:5)
JavaValue[getter] x1: int (evaluatableGetters.kt:4)
Packets sent: 54, methods called: 3
Packets sent: 84, methods called: 5
evaluatableGetters.kt:114
KotlinStackFrame (evaluatableGetters.kt:114)
JavaValue[local] x: evaluatableGetters.X1 = evaluatableGetters.X90@hashCode (evaluatableGetters.kt:112)
@@ -498,7 +498,7 @@ KotlinStackFrame (evaluatableGetters.kt:114)
JavaValue[getter] x3: int (evaluatableGetters.kt:6)
JavaValue[getter] x2: int (evaluatableGetters.kt:5)
JavaValue[getter] x1: int (evaluatableGetters.kt:4)
Packets sent: 55, methods called: 3
Packets sent: 80, methods called: 4
evaluatableGetters.kt:114
KotlinStackFrame (evaluatableGetters.kt:114)
JavaValue[local] x: evaluatableGetters.X1 = evaluatableGetters.X100@hashCode (evaluatableGetters.kt:112)
@@ -603,7 +603,7 @@ KotlinStackFrame (evaluatableGetters.kt:114)
JavaValue[getter] x3: int (evaluatableGetters.kt:6)
JavaValue[getter] x2: int (evaluatableGetters.kt:5)
JavaValue[getter] x1: int (evaluatableGetters.kt:4)
Packets sent: 55, methods called: 3
Packets sent: 81, methods called: 4
evaluatableGetters.kt:114
KotlinStackFrame (evaluatableGetters.kt:114)
JavaValue[local] x: evaluatableGetters.X1 = evaluatableGetters.X100@hashCode (evaluatableGetters.kt:112)
@@ -708,7 +708,7 @@ KotlinStackFrame (evaluatableGetters.kt:114)
JavaValue[getter] x3: int (evaluatableGetters.kt:6)
JavaValue[getter] x2: int (evaluatableGetters.kt:5)
JavaValue[getter] x1: int (evaluatableGetters.kt:4)
Packets sent: 19, methods called: 4
Packets sent: 22, methods called: 4
Disconnected from the target VM
Process finished with exit code 0