[kotlin] implement asynchronous smart step target fetching

^KTIJ-19896 fixed
^KTIJ-20281 fixed
^KTIJ-19441 fixed

GitOrigin-RevId: c006fdb152440b56456e943501b1ff4171721a70
This commit is contained in:
Nikita Nazarov
2021-12-06 08:36:34 +00:00
committed by intellij-monorepo-bot
parent bf60c80805
commit 3d5838986e
@@ -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<SmartStepTarget> {
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<List<SmartStepTarget>> {
val result = AsyncPromise<List<SmartStepTarget>>()
session.process.managerThread.schedule(
object : DebuggerContextCommandImpl(session.contextManager.context) {
override fun threadAction(suspendContext: SuspendContextImpl) =
result.compute { findSmartStepTargetsInReadAction(position) }
return runReadAction {
val consumer = OrderedSet<SmartStepTarget>()
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<SmartStepTarget> =
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<List<SmartStepTarget>> {
findSmartStepTargets(position)
}.executeSynchronously()
private fun findSmartStepTargets(position: SourcePosition): List<SmartStepTarget> {
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<SmartStepTarget>()
val visitor = SmartStepTargetVisitor(ktElement, lines, consumer)
ktElement.accept(visitor, null)
return consumer
}