Fix step out from inline function literal placed at one line
#KT-10187 Fixed
This commit is contained in:
+17
-14
@@ -202,7 +202,7 @@ public class KotlinSteppingCommandProvider: JvmSteppingCommandProvider() {
|
||||
val lineStartOffset = file.getLineStartOffset(sourcePosition.line) ?: return null
|
||||
|
||||
val inlineFunctions = getInlineFunctionsIfAny(file, lineStartOffset)
|
||||
val inlinedArgument = getInlineArgumentIfAny(file, lineStartOffset)
|
||||
val inlinedArgument = getInlineArgumentIfAny(sourcePosition.elementAt)
|
||||
|
||||
if (inlineFunctions.isEmpty() && inlinedArgument == null) return null
|
||||
|
||||
@@ -334,7 +334,11 @@ fun getStepOutPosition(
|
||||
val computedReferenceType = location.declaringType() ?: return null
|
||||
|
||||
val locations = computedReferenceType.allLineLocations()
|
||||
val nextLineLocations = locations.dropWhile { it.lineNumber() != location.lineNumber() }.filter { it.method() == location.method() }
|
||||
val nextLineLocations = locations
|
||||
.dropWhile { it != location }
|
||||
.drop(1)
|
||||
.filter { it.method() == location.method() }
|
||||
.dropWhile { it.lineNumber() == location.lineNumber() }
|
||||
|
||||
if (inlineFunctions.isNotEmpty()) {
|
||||
return suspendContext.getXPositionForStepOutFromInlineFunction(nextLineLocations, inlineFunctions) ?: return null
|
||||
@@ -352,13 +356,12 @@ private fun SuspendContextImpl.getXPositionForStepOutFromInlineFunction(
|
||||
inlineFunctionsToSkip: List<KtNamedFunction>
|
||||
): XSourcePositionImpl? {
|
||||
return getNextPositionWithFilter(locations) {
|
||||
file, offset ->
|
||||
offset, elementAt ->
|
||||
if (inlineFunctionsToSkip.any { it.textRange.contains(offset) }) {
|
||||
return@getNextPositionWithFilter true
|
||||
}
|
||||
|
||||
val inlinedArgument = getInlineArgumentIfAny(file, offset)
|
||||
inlinedArgument != null && inlinedArgument.textRange.contains(offset)
|
||||
getInlineArgumentIfAny(elementAt) != null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,37 +370,37 @@ private fun SuspendContextImpl.getXPositionForStepOutFromInlinedArgument(
|
||||
inlinedArgumentToSkip: KtFunctionLiteral
|
||||
): XSourcePositionImpl? {
|
||||
return getNextPositionWithFilter(locations) {
|
||||
file, offset ->
|
||||
offset, elementAt ->
|
||||
inlinedArgumentToSkip.textRange.contains(offset)
|
||||
}
|
||||
}
|
||||
|
||||
private fun SuspendContextImpl.getNextPositionWithFilter(
|
||||
locations: List<Location>,
|
||||
skip: (KtFile, Int) -> Boolean
|
||||
skip: (Int, PsiElement) -> Boolean
|
||||
): XSourcePositionImpl? {
|
||||
for (location in locations) {
|
||||
val file = try {
|
||||
this.debugProcess.positionManager.getSourcePosition(location)?.file as? KtFile
|
||||
val sourcePosition = try {
|
||||
this.debugProcess.positionManager.getSourcePosition(location)
|
||||
}
|
||||
catch(e: NoDataException) {
|
||||
null
|
||||
} ?: continue
|
||||
|
||||
val file = sourcePosition.file as? KtFile ?: continue
|
||||
val elementAt = sourcePosition.elementAt ?: continue
|
||||
val currentLine = location.lineNumber() - 1
|
||||
val lineStartOffset = file.getLineStartOffset(currentLine) ?: continue
|
||||
if (skip(file, lineStartOffset)) continue
|
||||
if (skip(lineStartOffset, elementAt)) continue
|
||||
|
||||
val elementAt = file.findElementAt(lineStartOffset) ?: continue
|
||||
return XSourcePositionImpl.createByElement(elementAt)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun getInlineArgumentIfAny(file: KtFile, offset: Int): KtFunctionLiteral? {
|
||||
val elementAt = file.findElementAt(offset) ?: return null
|
||||
val functionLiteralExpression = elementAt.getParentOfType<KtFunctionLiteralExpression>(false) ?: return null
|
||||
private fun getInlineArgumentIfAny(elementAt: PsiElement?): KtFunctionLiteral? {
|
||||
val functionLiteralExpression = elementAt?.getParentOfType<KtFunctionLiteralExpression>(false) ?: return null
|
||||
|
||||
val context = functionLiteralExpression.analyze(BodyResolveMode.PARTIAL)
|
||||
if (!InlineUtil.isInlinedArgument(functionLiteralExpression.functionLiteral, context, false)) return null
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
LineBreakpoint created at stepOutInlinedLambdaArgumentOneLine.kt:5 lambdaOrdinal = 0
|
||||
!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! stepOutInlinedLambdaArgumentOneLine.StepOutInlinedLambdaArgumentOneLineKt
|
||||
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
stepOutInlinedLambdaArgumentOneLine.kt:5
|
||||
stepOutInlinedLambdaArgumentOneLine.kt:6
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package stepOutInlinedLambdaArgumentOneLine
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
//Breakpoint! (lambdaOrdinal = 0)
|
||||
dive(3) { x -> x + 4 }
|
||||
}
|
||||
|
||||
inline fun dive(p: Int, f:(Int) -> Int) = f(p)
|
||||
|
||||
// STEP_OUT: 2
|
||||
@@ -316,6 +316,12 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest {
|
||||
doStepOutTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("stepOutInlinedLambdaArgumentOneLine.kt")
|
||||
public void testStepOutInlinedLambdaArgumentOneLine() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOut/stepOutInlinedLambdaArgumentOneLine.kt");
|
||||
doStepOutTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("stepOutSeveralInlineArgumentDeepest.kt")
|
||||
public void testStepOutSeveralInlineArgumentDeepest() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOut/stepOutSeveralInlineArgumentDeepest.kt");
|
||||
|
||||
Reference in New Issue
Block a user