mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 03:21:12 +07:00
[debugger, kotlin] Smart step into: provide sync method for tests
* do not block DMT * fix flaky tests GitOrigin-RevId: d9f319d158d1f79f8fb1e664b43d72e7cf8403ab
This commit is contained in:
committed by
intellij-monorepo-bot
parent
436f5dd33f
commit
2fc7868ad6
@@ -25,6 +25,7 @@ import com.intellij.psi.util.parents
|
||||
import com.intellij.util.Range
|
||||
import com.intellij.util.containers.OrderedSet
|
||||
import com.sun.jdi.Location
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.concurrency.Promise
|
||||
import org.jetbrains.concurrency.asPromise
|
||||
import org.jetbrains.kotlin.idea.base.psi.getTopmostElementAtOffset
|
||||
@@ -53,9 +54,12 @@ class KotlinSmartStepIntoHandler : JvmSmartStepIntoHandler() {
|
||||
findSmartStepTargetsInternal(position, session)
|
||||
}.asPromise()
|
||||
|
||||
override fun findSmartStepTargets(position: SourcePosition): List<SmartStepTarget> =
|
||||
override fun findSmartStepTargets(position: SourcePosition) = findSmartStepTargetsSync(position, null)
|
||||
|
||||
@ApiStatus.Internal
|
||||
fun findSmartStepTargetsSync(position: SourcePosition, session: DebuggerSession?): List<SmartStepTarget> =
|
||||
runBlockingCancellable {
|
||||
findSmartStepTargetsInternal(position, null)
|
||||
findSmartStepTargetsInternal(position, session)
|
||||
}
|
||||
|
||||
override fun createMethodFilter(stepTarget: SmartStepTarget?): MethodFilter? =
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.kotlin.idea.debugger.stepping.smartStepInto
|
||||
|
||||
import com.intellij.debugger.engine.PositionManagerAsync
|
||||
import com.intellij.debugger.PositionManager
|
||||
import com.intellij.openapi.application.readAction
|
||||
import com.intellij.psi.util.parentOfType
|
||||
import com.sun.jdi.Location
|
||||
import kotlinx.coroutines.future.await
|
||||
import org.jetbrains.kotlin.idea.debugger.base.util.safeGetSourcePosition
|
||||
import org.jetbrains.kotlin.idea.debugger.base.util.safeMethod
|
||||
import org.jetbrains.kotlin.idea.debugger.core.getInlineFunctionAndArgumentVariablesToBordersMap
|
||||
import org.jetbrains.kotlin.idea.debugger.core.isInlineFunctionMarkerVariableName
|
||||
@@ -56,7 +56,7 @@ internal class KotlinSmartStepTargetFiltererAdapter(
|
||||
|
||||
suspend fun visitTrace(
|
||||
targetFilterer: KotlinSmartStepTargetFilterer,
|
||||
positionManager: PositionManagerAsync
|
||||
positionManager: PositionManager
|
||||
): Pair<List<KotlinMethodSmartStepTarget>, List<KotlinMethodSmartStepTarget>> {
|
||||
for (element in visitedTrace) {
|
||||
visitTraceElement(element, targetFilterer, positionManager)
|
||||
@@ -72,7 +72,7 @@ internal class KotlinSmartStepTargetFiltererAdapter(
|
||||
private suspend fun visitTraceElement(
|
||||
element: BytecodeTraceElement,
|
||||
targetFilterer: KotlinSmartStepTargetFilterer,
|
||||
positionManager: PositionManagerAsync
|
||||
positionManager: PositionManager
|
||||
) {
|
||||
when (element) {
|
||||
is BytecodeTraceElement.InlineCall -> {
|
||||
@@ -108,7 +108,7 @@ private fun extractInlineCalls(location: Location): List<InlineCallInfo> = locat
|
||||
// Filter already visible variable to support smart-step-into while inside an inline function
|
||||
.filterNot { location.codeIndex() in it.bciRange }
|
||||
|
||||
private suspend fun getCalledInlineFunction(positionManager: PositionManagerAsync, location: Location): KtNamedFunction? {
|
||||
val sourcePosition = positionManager.getSourcePositionAsync(location).await()
|
||||
return readAction { sourcePosition?.elementAt?.parentOfType<KtNamedFunction>() }
|
||||
private suspend fun getCalledInlineFunction(positionManager: PositionManager, location: Location): KtNamedFunction? {
|
||||
val sourcePosition = positionManager.safeGetSourcePosition(location) ?: return null
|
||||
return readAction { sourcePosition.elementAt?.parentOfType<KtNamedFunction>() }
|
||||
}
|
||||
|
||||
@@ -21,9 +21,7 @@ import com.intellij.execution.process.ProcessOutputTypes
|
||||
import com.intellij.jarRepository.JarRepositoryManager
|
||||
import com.intellij.jarRepository.RemoteRepositoryDescription
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.readAction
|
||||
import com.intellij.openapi.application.runReadAction
|
||||
import com.intellij.openapi.components.ComponentManagerEx
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.roots.OrderRootType
|
||||
import com.intellij.openapi.roots.libraries.ui.OrderRoot
|
||||
@@ -32,11 +30,6 @@ import com.intellij.testFramework.runInEdtAndWait
|
||||
import com.intellij.xdebugger.frame.XStackFrame
|
||||
import com.intellij.xdebugger.impl.XSourcePositionImpl
|
||||
import junit.framework.AssertionFailedError
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jetbrains.concurrency.asDeferred
|
||||
import org.jetbrains.idea.maven.aether.ArtifactKind
|
||||
import org.jetbrains.jps.model.library.JpsMavenRepositoryLibraryDescriptor
|
||||
import org.jetbrains.kotlin.idea.base.test.InTextDirectivesUtils.areLogErrorsIgnored
|
||||
@@ -189,9 +182,6 @@ abstract class KotlinDescriptorTestCaseWithStepping : KotlinDescriptorTestCase()
|
||||
dp.managerThread.schedule(stepOverCommand)
|
||||
}
|
||||
|
||||
private fun launch(block: suspend CoroutineScope.() -> Unit) =
|
||||
(project as ComponentManagerEx).getCoroutineScope().launch(block = block)
|
||||
|
||||
private fun process(instruction: SteppingInstruction) {
|
||||
fun loop(count: Int, block: SuspendContextImpl.() -> Unit) {
|
||||
repeat(count) {
|
||||
@@ -206,20 +196,18 @@ abstract class KotlinDescriptorTestCaseWithStepping : KotlinDescriptorTestCase()
|
||||
SteppingInstructionKind.StepOut -> loop(instruction.arg) { doStepOut() }
|
||||
SteppingInstructionKind.StepOver -> loop(instruction.arg) { doStepOver() }
|
||||
SteppingInstructionKind.ForceStepOver -> loop(instruction.arg) { doStepOver(ignoreBreakpoints = true) }
|
||||
SteppingInstructionKind.SmartStepInto -> loop(instruction.arg) { launch { doSmartStepInto() } }
|
||||
SteppingInstructionKind.SmartStepIntoByIndex -> doOnBreakpoint { launch { doSmartStepInto(instruction.arg) } }
|
||||
SteppingInstructionKind.SmartStepInto -> loop(instruction.arg) { doSmartStepInto() }
|
||||
SteppingInstructionKind.SmartStepIntoByIndex -> doOnBreakpoint { doSmartStepInto(instruction.arg) }
|
||||
SteppingInstructionKind.Resume -> loop(instruction.arg) { resume(this) }
|
||||
SteppingInstructionKind.SmartStepTargetsExpectedNumber ->
|
||||
doOnBreakpoint {
|
||||
launch {
|
||||
checkNumberOfSmartStepTargets(instruction.arg)
|
||||
this@KotlinDescriptorTestCaseWithStepping.resume(this@doOnBreakpoint)
|
||||
}
|
||||
checkNumberOfSmartStepTargets(instruction.arg)
|
||||
resume(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun checkNumberOfSmartStepTargets(expectedNumber: Int) {
|
||||
private fun checkNumberOfSmartStepTargets(expectedNumber: Int) {
|
||||
val smartStepFilters = createSmartStepIntoFilters()
|
||||
try {
|
||||
assertEquals(
|
||||
@@ -232,7 +220,7 @@ abstract class KotlinDescriptorTestCaseWithStepping : KotlinDescriptorTestCase()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun SuspendContextImpl.doSmartStepInto(chooseFromList: Int = 0) {
|
||||
private fun SuspendContextImpl.doSmartStepInto(chooseFromList: Int = 0) {
|
||||
this.doSmartStepInto(chooseFromList, false)
|
||||
}
|
||||
|
||||
@@ -280,7 +268,7 @@ abstract class KotlinDescriptorTestCaseWithStepping : KotlinDescriptorTestCase()
|
||||
|
||||
protected open fun extraPrintContext(context: SuspendContextImpl) {}
|
||||
|
||||
private suspend fun SuspendContextImpl.doSmartStepInto(chooseFromList: Int, ignoreFilters: Boolean) {
|
||||
private fun SuspendContextImpl.doSmartStepInto(chooseFromList: Int, ignoreFilters: Boolean) {
|
||||
val filters = createSmartStepIntoFilters()
|
||||
if (chooseFromList == 0) {
|
||||
if (filters.isEmpty()) {
|
||||
@@ -303,26 +291,22 @@ abstract class KotlinDescriptorTestCaseWithStepping : KotlinDescriptorTestCase()
|
||||
elementAt.getElementTextWithContext()
|
||||
}
|
||||
|
||||
private suspend fun createSmartStepIntoFilters(): List<MethodFilter> {
|
||||
val position = debuggerContext.sourcePosition
|
||||
val stepTargets = withContext(Dispatchers.Default) {
|
||||
KotlinSmartStepIntoHandler()
|
||||
.findStepIntoTargets(position, debuggerSession)
|
||||
.asDeferred().await()
|
||||
}
|
||||
private fun createSmartStepIntoFilters(): List<MethodFilter> {
|
||||
val stepTargets = KotlinSmartStepIntoHandler()
|
||||
.findSmartStepTargetsSync(debuggerContext.sourcePosition, debuggerSession)
|
||||
|
||||
// the resulting order is different from the order in code when stepping some methods are filtered
|
||||
// due to de-prioritisation in JvmSmartStepIntoHandler.reorderWithSteppingFilters
|
||||
if (readAction { stepTargets.none { DebugProcessImpl.isClassFiltered(it.className)} }) {
|
||||
if (runReadAction { stepTargets.none { DebugProcessImpl.isClassFiltered(it.className)} }) {
|
||||
try {
|
||||
assertEquals("Smart step targets are not sorted by position in tree",
|
||||
stepTargets.sortedByPositionInTree().map { readAction { it.presentation } },
|
||||
stepTargets.map { readAction { it.presentation } })
|
||||
stepTargets.sortedByPositionInTree().map { runReadAction { it.presentation } },
|
||||
stepTargets.map { runReadAction { it.presentation } })
|
||||
} catch (e: AssertionFailedError) {
|
||||
thrownExceptions.add(e)
|
||||
}
|
||||
}
|
||||
return readAction {
|
||||
return runReadAction {
|
||||
stepTargets.mapNotNull { stepTarget ->
|
||||
when (stepTarget) {
|
||||
is KotlinSmartStepTarget -> stepTarget.createMethodFilter()
|
||||
|
||||
Reference in New Issue
Block a user