Debugger: do not change package name for debug function
This commit is contained in:
+9
-10
@@ -16,22 +16,22 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.debugger.evaluate
|
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.SourcePosition
|
||||||
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
|
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
|
||||||
import java.util.ArrayList
|
|
||||||
import com.intellij.openapi.components.ServiceManager
|
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 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.apache.log4j.Logger
|
||||||
import org.jetbrains.eval4j.Value
|
import org.jetbrains.eval4j.Value
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
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) {
|
class KotlinEvaluateExpressionCache(val project: Project) {
|
||||||
|
|
||||||
@@ -89,7 +89,6 @@ class KotlinEvaluateExpressionCache(val project: Project) {
|
|||||||
val bytecodes: ByteArray,
|
val bytecodes: ByteArray,
|
||||||
val additionalClasses: List<Pair<String, ByteArray>>,
|
val additionalClasses: List<Pair<String, ByteArray>>,
|
||||||
val sourcePosition: SourcePosition,
|
val sourcePosition: SourcePosition,
|
||||||
val funName: String,
|
|
||||||
val parameters: ParametersDescriptor
|
val parameters: ParametersDescriptor
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -81,7 +81,8 @@ import java.util.*
|
|||||||
|
|
||||||
internal val RECEIVER_NAME = "\$receiver"
|
internal val RECEIVER_NAME = "\$receiver"
|
||||||
internal val THIS_NAME = "this"
|
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
|
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()
|
val additionalFiles = if (outputFiles.size < 2) emptyList()
|
||||||
else outputFiles.subList(1, outputFiles.size).map { getClassName(it.relativePath) to it.asByteArray() }
|
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(),
|
outputFiles.first().asByteArray(),
|
||||||
additionalFiles,
|
additionalFiles,
|
||||||
sourcePosition,
|
sourcePosition,
|
||||||
funName,
|
|
||||||
parametersDescriptor)
|
parametersDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,7 +222,7 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: Sour
|
|||||||
var resultValue: InterpreterResult? = null
|
var resultValue: InterpreterResult? = null
|
||||||
ClassReader(compiledData.bytecodes).accept(object : ClassVisitor(ASM5) {
|
ClassReader(compiledData.bytecodes).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? {
|
||||||
if (name == compiledData.funName) {
|
if (name == GENERATED_FUNCTION_NAME) {
|
||||||
val argumentTypes = Type.getArgumentTypes(desc)
|
val argumentTypes = Type.getArgumentTypes(desc)
|
||||||
val args = context.getArgumentsForEval4j(compiledData.parameters, argumentTypes)
|
val args = context.getArgumentsForEval4j(compiledData.parameters, argumentTypes)
|
||||||
|
|
||||||
@@ -255,7 +252,7 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: Sour
|
|||||||
}
|
}
|
||||||
}, 0)
|
}, 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 {
|
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 = """
|
private val template = """
|
||||||
package packageForDebugger
|
!PACKAGE!
|
||||||
|
|
||||||
!IMPORT_LIST!
|
!IMPORT_LIST!
|
||||||
|
|
||||||
@@ -481,17 +478,17 @@ private fun createFileForDebugger(codeFragment: KtCodeFragment,
|
|||||||
): KtFile {
|
): KtFile {
|
||||||
val containingContextFile = codeFragment.getContextContainingFile()
|
val containingContextFile = codeFragment.getContextContainingFile()
|
||||||
val importsFromContextFile = containingContextFile?.importList?.let { it.text + "\n" } ?: ""
|
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(
|
var fileText = template.replace(
|
||||||
"!IMPORT_LIST!",
|
"!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
|
val extractedFunctionText = extractedFunction.text
|
||||||
assert(extractedFunctionText != null) { "Text of extracted function shouldn't be null" }
|
assert(extractedFunctionText != null) { "Text of extracted function shouldn't be null" }
|
||||||
fileText = fileText.replace("!FUNCTION!", extractedFunction.text!!)
|
fileText = fileText.replace("!FUNCTION!", extractedFunction.text!!)
|
||||||
|
|||||||
+1
-1
@@ -100,7 +100,7 @@ fun getFunctionForExtractedFragment(
|
|||||||
|
|
||||||
val generatorOptions = ExtractionGeneratorOptions(inTempFile = true,
|
val generatorOptions = ExtractionGeneratorOptions(inTempFile = true,
|
||||||
flexibleTypesAllowed = true,
|
flexibleTypesAllowed = true,
|
||||||
allowDummyName = true,
|
dummyName = GENERATED_FUNCTION_NAME,
|
||||||
allowExpressionBody = false)
|
allowExpressionBody = false)
|
||||||
return ExtractionGeneratorConfiguration(validationResult.descriptor, generatorOptions).generateDeclaration()
|
return ExtractionGeneratorConfiguration(validationResult.descriptor, generatorOptions).generateDeclaration()
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -414,7 +414,7 @@ data class ExtractionGeneratorOptions(
|
|||||||
val inTempFile: Boolean = false,
|
val inTempFile: Boolean = false,
|
||||||
val target: ExtractionTarget = ExtractionTarget.FUNCTION,
|
val target: ExtractionTarget = ExtractionTarget.FUNCTION,
|
||||||
val flexibleTypesAllowed: Boolean = false,
|
val flexibleTypesAllowed: Boolean = false,
|
||||||
val allowDummyName: Boolean = false,
|
val dummyName: String? = null,
|
||||||
val allowExpressionBody: Boolean = true,
|
val allowExpressionBody: Boolean = true,
|
||||||
val delayInitialOccurrenceReplacement: Boolean = false
|
val delayInitialOccurrenceReplacement: Boolean = false
|
||||||
) {
|
) {
|
||||||
|
|||||||
+1
-1
@@ -93,7 +93,7 @@ fun ExtractionGeneratorConfiguration.getDeclarationText(
|
|||||||
builder.receiver(if (isFunctionType) "($receiverTypeAsString)" else receiverTypeAsString)
|
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 ->
|
descriptor.parameters.forEach { parameter ->
|
||||||
builder.param(parameter.name,
|
builder.param(parameter.name,
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ LineBreakpoint created at .kt.kt:5
|
|||||||
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||||
.kt.kt:5
|
.kt.kt:5
|
||||||
Compile bytecode for 1 + 1
|
Compile bytecode for 1 + 1
|
||||||
|
Compile bytecode for Test(1).a
|
||||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||||
|
|
||||||
Process finished with exit code 0
|
Process finished with exit code 0
|
||||||
|
|||||||
@@ -5,5 +5,10 @@ fun main(args: Array<String>) {
|
|||||||
args.size()
|
args.size()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Test(val a: Int)
|
||||||
|
|
||||||
// EXPRESSION: 1 + 1
|
// EXPRESSION: 1 + 1
|
||||||
// RESULT: 2: I
|
// RESULT: 2: I
|
||||||
|
|
||||||
|
// EXPRESSION: Test(1).a
|
||||||
|
// RESULT: 1: I
|
||||||
|
|||||||
Vendored
+1
-1
@@ -16,4 +16,4 @@ interface T {
|
|||||||
// RESULT: 1: I
|
// RESULT: 1: I
|
||||||
|
|
||||||
// EXPRESSION: object: T {}
|
// 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;
|
||||||
Reference in New Issue
Block a user