Evaluate expression: find local variable using callText from extract function instead of function parameter names

This commit is contained in:
Natalia Ukhorskaya
2015-03-10 14:23:28 +03:00
parent cdf081ddc3
commit 3eb2182ef0
5 changed files with 55 additions and 17 deletions
@@ -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
}
@@ -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() }
@@ -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
@@ -0,0 +1,21 @@
package innerClass
fun main(args: Array<String>) {
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
@@ -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");