diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/classLoading/AndroidOClassLoadingAdapter.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/classLoading/AndroidOClassLoadingAdapter.kt index 6f047233c6c..ded7fbfcbc9 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/classLoading/AndroidOClassLoadingAdapter.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/classLoading/AndroidOClassLoadingAdapter.kt @@ -24,8 +24,8 @@ import com.sun.jdi.* import org.jetbrains.kotlin.idea.debugger.isDexDebug class AndroidOClassLoadingAdapter : AbstractAndroidClassLoadingAdapter() { - override fun isApplicable(context: EvaluationContextImpl, hasAdditionalClasses: Boolean, hasLoops: Boolean): Boolean { - return (hasAdditionalClasses || hasLoops) && context.debugProcess.isDexDebug() + override fun isApplicable(context: EvaluationContextImpl, info: ClassLoadingAdapter.Companion.ClassInfoForEvaluator) = with(info) { + isCompilingEvaluatorPreferred && context.debugProcess.isDexDebug() } private fun resolveClassLoaderClass(context: EvaluationContextImpl): ClassType? { diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/classLoading/ClassLoadingAdapter.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/classLoading/ClassLoadingAdapter.kt index 08e6f7a435b..8f73c643837 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/classLoading/ClassLoadingAdapter.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/classLoading/ClassLoadingAdapter.kt @@ -25,9 +25,7 @@ import com.sun.jdi.ClassLoaderReference import com.sun.jdi.Value import org.jetbrains.org.objectweb.asm.ClassReader import org.jetbrains.org.objectweb.asm.Label -import org.jetbrains.org.objectweb.asm.tree.ClassNode -import org.jetbrains.org.objectweb.asm.tree.JumpInsnNode -import org.jetbrains.org.objectweb.asm.tree.LabelNode +import org.jetbrains.org.objectweb.asm.tree.* import kotlin.math.min interface ClassLoadingAdapter { @@ -40,15 +38,15 @@ interface ClassLoadingAdapter { ) fun loadClasses(context: EvaluationContextImpl, classes: Collection): ClassLoaderReference? { - val hasAdditionalClasses = classes.size > 1 - val hasLoops = classes.isNotEmpty() && doesContainLoops(classes.first { it.isMainClass() }.bytes) + val mainClass = classes.firstOrNull { it.isMainClass() } ?: return null + + var info = ClassInfoForEvaluator(containsAdditionalClasses = classes.size > 1) + if (!info.containsAdditionalClasses) { + info = analyzeClass(mainClass, info) + } for (adapter in ADAPTERS) { - if (adapter.isApplicable( - context, - hasAdditionalClasses = hasAdditionalClasses, - hasLoops = hasLoops - )) { + if (adapter.isApplicable(context, info)) { return adapter.loadClasses(context, classes) } } @@ -56,30 +54,44 @@ interface ClassLoadingAdapter { return null } - private fun doesContainLoops(clazz: ByteArray): Boolean { - val classNode = ClassNode().apply { ClassReader(clazz).accept(this, ClassReader.EXPAND_FRAMES) } + data class ClassInfoForEvaluator( + val containsLoops: Boolean = false, + val containsCodeUnsupportedInEval4J: Boolean = false, + val containsAdditionalClasses: Boolean = false + ) { + val isCompilingEvaluatorPreferred: Boolean + get() = containsLoops || containsCodeUnsupportedInEval4J || containsAdditionalClasses + } + + private fun analyzeClass(classToLoad: ClassToLoad, info: ClassInfoForEvaluator): ClassInfoForEvaluator { + val classNode = ClassNode().apply { ClassReader(classToLoad.bytes).accept(this, ClassReader.EXPAND_FRAMES) } val methodToRun = classNode.methods.single() - val labelsVisited = hashSetOf