Fix smart step into functions call with suspend lambdas (KT-14700)
#KT-14700 Fixed
This commit is contained in:
@@ -21,6 +21,7 @@ import com.intellij.debugger.engine.BreakpointStepMethodFilter
|
||||
import com.intellij.debugger.engine.DebugProcessImpl
|
||||
import com.intellij.util.Range
|
||||
import com.sun.jdi.Location
|
||||
import org.jetbrains.kotlin.codegen.coroutines.DO_RESUME_METHOD_NAME
|
||||
import org.jetbrains.kotlin.idea.refactoring.isMultiLine
|
||||
import org.jetbrains.kotlin.idea.debugger.isInsideInlineArgument
|
||||
import org.jetbrains.kotlin.psi.KtBlockExpression
|
||||
@@ -30,7 +31,8 @@ import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
class KotlinLambdaMethodFilter(
|
||||
private val lambda: KtFunction,
|
||||
private val myCallingExpressionLines: Range<Int>,
|
||||
private val isInline: Boolean
|
||||
private val isInline: Boolean,
|
||||
private val isSuspend: Boolean
|
||||
): BreakpointStepMethodFilter {
|
||||
private val myFirstStatementPosition: SourcePosition?
|
||||
private val myLastStatementLine: Int
|
||||
@@ -72,9 +74,12 @@ class KotlinLambdaMethodFilter(
|
||||
|
||||
override fun getCallingExpressionLines() = if (isInline) Range(0, 999) else myCallingExpressionLines
|
||||
|
||||
companion object {
|
||||
fun isLambdaName(name: String?): Boolean {
|
||||
return name == OperatorNameConventions.INVOKE.asString()
|
||||
private fun isLambdaName(name: String?): Boolean {
|
||||
if (isSuspend) {
|
||||
return name == DO_RESUME_METHOD_NAME
|
||||
}
|
||||
|
||||
return name == OperatorNameConventions.INVOKE.asString()
|
||||
}
|
||||
|
||||
}
|
||||
+4
-2
@@ -23,14 +23,16 @@ import org.jetbrains.kotlin.idea.KotlinIcons
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import javax.swing.Icon
|
||||
|
||||
class KotlinLambdaSmartStepTarget(
|
||||
label: String,
|
||||
highlightElement: KtFunction,
|
||||
lines: Range<Int>,
|
||||
val isInline: Boolean
|
||||
val isInline: Boolean,
|
||||
val isSuspend: Boolean
|
||||
): SmartStepTarget(label, highlightElement, true, lines) {
|
||||
override fun getIcon() = KotlinIcons.LAMBDA
|
||||
override fun getIcon(): Icon = KotlinIcons.LAMBDA
|
||||
|
||||
fun getLambda() = highlightElement as KtFunction
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.util.Range
|
||||
import com.intellij.util.containers.OrderedSet
|
||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
@@ -50,8 +51,8 @@ class KotlinSmartStepIntoHandler : JvmSmartStepIntoHandler() {
|
||||
|
||||
val elementAtOffset = position.elementAt ?: return emptyList()
|
||||
|
||||
val element = CodeInsightUtils.getTopmostElementAtOffset(elementAtOffset, elementAtOffset.textRange.startOffset)
|
||||
if (element !is KtElement) return emptyList()
|
||||
val element = CodeInsightUtils.getTopmostElementAtOffset(elementAtOffset, elementAtOffset.textRange.startOffset) as? KtElement ?:
|
||||
return emptyList()
|
||||
|
||||
val elementTextRange = element.textRange ?: return emptyList()
|
||||
|
||||
@@ -80,8 +81,10 @@ class KotlinSmartStepIntoHandler : JvmSmartStepIntoHandler() {
|
||||
val arguments = resolvedCall.valueArguments
|
||||
for ((param, argument) in arguments) {
|
||||
if (argument.arguments.any { getArgumentExpression(it) == function }) {
|
||||
val label = KotlinLambdaSmartStepTarget.calcLabel(resolvedCall.resultingDescriptor, param.name)
|
||||
result.add(KotlinLambdaSmartStepTarget(label, function, lines, InlineUtil.isInline(resolvedCall.resultingDescriptor)))
|
||||
val resultingDescriptor = resolvedCall.resultingDescriptor
|
||||
val label = KotlinLambdaSmartStepTarget.calcLabel(resultingDescriptor, param.name)
|
||||
result.add(KotlinLambdaSmartStepTarget(
|
||||
label, function, lines, InlineUtil.isInline(resultingDescriptor), param.type.isSuspendFunctionType))
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -195,8 +198,11 @@ class KotlinSmartStepIntoHandler : JvmSmartStepIntoHandler() {
|
||||
|
||||
override fun createMethodFilter(stepTarget: SmartStepTarget?): MethodFilter? {
|
||||
return when (stepTarget) {
|
||||
is KotlinMethodSmartStepTarget -> KotlinBasicStepMethodFilter(stepTarget.descriptor, stepTarget.callingExpressionLines!!)
|
||||
is KotlinLambdaSmartStepTarget -> KotlinLambdaMethodFilter(stepTarget.getLambda(), stepTarget.callingExpressionLines!!, stepTarget.isInline)
|
||||
is KotlinMethodSmartStepTarget ->
|
||||
KotlinBasicStepMethodFilter(stepTarget.descriptor, stepTarget.callingExpressionLines!!)
|
||||
is KotlinLambdaSmartStepTarget ->
|
||||
KotlinLambdaMethodFilter(
|
||||
stepTarget.getLambda(), stepTarget.callingExpressionLines!!, stepTarget.isInline, stepTarget.isSuspend)
|
||||
else -> super.createMethodFilter(stepTarget)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
LineBreakpoint created at coroutine.kt:15
|
||||
!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! coroutine.CoroutineKt
|
||||
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
coroutine.kt:15
|
||||
coroutine.kt:16
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
@@ -0,0 +1,18 @@
|
||||
package coroutine
|
||||
|
||||
import forTests.builder
|
||||
|
||||
suspend fun second() {
|
||||
}
|
||||
|
||||
suspend fun first() {
|
||||
second()
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
// SMART_STEP_INTO_BY_INDEX: 2
|
||||
//Breakpoint!
|
||||
builder {
|
||||
first()
|
||||
}
|
||||
}
|
||||
@@ -213,8 +213,11 @@ abstract class KotlinDebuggerTestBase : KotlinDebuggerTestCase() {
|
||||
stepTargets.filterIsInstance<SmartStepTarget>().mapNotNull {
|
||||
stepTarget ->
|
||||
when (stepTarget) {
|
||||
is KotlinLambdaSmartStepTarget -> KotlinLambdaMethodFilter(stepTarget.getLambda(), stepTarget.getCallingExpressionLines()!!, stepTarget.isInline)
|
||||
is KotlinMethodSmartStepTarget -> KotlinBasicStepMethodFilter(stepTarget.descriptor, stepTarget.getCallingExpressionLines()!!)
|
||||
is KotlinLambdaSmartStepTarget ->
|
||||
KotlinLambdaMethodFilter(
|
||||
stepTarget.getLambda(), stepTarget.getCallingExpressionLines()!!, stepTarget.isInline, stepTarget.isSuspend)
|
||||
is KotlinMethodSmartStepTarget ->
|
||||
KotlinBasicStepMethodFilter(stepTarget.descriptor, stepTarget.getCallingExpressionLines()!!)
|
||||
is MethodSmartStepTarget -> BasicStepMethodFilter(stepTarget.method, stepTarget.getCallingExpressionLines())
|
||||
else -> null
|
||||
}
|
||||
|
||||
@@ -944,6 +944,12 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/stepping/custom"), Pattern.compile("^([^.]+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("coroutine.kt")
|
||||
public void testCoroutine() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/custom/coroutine.kt");
|
||||
doCustomTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("crossinlineLiteral.kt")
|
||||
public void testCrossinlineLiteral() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/custom/crossinlineLiteral.kt");
|
||||
|
||||
Reference in New Issue
Block a user