From 3d5838986e3ded7865b090e5beeedcbede597e5c Mon Sep 17 00:00:00 2001 From: Nikita Nazarov Date: Mon, 6 Dec 2021 10:51:29 +0300 Subject: [PATCH] [kotlin] implement asynchronous smart step target fetching ^KTIJ-19896 fixed ^KTIJ-20281 fixed ^KTIJ-19441 fixed GitOrigin-RevId: c006fdb152440b56456e943501b1ff4171721a70 --- .../KotlinSmartStepIntoHandler.kt | 56 ++++++++++++++----- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/plugins/kotlin/jvm-debugger/core/src/org/jetbrains/kotlin/idea/debugger/stepping/smartStepInto/KotlinSmartStepIntoHandler.kt b/plugins/kotlin/jvm-debugger/core/src/org/jetbrains/kotlin/idea/debugger/stepping/smartStepInto/KotlinSmartStepIntoHandler.kt index 7ed5393349c5..c6c062f9aad1 100644 --- a/plugins/kotlin/jvm-debugger/core/src/org/jetbrains/kotlin/idea/debugger/stepping/smartStepInto/KotlinSmartStepIntoHandler.kt +++ b/plugins/kotlin/jvm-debugger/core/src/org/jetbrains/kotlin/idea/debugger/stepping/smartStepInto/KotlinSmartStepIntoHandler.kt @@ -6,13 +6,19 @@ import com.intellij.debugger.SourcePosition import com.intellij.debugger.actions.JvmSmartStepIntoHandler import com.intellij.debugger.actions.SmartStepTarget import com.intellij.debugger.engine.MethodFilter +import com.intellij.debugger.engine.SuspendContextImpl +import com.intellij.debugger.engine.events.DebuggerContextCommandImpl import com.intellij.debugger.impl.DebuggerSession +import com.intellij.debugger.impl.PrioritizedTask +import com.intellij.openapi.application.ReadAction import com.intellij.psi.PsiDocumentManager import com.intellij.util.Range import com.intellij.util.containers.OrderedSet +import org.jetbrains.concurrency.AsyncPromise +import org.jetbrains.concurrency.Promise +import org.jetbrains.concurrency.compute import org.jetbrains.kotlin.idea.core.util.CodeInsightUtils.getTopmostElementAtOffset import org.jetbrains.kotlin.idea.debugger.KotlinDebuggerSettings -import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile @@ -26,22 +32,26 @@ class KotlinSmartStepIntoHandler : JvmSmartStepIntoHandler() { super.findStepIntoTargets(position, session) } - override fun findSmartStepTargets(position: SourcePosition): List { - val file = position.file - val element = position.elementAt ?: return emptyList() - val ktElement = getTopmostElementAtOffset(element, element.textRange.startOffset) as? KtElement - val elementTextRange = ktElement?.textRange ?: return emptyList() - val document = PsiDocumentManager.getInstance(file.project).getDocument(file) ?: return emptyList() - val lines = Range(document.getLineNumber(elementTextRange.startOffset), document.getLineNumber(elementTextRange.endOffset)) + override fun findSmartStepTargetsAsync(position: SourcePosition, session: DebuggerSession): Promise> { + val result = AsyncPromise>() + session.process.managerThread.schedule( + object : DebuggerContextCommandImpl(session.contextManager.context) { + override fun threadAction(suspendContext: SuspendContextImpl) = + result.compute { findSmartStepTargetsInReadAction(position) } - return runReadAction { - val consumer = OrderedSet() - val visitor = SmartStepTargetVisitor(ktElement, lines, consumer) - ktElement.accept(visitor, null) - return@runReadAction consumer - } + override fun commandCancelled() { + result.setError("Cancelled") + } + + override fun getPriority() = + PrioritizedTask.Priority.NORMAL + }) + return result } + override fun findSmartStepTargets(position: SourcePosition): List = + findSmartStepTargetsInReadAction(position) + override fun createMethodFilter(stepTarget: SmartStepTarget?): MethodFilter? { return when (stepTarget) { is KotlinSmartStepTarget -> stepTarget.createMethodFilter() @@ -49,3 +59,21 @@ class KotlinSmartStepIntoHandler : JvmSmartStepIntoHandler() { } } } + +private fun findSmartStepTargetsInReadAction(position: SourcePosition) = + ReadAction.nonBlocking> { + findSmartStepTargets(position) + }.executeSynchronously() + +private fun findSmartStepTargets(position: SourcePosition): List { + val element = position.elementAt ?: return emptyList() + val ktElement = getTopmostElementAtOffset(element, element.textRange.startOffset) as? KtElement + val elementTextRange = ktElement?.textRange ?: return emptyList() + val file = position.file + val document = PsiDocumentManager.getInstance(file.project).getDocument(file) ?: return emptyList() + val lines = Range(document.getLineNumber(elementTextRange.startOffset), document.getLineNumber(elementTextRange.endOffset)) + val consumer = OrderedSet() + val visitor = SmartStepTargetVisitor(ktElement, lines, consumer) + ktElement.accept(visitor, null) + return consumer +}