From 3eb2182ef0a160e365ce6db22aa1ff42bc24c804 Mon Sep 17 00:00:00 2001 From: Natalia Ukhorskaya Date: Tue, 10 Mar 2015 14:23:28 +0300 Subject: [PATCH] Evaluate expression: find local variable using callText from extract function instead of function parameter names --- .../evaluate/KotlinEvaluationBuilder.kt | 31 ++++++++++--------- .../extractFunctionForDebuggerUtil.kt | 6 ++-- .../debugger/tinyApp/outs/innerClass.out | 8 +++++ .../evaluate/singleBreakpoint/innerClass.kt | 21 +++++++++++++ ...KotlinEvaluateExpressionTestGenerated.java | 6 ++++ 5 files changed, 55 insertions(+), 17 deletions(-) create mode 100644 idea/testData/debugger/tinyApp/outs/innerClass.out create mode 100644 idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/innerClass.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluationBuilder.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluationBuilder.kt index 1461c6d36f5..ccc54ee75f0 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluationBuilder.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluationBuilder.kt @@ -53,6 +53,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyzeFullyAndGetResult import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinEvaluateExpressionCache.CompiledDataDescriptor import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinEvaluateExpressionCache.ParametersDescriptor import org.jetbrains.kotlin.idea.debugger.evaluate.compilingEvaluator.loadClasses +import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.ExtractionResult import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.idea.util.attachment.attachmentByPsiFile import org.jetbrains.kotlin.idea.util.attachment.mergeAttachments @@ -152,10 +153,11 @@ class KotlinEvaluator(val codeFragment: JetCodeFragment, private fun extractAndCompile(codeFragment: JetCodeFragment, sourcePosition: SourcePosition, context: EvaluationContextImpl): CompiledDataDescriptor { codeFragment.checkForErrors() - val extractedFunction = getFunctionForExtractedFragment(codeFragment, sourcePosition.getFile(), sourcePosition.getLine()) - if (extractedFunction == null) { + val extractionResult = getFunctionForExtractedFragment(codeFragment, sourcePosition.getFile(), sourcePosition.getLine()) + if (extractionResult == null) { throw IllegalStateException("Code fragment cannot be extracted to function") } + val extractedFunction = extractionResult.declaration as JetNamedFunction val classFileFactory = createClassFileFactory(codeFragment, extractedFunction, context) @@ -177,7 +179,7 @@ class KotlinEvaluator(val codeFragment: JetCodeFragment, additionalFiles, sourcePosition, funName, - extractedFunction.getParametersForDebugger()) + extractionResult.getParametersForDebugger()) } private fun getClassName(fileName: String): String { @@ -239,21 +241,22 @@ class KotlinEvaluator(val codeFragment: JetCodeFragment, return jdiValue.asJdiValue(vm, jdiValue.asmType) } - private fun JetNamedFunction.getParametersForDebugger(): ParametersDescriptor { + private fun ExtractionResult.getParametersForDebugger(): ParametersDescriptor { return runReadAction { val parameters = ParametersDescriptor() - val bindingContext = analyzeFullyAndGetResult().bindingContext - val descriptor = bindingContext[BindingContext.FUNCTION, this] - if (descriptor != null) { - val receiver = descriptor.getExtensionReceiverParameter() - if (receiver != null) { - parameters.add(THIS_NAME, receiver.getType()) - } + val receiver = config.descriptor.receiverParameter + if (receiver != null) { + parameters.add(THIS_NAME, receiver.getParameterType(true)) + } - descriptor.getValueParameters().forEach { - param -> - parameters.add(param.getName().asString(), param.getType()) + for (param in config.descriptor.parameters) { + val paramName = if (param.argumentText.contains("@")) { + param.argumentText.substringBefore("@") } + else { + param.argumentText + } + parameters.add(paramName, param.getParameterType(true)) } parameters } diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/extractFunctionForDebuggerUtil.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/extractFunctionForDebuggerUtil.kt index da35da8121e..feba97a8050 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/extractFunctionForDebuggerUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/extractFunctionForDebuggerUtil.kt @@ -38,7 +38,7 @@ fun getFunctionForExtractedFragment( codeFragment: JetCodeFragment, breakpointFile: PsiFile, breakpointLine: Int -): JetNamedFunction? { +): ExtractionResult? { fun getErrorMessageForExtractFunctionResult(analysisResult: AnalysisResult): String { if (KotlinInternalMode.enabled) { @@ -66,7 +66,7 @@ fun getFunctionForExtractedFragment( }.joinToString(", ") } - fun generateFunction(): JetNamedFunction? { + fun generateFunction(): ExtractionResult? { val originalFile = breakpointFile as JetFile val tmpFile = originalFile.createTempCopy { it } @@ -105,7 +105,7 @@ fun getFunctionForExtractedFragment( validationResult.descriptor, ExtractionGeneratorOptions(inTempFile = true, flexibleTypesAllowed = true) ) - return config.generateDeclaration().declaration as JetNamedFunction + return config.generateDeclaration() } return runReadAction { generateFunction() } diff --git a/idea/testData/debugger/tinyApp/outs/innerClass.out b/idea/testData/debugger/tinyApp/outs/innerClass.out new file mode 100644 index 00000000000..b6f129e24e6 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/innerClass.out @@ -0,0 +1,8 @@ +LineBreakpoint created at innerClass.kt:13 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! innerClass.InnerClassPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +innerClass.kt:13 +Compile bytecode for baseFun(innerProp) +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/innerClass.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/innerClass.kt new file mode 100644 index 00000000000..120d5e0f573 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/innerClass.kt @@ -0,0 +1,21 @@ +package innerClass + +fun main(args: Array) { + MyClass().MyInnerClass().innerFun() +} + +class MyClass { + inner class MyInnerClass { + val innerProp = 1 + + fun innerFun() { + //Breakpoint! + baseFun(innerProp) + } + } + + fun baseFun(i: Int) = i +} + +// EXPRESSION: baseFun(innerProp) +// RESULT: 1: I \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java index 645cb7f10c3..a5a868bd813 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java @@ -151,6 +151,12 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat doSingleBreakpointTest(fileName); } + @TestMetadata("innerClass.kt") + public void testInnerClass() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/innerClass.kt"); + doSingleBreakpointTest(fileName); + } + @TestMetadata("insertInBlock.kt") public void testInsertInBlock() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/insertInBlock.kt");