Debugger: do not change package name for debug function

This commit is contained in:
Natalia Ukhorskaya
2015-11-19 18:52:27 +03:00
parent 002aaaa908
commit 062b27995c
8 changed files with 30 additions and 28 deletions
@@ -16,22 +16,22 @@
package org.jetbrains.kotlin.idea.debugger.evaluate
import com.intellij.openapi.project.Project
import com.intellij.psi.util.CachedValuesManager
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.PsiModificationTracker
import org.jetbrains.kotlin.psi.KtCodeFragment
import com.intellij.debugger.SourcePosition
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
import java.util.ArrayList
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.project.Project
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
import com.intellij.psi.util.PsiModificationTracker
import com.intellij.util.containers.MultiMap
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.apache.log4j.Logger
import org.jetbrains.eval4j.Value
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.psi.KtCodeFragment
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.types.KotlinType
import java.util.*
class KotlinEvaluateExpressionCache(val project: Project) {
@@ -89,7 +89,6 @@ class KotlinEvaluateExpressionCache(val project: Project) {
val bytecodes: ByteArray,
val additionalClasses: List<Pair<String, ByteArray>>,
val sourcePosition: SourcePosition,
val funName: String,
val parameters: ParametersDescriptor
)
@@ -81,7 +81,8 @@ import java.util.*
internal val RECEIVER_NAME = "\$receiver"
internal val THIS_NAME = "this"
val LOG = Logger.getInstance("#org.jetbrains.kotlin.idea.debugger.evaluate.KotlinEvaluator")
internal val LOG = Logger.getInstance("#org.jetbrains.kotlin.idea.debugger.evaluate.KotlinEvaluator")
internal val GENERATED_FUNCTION_NAME = "generated_for_debugger_kotlin_rulezzzz"
private val DEBUG_MODE = false
@@ -197,9 +198,6 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: Sour
}
}
val funName = runReadAction { extractedFunction.name }
?: throw IllegalStateException("Extracted function should have a name: ${extractedFunction.text}")
val additionalFiles = if (outputFiles.size < 2) emptyList()
else outputFiles.subList(1, outputFiles.size).map { getClassName(it.relativePath) to it.asByteArray() }
@@ -207,7 +205,6 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: Sour
outputFiles.first().asByteArray(),
additionalFiles,
sourcePosition,
funName,
parametersDescriptor)
}
@@ -225,7 +222,7 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: Sour
var resultValue: InterpreterResult? = null
ClassReader(compiledData.bytecodes).accept(object : ClassVisitor(ASM5) {
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<out String>?): MethodVisitor? {
if (name == compiledData.funName) {
if (name == GENERATED_FUNCTION_NAME) {
val argumentTypes = Type.getArgumentTypes(desc)
val args = context.getArgumentsForEval4j(compiledData.parameters, argumentTypes)
@@ -255,7 +252,7 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: Sour
}
}, 0)
return resultValue ?: throw IllegalStateException("resultValue is null: cannot find method ${compiledData.funName}")
return resultValue ?: throw IllegalStateException("resultValue is null: cannot find method " + GENERATED_FUNCTION_NAME)
}
private fun boxOrUnboxArgumentIfNeeded(eval: JDIEval, argumentValue: Value, parameterType: Type): Value {
@@ -469,7 +466,7 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: Sour
}
private val template = """
package packageForDebugger
!PACKAGE!
!IMPORT_LIST!
@@ -481,17 +478,17 @@ private fun createFileForDebugger(codeFragment: KtCodeFragment,
): KtFile {
val containingContextFile = codeFragment.getContextContainingFile()
val importsFromContextFile = containingContextFile?.importList?.let { it.text + "\n" } ?: ""
val packageFromContextFile = containingContextFile?.packageName?.let {
if (it.isNotBlank()) "import $it.*\n" else null
} ?: ""
var fileText = template.replace(
"!IMPORT_LIST!",
packageFromContextFile
+ importsFromContextFile
+ codeFragment.importsToString().split(KtCodeFragment.IMPORT_SEPARATOR).joinToString("\n")
importsFromContextFile + codeFragment.importsToString().split(KtCodeFragment.IMPORT_SEPARATOR).joinToString("\n")
)
val packageFromContextFile = containingContextFile?.packageName?.let {
if (it.isNotBlank()) "package $it" else ""
} ?: ""
fileText = fileText.replace("!PACKAGE!", packageFromContextFile)
val extractedFunctionText = extractedFunction.text
assert(extractedFunctionText != null) { "Text of extracted function shouldn't be null" }
fileText = fileText.replace("!FUNCTION!", extractedFunction.text!!)
@@ -100,7 +100,7 @@ fun getFunctionForExtractedFragment(
val generatorOptions = ExtractionGeneratorOptions(inTempFile = true,
flexibleTypesAllowed = true,
allowDummyName = true,
dummyName = GENERATED_FUNCTION_NAME,
allowExpressionBody = false)
return ExtractionGeneratorConfiguration(validationResult.descriptor, generatorOptions).generateDeclaration()
}
@@ -414,7 +414,7 @@ data class ExtractionGeneratorOptions(
val inTempFile: Boolean = false,
val target: ExtractionTarget = ExtractionTarget.FUNCTION,
val flexibleTypesAllowed: Boolean = false,
val allowDummyName: Boolean = false,
val dummyName: String? = null,
val allowExpressionBody: Boolean = true,
val delayInitialOccurrenceReplacement: Boolean = false
) {
@@ -93,7 +93,7 @@ fun ExtractionGeneratorConfiguration.getDeclarationText(
builder.receiver(if (isFunctionType) "($receiverTypeAsString)" else receiverTypeAsString)
}
builder.name(if (descriptor.name == "" && generatorOptions.allowDummyName) "myFun" else descriptor.name)
builder.name(generatorOptions.dummyName ?: descriptor.name)
descriptor.parameters.forEach { parameter ->
builder.param(parameter.name,
+1
View File
@@ -3,6 +3,7 @@ LineBreakpoint created at .kt.kt:5
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
.kt.kt:5
Compile bytecode for 1 + 1
Compile bytecode for Test(1).a
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
@@ -5,5 +5,10 @@ fun main(args: Array<String>) {
args.size()
}
class Test(val a: Int)
// EXPRESSION: 1 + 1
// RESULT: 2: I
// EXPRESSION: Test(1).a
// RESULT: 1: I
@@ -16,4 +16,4 @@ interface T {
// RESULT: 1: I
// EXPRESSION: object: T {}
// RESULT: instance of packageForDebugger.DebugFileKt$myFun$1(id=ID): LpackageForDebugger/DebugFileKt$myFun$1;
// RESULT: instance of ceObject.DebugFileKt$generated_for_debugger_kotlin_rulezzzz$1(id=ID): LceObject/DebugFileKt$generated_for_debugger_kotlin_rulezzzz$1;