Adjust debugger to the new suspend function strategy

Now it's impossible to determine by descriptor if there is
a state machine for function, but at the same time
it doesn't really matter here since there is no LINENUMBERs
in doResume of continuation implementations for named suspend
functions

 #KT-17585 Fixed
 #KT-16603 Fixed
This commit is contained in:
Denis Zharkov
2017-05-04 19:00:54 +03:00
parent 7c6a15ddfe
commit 6e114a90dc
5 changed files with 17 additions and 29 deletions
@@ -24,18 +24,15 @@ import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiTreeUtil
import com.sun.jdi.AbsentInformationException import com.sun.jdi.AbsentInformationException
import com.sun.jdi.ReferenceType import com.sun.jdi.ReferenceType
import org.jetbrains.kotlin.codegen.binding.CodegenBinding.* import org.jetbrains.kotlin.codegen.binding.CodegenBinding.asmTypeForAnonymousClass
import org.jetbrains.kotlin.codegen.coroutines.containsNonTailSuspensionCalls
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider
import org.jetbrains.kotlin.fileClasses.getFileClassInternalName import org.jetbrains.kotlin.fileClasses.getFileClassInternalName
import org.jetbrains.kotlin.idea.debugger.breakpoints.getLambdasAtLineIfAny import org.jetbrains.kotlin.idea.debugger.breakpoints.getLambdasAtLineIfAny
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches.ComputedClassNames
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches.ComputedClassNames.Companion.EMPTY
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches.Companion.getOrComputeClassNames import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches.Companion.getOrComputeClassNames
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches.ComputedClassNames
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches.ComputedClassNames.Companion.Cached import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches.ComputedClassNames.Companion.Cached
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches.ComputedClassNames.Companion.EMPTY
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches.ComputedClassNames.Companion.NonCached import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches.ComputedClassNames.Companion.NonCached
import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
@@ -187,12 +184,11 @@ class DebuggerClassNameProvider(
} }
is KtNamedFunction -> { is KtNamedFunction -> {
val typeMapper = KotlinDebuggerCaches.getOrCreateTypeMapper(element) val typeMapper = KotlinDebuggerCaches.getOrCreateTypeMapper(element)
val descriptor = typeMapper.bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element)
val classNamesOfContainingDeclaration = getOuterClassNamesForElement(element.relevantParentInReadAction) val classNamesOfContainingDeclaration = getOuterClassNamesForElement(element.relevantParentInReadAction)
val nonInlineClasses: ComputedClassNames val nonInlineClasses: ComputedClassNames
if (runReadAction { element.name == null || element.isLocal } || isFunctionWithSuspendStateMachine(descriptor, typeMapper.bindingContext)) { if (runReadAction { element.name == null || element.isLocal }) {
nonInlineClasses = classNamesOfContainingDeclaration + ComputedClassNames.Cached( nonInlineClasses = classNamesOfContainingDeclaration + ComputedClassNames.Cached(
asmTypeForAnonymousClass(typeMapper.bindingContext, element).internalName.toJdiName()) asmTypeForAnonymousClass(typeMapper.bindingContext, element).internalName.toJdiName())
} }
@@ -246,10 +242,6 @@ class DebuggerClassNameProvider(
return type.className return type.className
} }
private fun isFunctionWithSuspendStateMachine(descriptor: DeclarationDescriptor?, bindingContext: BindingContext): Boolean {
return descriptor is SimpleFunctionDescriptor && descriptor.isSuspend && descriptor.containsNonTailSuspensionCalls(bindingContext)
}
private val KtDeclaration.isInlineInReadAction: Boolean private val KtDeclaration.isInlineInReadAction: Boolean
get() = runReadAction { hasModifier(KtTokens.INLINE_KEYWORD) } get() = runReadAction { hasModifier(KtTokens.INLINE_KEYWORD) }
-2
View File
@@ -2,10 +2,8 @@ LineBreakpoint created at siSuspendFun.kt:29
Run Java Run Java
Connected to the target VM Connected to the target VM
siSuspendFun.kt:29 siSuspendFun.kt:29
siSuspendFun.kt:21
siSuspendFun.kt:22 siSuspendFun.kt:22
siSuspendFun.kt:18 siSuspendFun.kt:18
siSuspendFun.kt:18
siSuspendFun.kt:14 siSuspendFun.kt:14
siSuspendFun.kt:10 siSuspendFun.kt:10
siSuspendFun.kt:6 siSuspendFun.kt:6
-2
View File
@@ -5,9 +5,7 @@ souSuspendFun.kt:7
souSuspendFun.kt:11 souSuspendFun.kt:11
souSuspendFun.kt:15 souSuspendFun.kt:15
souSuspendFun.kt:19 souSuspendFun.kt:19
souSuspendFun.kt:19
souSuspendFun.kt:23 souSuspendFun.kt:23
souSuspendFun.kt:25
souSuspendFun.kt:29 souSuspendFun.kt:29
Disconnected from the target VM Disconnected from the target VM
@@ -3,23 +3,23 @@ package siSuspendFun
import forTests.builder import forTests.builder
private fun foo(): Int { private fun foo(): Int {
return 42 // 8 return 42 // 6
} }
// One line suspend wihtout doResume // One line suspend wihtout doResume
suspend fun fourth() = foo() // 7 suspend fun fourth() = foo() // 5
// Multiline suspend without doResume // Multiline suspend without doResume
suspend fun third() : Int? { suspend fun third() : Int? {
return fourth() // 6 return fourth() // 4
} }
// One line suspend with doResume // One line suspend with doResume
suspend fun second(): Int = third()?.let { return it } ?: 0 // 4 (FIX IT!) 5 suspend fun second(): Int = third()?.let { return it } ?: 0 // 3
// Multiline suspend with doResume // Multiline suspend with doResume
suspend fun first(): Int { // 2 (FIX IT!) suspend fun first(): Int { //
second() // 3 second() // 2
return 12 return 12
} }
@@ -31,4 +31,4 @@ fun main(args: Array<String>) {
} }
} }
// STEP_INTO: 7 // STEP_INTO: 5
@@ -16,18 +16,18 @@ suspend fun third() : Int? {
} }
// One line suspend with doResume // One line suspend with doResume
suspend fun second(): Int = third()?.let { return it } ?: 0 // 4 5 (FIX IT) suspend fun second(): Int = third()?.let { return it } ?: 0 // 4 (FIX IT)
// Multiline suspend with doResume // Multiline suspend with doResume
suspend fun first(): Int { suspend fun first(): Int {
second() // 6 second() // 5
return 12 return 12
} // 7 (FIX IT) }
fun main(args: Array<String>) { fun main(args: Array<String>) {
builder { builder {
first() // 8 first() // 6
} }
} }
// STEP_OUT: 7 // STEP_OUT: 5