Minor: Fixes after review
This commit is contained in:
@@ -73,6 +73,7 @@ import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
|||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.codeFragmentUtil.debugTypeInfo
|
import org.jetbrains.kotlin.psi.codeFragmentUtil.debugTypeInfo
|
||||||
import org.jetbrains.kotlin.psi.codeFragmentUtil.suppressDiagnosticsInDebugMode
|
import org.jetbrains.kotlin.psi.codeFragmentUtil.suppressDiagnosticsInDebugMode
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||||
import org.jetbrains.kotlin.resolve.AnalyzingUtils
|
import org.jetbrains.kotlin.resolve.AnalyzingUtils
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||||
@@ -159,7 +160,7 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: Sour
|
|||||||
try {
|
try {
|
||||||
return runEval4j(context, extractAndCompile(codeFragment, sourcePosition, context)).toJdiValue(context)
|
return runEval4j(context, extractAndCompile(codeFragment, sourcePosition, context)).toJdiValue(context)
|
||||||
} finally {
|
} finally {
|
||||||
classLoaderHandler.dispose()
|
classLoaderHandler?.dispose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,20 +256,24 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: Sour
|
|||||||
return fileName.substringBeforeLast(".class").replace("/", ".")
|
return fileName.substringBeforeLast(".class").replace("/", ".")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val CompiledDataDescriptor.mainClass
|
||||||
|
get() = classes.firstOrNull() ?: error(
|
||||||
|
"Can't find main class for " + sourcePosition.elementAt.getParentOfType<KtDeclaration>(strict = false))
|
||||||
|
|
||||||
private fun evaluateWithCompilation(context: EvaluationContextImpl, compiledData: CompiledDataDescriptor): Any? {
|
private fun evaluateWithCompilation(context: EvaluationContextImpl, compiledData: CompiledDataDescriptor): Any? {
|
||||||
val vm = context.debugProcess.virtualMachineProxy.virtualMachine
|
val vm = context.debugProcess.virtualMachineProxy.virtualMachine
|
||||||
val classLoader = context.classLoader ?: return null
|
val classLoader = context.classLoader ?: return null
|
||||||
val mainClassBytecode = compiledData.classes[0].bytes
|
val mainClassBytecode = compiledData.mainClass.bytes
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val mainClassAsmNode = ClassNode().apply { ClassReader(mainClassBytecode).accept(this, ClassReader.EXPAND_FRAMES) }
|
val mainClassAsmNode = ClassNode().apply { ClassReader(mainClassBytecode).accept(this, ClassReader.SKIP_CODE) }
|
||||||
val mainClassJdiName = mainClassAsmNode.name.replace('/', '.')
|
val mainClassJdiName = mainClassAsmNode.name.replace('/', '.')
|
||||||
assert(mainClassAsmNode.methods.size == 1)
|
assert(mainClassAsmNode.methods.size == 1)
|
||||||
|
|
||||||
val methodToInvoke = mainClassAsmNode.methods[0]
|
val methodToInvoke = mainClassAsmNode.methods[0]
|
||||||
assert(methodToInvoke.parameters == null || methodToInvoke.parameters.isEmpty())
|
assert(methodToInvoke.parameters == null || methodToInvoke.parameters.isEmpty())
|
||||||
|
|
||||||
val mainClass = classByName(context, mainClassJdiName, classLoader).reflectedType() as ClassType
|
val mainClass = context.debugProcess.findClass(context, mainClassJdiName, classLoader) as ClassType
|
||||||
|
|
||||||
val thread = context.suspendContext.thread?.threadReference!!
|
val thread = context.suspendContext.thread?.threadReference!!
|
||||||
val invokePolicy = context.suspendContext.getInvokePolicy()
|
val invokePolicy = context.suspendContext.getInvokePolicy()
|
||||||
@@ -296,23 +301,12 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: Sour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun classByName(context: EvaluationContextImpl, className: String, classLoader: ClassLoaderReference): ClassObjectReference {
|
|
||||||
val process = context.debugProcess
|
|
||||||
val vm = process.virtualMachineProxy
|
|
||||||
val classClass = process.findClass(context, Class::class.java.canonicalName, classLoader) as ClassType
|
|
||||||
val forNameMethod = classClass.concreteMethodByName(
|
|
||||||
"forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;") ?: error("'forName' method not found")
|
|
||||||
return process.invokeMethod(context, classClass, forNameMethod, listOf(
|
|
||||||
vm.mirrorOf(className),
|
|
||||||
vm.mirrorOf(true),
|
|
||||||
classLoader)) as ClassObjectReference
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun runEval4j(context: EvaluationContextImpl, compiledData: CompiledDataDescriptor): InterpreterResult {
|
private fun runEval4j(context: EvaluationContextImpl, compiledData: CompiledDataDescriptor): InterpreterResult {
|
||||||
val virtualMachine = context.debugProcess.virtualMachineProxy.virtualMachine
|
val virtualMachine = context.debugProcess.virtualMachineProxy.virtualMachine
|
||||||
var resultValue: InterpreterResult? = null
|
var resultValue: InterpreterResult? = null
|
||||||
|
|
||||||
val mainClassBytecode = compiledData.classes[0].bytes
|
// assert [0] with some context
|
||||||
|
val mainClassBytecode = compiledData.mainClass.bytes
|
||||||
|
|
||||||
ClassReader(mainClassBytecode).accept(object : ClassVisitor(ASM5) {
|
ClassReader(mainClassBytecode).accept(object : ClassVisitor(ASM5) {
|
||||||
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<out String>?): MethodVisitor? {
|
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<out String>?): MethodVisitor? {
|
||||||
|
|||||||
-3
@@ -46,6 +46,3 @@ abstract class AbstractAndroidClassLoadingAdapter : ClassLoadingAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val ClassLoaderReference.isDalvikClassLoader: Boolean
|
|
||||||
get() = referenceType()?.name()?.startsWith("dalvik.system.") ?: false
|
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.idea.debugger.evaluate.compilingEvaluator
|
package org.jetbrains.kotlin.idea.debugger.evaluate.compilingEvaluator
|
||||||
|
|
||||||
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
|
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
|
||||||
|
import org.jetbrains.kotlin.idea.debugger.evaluate.LOG
|
||||||
import org.jetbrains.kotlin.idea.debugger.evaluate.classLoading.ClassLoaderHandler
|
import org.jetbrains.kotlin.idea.debugger.evaluate.classLoading.ClassLoaderHandler
|
||||||
import org.jetbrains.kotlin.idea.debugger.evaluate.classLoading.ClassLoadingAdapter
|
import org.jetbrains.kotlin.idea.debugger.evaluate.classLoading.ClassLoadingAdapter
|
||||||
import org.jetbrains.kotlin.idea.debugger.evaluate.classLoading.ClassToLoad
|
import org.jetbrains.kotlin.idea.debugger.evaluate.classLoading.ClassToLoad
|
||||||
@@ -25,14 +26,15 @@ fun loadClassesSafely(evaluationContext: EvaluationContextImpl, classes: Collect
|
|||||||
try {
|
try {
|
||||||
return loadClasses(evaluationContext, classes)
|
return loadClasses(evaluationContext, classes)
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
|
LOG.debug("Failed to evaluate expression", e)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadClasses(evaluationContext: EvaluationContextImpl, classes: Collection<ClassToLoad>): ClassLoaderHandler {
|
fun loadClasses(evaluationContext: EvaluationContextImpl, classes: Collection<ClassToLoad>): ClassLoaderHandler? {
|
||||||
if (classes.isEmpty()) return ClassLoaderHandler(evaluationContext.classLoader)
|
if (classes.isEmpty()) return ClassLoaderHandler(evaluationContext.classLoader)
|
||||||
|
|
||||||
return ClassLoadingAdapter.loadClasses(evaluationContext, classes).apply {
|
return ClassLoadingAdapter.loadClasses(evaluationContext, classes)?.apply {
|
||||||
evaluationContext.classLoader = this.reference
|
evaluationContext.classLoader = this.reference
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user