Debugger: fix evaluate expression when breakpoint is set on function without body inside object

#KT-15855 Fixed
This commit is contained in:
Natalia Ukhorskaya
2017-01-27 17:31:11 +03:00
committed by Nikolay Krasko
parent faac1c3156
commit 68f722b337
3 changed files with 23 additions and 19 deletions
@@ -24,11 +24,9 @@ import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.util.ExceptionUtil
import org.jetbrains.kotlin.idea.actions.internal.KotlinInternalMode
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFullyAndGetResult
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.intentions.InsertExplicitTypeArgumentsIntention
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.*
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.AnalysisResult.ErrorMessage
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.AnalysisResult.Status
@@ -42,7 +40,6 @@ import org.jetbrains.kotlin.psi.codeFragmentUtil.suppressDiagnosticsInDebugMode
import org.jetbrains.kotlin.psi.psiUtil.findDescendantOfType
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.BindingContext.IMPLICIT_RECEIVER_SMARTCAST
import org.jetbrains.kotlin.resolve.BindingContext.SMARTCAST
fun getFunctionForExtractedFragment(
@@ -290,12 +287,12 @@ private fun findElementBefore(contextElement: PsiElement): PsiElement? {
contextElement is KtProperty && !contextElement.isLocal -> {
val delegateExpressionOrInitializer = contextElement.delegateExpressionOrInitializer
if (delegateExpressionOrInitializer != null) {
wrapInRunFun(delegateExpressionOrInitializer)
wrapInLambdaCall(delegateExpressionOrInitializer)
}
else {
val getter = contextElement.getter!!
if (!getter.hasBlockBody()) {
wrapInRunFun(getter.bodyExpression!!)
wrapInLambdaCall(getter.bodyExpression!!)
}
else {
(getter.bodyExpression as KtBlockExpression).statements.first()
@@ -323,7 +320,7 @@ private fun findElementBefore(contextElement: PsiElement): PsiElement? {
newBlock.rBrace
}
contextElement is KtDeclarationWithBody && !contextElement.hasBlockBody() -> {
wrapInRunFun(contextElement.bodyExpression!!)
wrapInLambdaCall(contextElement.bodyExpression!!)
}
contextElement is KtDeclarationWithBody && contextElement.hasBlockBody() -> {
val block = contextElement.bodyExpression as KtBlockExpression
@@ -336,7 +333,7 @@ private fun findElementBefore(contextElement: PsiElement): PsiElement? {
entryExpression.statements.firstOrNull() ?: entryExpression.lastChild
}
else {
wrapInRunFun(entryExpression!!)
wrapInLambdaCall(entryExpression!!)
}
}
else -> {
@@ -345,18 +342,12 @@ private fun findElementBefore(contextElement: PsiElement): PsiElement? {
}
}
private fun replaceByRunFunction(expression: KtExpression): KtCallExpression {
val callExpression = KtPsiFactory(expression).createExpression("run { \n${expression.text} \n}") as KtCallExpression
val replaced = expression.replaced(callExpression)
val typeArguments = InsertExplicitTypeArgumentsIntention.createTypeArguments(replaced, replaced.analyze())
if (typeArguments?.arguments?.isNotEmpty() ?: false) {
val calleeExpression = replaced.calleeExpression
replaced.addAfter(typeArguments!!, calleeExpression)
}
return replaced
private fun replaceByLambdaCall(expression: KtExpression): KtCallExpression {
val callExpression = KtPsiFactory(expression).createExpression("{ \n${expression.text} \n}()") as KtCallExpression
return expression.replaced(callExpression)
}
private fun wrapInRunFun(expression: KtExpression): PsiElement? {
val replacedBody = replaceByRunFunction(expression)
return replacedBody.lambdaArguments.first().getLambdaExpression().bodyExpression?.firstChild
private fun wrapInLambdaCall(expression: KtExpression): PsiElement? {
val replacedBody = replaceByLambdaCall(expression)
return (replacedBody.calleeExpression as? KtLambdaExpression)?.bodyExpression?.firstChild
}
@@ -4,6 +4,7 @@ LineBreakpoint created at withoutBodyFunctions.kt:21
LineBreakpoint created at withoutBodyFunctions.kt:27
LineBreakpoint created at withoutBodyFunctions.kt:32
LineBreakpoint created at withoutBodyFunctions.kt:37
LineBreakpoint created at withoutBodyFunctions.kt:43
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !OUTPUT_PATH!;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! withoutBodyFunctions.WithoutBodyFunctionsKt
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
withoutBodyFunctions.kt:9
@@ -18,6 +19,8 @@ withoutBodyFunctions.kt:32
Compile bytecode for i
withoutBodyFunctions.kt:37
Compile bytecode for i
withoutBodyFunctions.kt:43
Compile bytecode for test2()
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
@@ -36,6 +36,14 @@ fun fooOneLine(i: Int): Int { return 1 }
//Breakpoint!
fun fooEmpty(i: Int) {}
object A {
// EXPRESSION: test2()
// RESULT: 2: I
//Breakpoint!
@JvmStatic fun fooWithoutBodyInsideObject() = test2()
fun test2() = 2
}
fun main(args: Array<String>) {
aGet
aGet2
@@ -44,4 +52,6 @@ fun main(args: Array<String>) {
foo(2)
fooOneLine(2)
fooEmpty(2)
A.fooWithoutBodyInsideObject()
}