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 lineStartOffset = file.getLineStartOffset(sourcePosition.line) ?: return null
|
||||||
|
|
||||||
val inlineFunctions = getInlineFunctionsIfAny(file, lineStartOffset)
|
val inlineFunctions = getInlineFunctionsIfAny(file, lineStartOffset)
|
||||||
val inlinedArgument = getInlineArgumentIfAny(file, lineStartOffset)
|
val inlinedArgument = getInlineArgumentIfAny(sourcePosition.elementAt)
|
||||||
|
|
||||||
if (inlineFunctions.isEmpty() && inlinedArgument == null) return null
|
if (inlineFunctions.isEmpty() && inlinedArgument == null) return null
|
||||||
|
|
||||||
@@ -334,7 +334,11 @@ fun getStepOutPosition(
|
|||||||
val computedReferenceType = location.declaringType() ?: return null
|
val computedReferenceType = location.declaringType() ?: return null
|
||||||
|
|
||||||
val locations = computedReferenceType.allLineLocations()
|
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()) {
|
if (inlineFunctions.isNotEmpty()) {
|
||||||
return suspendContext.getXPositionForStepOutFromInlineFunction(nextLineLocations, inlineFunctions) ?: return null
|
return suspendContext.getXPositionForStepOutFromInlineFunction(nextLineLocations, inlineFunctions) ?: return null
|
||||||
@@ -352,13 +356,12 @@ private fun SuspendContextImpl.getXPositionForStepOutFromInlineFunction(
|
|||||||
inlineFunctionsToSkip: List<KtNamedFunction>
|
inlineFunctionsToSkip: List<KtNamedFunction>
|
||||||
): XSourcePositionImpl? {
|
): XSourcePositionImpl? {
|
||||||
return getNextPositionWithFilter(locations) {
|
return getNextPositionWithFilter(locations) {
|
||||||
file, offset ->
|
offset, elementAt ->
|
||||||
if (inlineFunctionsToSkip.any { it.textRange.contains(offset) }) {
|
if (inlineFunctionsToSkip.any { it.textRange.contains(offset) }) {
|
||||||
return@getNextPositionWithFilter true
|
return@getNextPositionWithFilter true
|
||||||
}
|
}
|
||||||
|
|
||||||
val inlinedArgument = getInlineArgumentIfAny(file, offset)
|
getInlineArgumentIfAny(elementAt) != null
|
||||||
inlinedArgument != null && inlinedArgument.textRange.contains(offset)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,37 +370,37 @@ private fun SuspendContextImpl.getXPositionForStepOutFromInlinedArgument(
|
|||||||
inlinedArgumentToSkip: KtFunctionLiteral
|
inlinedArgumentToSkip: KtFunctionLiteral
|
||||||
): XSourcePositionImpl? {
|
): XSourcePositionImpl? {
|
||||||
return getNextPositionWithFilter(locations) {
|
return getNextPositionWithFilter(locations) {
|
||||||
file, offset ->
|
offset, elementAt ->
|
||||||
inlinedArgumentToSkip.textRange.contains(offset)
|
inlinedArgumentToSkip.textRange.contains(offset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun SuspendContextImpl.getNextPositionWithFilter(
|
private fun SuspendContextImpl.getNextPositionWithFilter(
|
||||||
locations: List<Location>,
|
locations: List<Location>,
|
||||||
skip: (KtFile, Int) -> Boolean
|
skip: (Int, PsiElement) -> Boolean
|
||||||
): XSourcePositionImpl? {
|
): XSourcePositionImpl? {
|
||||||
for (location in locations) {
|
for (location in locations) {
|
||||||
val file = try {
|
val sourcePosition = try {
|
||||||
this.debugProcess.positionManager.getSourcePosition(location)?.file as? KtFile
|
this.debugProcess.positionManager.getSourcePosition(location)
|
||||||
}
|
}
|
||||||
catch(e: NoDataException) {
|
catch(e: NoDataException) {
|
||||||
null
|
null
|
||||||
} ?: continue
|
} ?: continue
|
||||||
|
|
||||||
|
val file = sourcePosition.file as? KtFile ?: continue
|
||||||
|
val elementAt = sourcePosition.elementAt ?: continue
|
||||||
val currentLine = location.lineNumber() - 1
|
val currentLine = location.lineNumber() - 1
|
||||||
val lineStartOffset = file.getLineStartOffset(currentLine) ?: continue
|
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 XSourcePositionImpl.createByElement(elementAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getInlineArgumentIfAny(file: KtFile, offset: Int): KtFunctionLiteral? {
|
private fun getInlineArgumentIfAny(elementAt: PsiElement?): KtFunctionLiteral? {
|
||||||
val elementAt = file.findElementAt(offset) ?: return null
|
val functionLiteralExpression = elementAt?.getParentOfType<KtFunctionLiteralExpression>(false) ?: return null
|
||||||
val functionLiteralExpression = elementAt.getParentOfType<KtFunctionLiteralExpression>(false) ?: return null
|
|
||||||
|
|
||||||
val context = functionLiteralExpression.analyze(BodyResolveMode.PARTIAL)
|
val context = functionLiteralExpression.analyze(BodyResolveMode.PARTIAL)
|
||||||
if (!InlineUtil.isInlinedArgument(functionLiteralExpression.functionLiteral, context, false)) return null
|
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);
|
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")
|
@TestMetadata("stepOutSeveralInlineArgumentDeepest.kt")
|
||||||
public void testStepOutSeveralInlineArgumentDeepest() throws Exception {
|
public void testStepOutSeveralInlineArgumentDeepest() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOut/stepOutSeveralInlineArgumentDeepest.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOut/stepOutSeveralInlineArgumentDeepest.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user