@@ -265,17 +265,12 @@ private fun findCallsOnPosition(sourcePosition: SourcePosition, filter: (KtCallE
265
265
}
266
266
}
267
267
268
-
269
268
sealed class Action (val position : XSourcePositionImpl ? = null ,
270
- val lineNumber : Int? = null ,
271
- val stepOverLines : Set <Int >? = null ,
272
- val inlineRangeVariables : List <LocalVariable >? = null ,
273
- val isDexDebug : Boolean = false ) {
269
+ val stepOverInlineData : StepOverFilterData ? = null ) {
274
270
class STEP_OVER : Action ()
275
271
class STEP_OUT : Action ()
276
272
class RUN_TO_CURSOR (position : XSourcePositionImpl ) : Action(position)
277
- class STEP_OVER_INLINED (lineNumber : Int , stepOverLines : Set <Int >, inlineVariables : List <LocalVariable >, isDexDebug : Boolean ) : Action(
278
- lineNumber = lineNumber, stepOverLines = stepOverLines, inlineRangeVariables = inlineVariables, isDexDebug = isDexDebug)
273
+ class STEP_OVER_INLINED (stepOverInlineData : StepOverFilterData ) : Action(stepOverInlineData = stepOverInlineData)
279
274
280
275
fun apply (debugProcess : DebugProcessImpl ,
281
276
suspendContext : SuspendContextImpl ,
@@ -289,12 +284,7 @@ sealed class Action(val position: XSourcePositionImpl? = null,
289
284
is Action .STEP_OUT -> debugProcess.createStepOutCommand(suspendContext).contextAction(suspendContext)
290
285
is Action .STEP_OVER -> debugProcess.createStepOverCommand(suspendContext, ignoreBreakpoints).contextAction(suspendContext)
291
286
is Action .STEP_OVER_INLINED -> KotlinStepActionFactory (debugProcess).createKotlinStepOverInlineAction(
292
- KotlinStepOverInlineFilter (
293
- isDexDebug,
294
- debugProcess.project,
295
- stepOverLines!! ,
296
- lineNumber ? : - 1 ,
297
- inlineRangeVariables!! )).contextAction(suspendContext)
287
+ KotlinStepOverInlineFilter (debugProcess.project, stepOverInlineData!! )).contextAction(suspendContext)
298
288
}
299
289
}
300
290
}
@@ -336,7 +326,7 @@ fun getStepOverAction(
336
326
return false
337
327
}
338
328
339
- if (nextLocation.ktLineNumber () !in range) {
329
+ if (nextLocation.lineNumber () !in range) {
340
330
return false
341
331
}
342
332
@@ -348,8 +338,10 @@ fun getStepOverAction(
348
338
}
349
339
}
350
340
341
+ val methodLocations = location.method().allLineLocations()
342
+
351
343
fun isBackEdgeLocation (): Boolean {
352
- val previousSuitableLocation = computedReferenceType.allLineLocations() .reversed()
344
+ val previousSuitableLocation = methodLocations .reversed()
353
345
.dropWhile { it != location }
354
346
.drop(1 )
355
347
.filter(::isLocationSuitable)
@@ -361,7 +353,7 @@ fun getStepOverAction(
361
353
362
354
val patchedLocation = if (isBackEdgeLocation()) {
363
355
// Pretend we had already did a backing step
364
- computedReferenceType.allLineLocations()
356
+ methodLocations
365
357
.filter(::isLocationSuitable)
366
358
.first { it.ktLineNumber() == location.ktLineNumber() }
367
359
}
@@ -388,7 +380,7 @@ fun getStepOverAction(
388
380
//
389
381
// It also thinks that too many lines are inlined when there's a call of function argument or other
390
382
// inline function in last statement of inline function. The list of inlineRangeVariables is used to overcome it.
391
- val probablyInlinedLocations = computedReferenceType.allLineLocations()
383
+ val probablyInlinedLocations = methodLocations
392
384
.dropWhile { it != patchedLocation }
393
385
.drop(1 )
394
386
.dropWhile { it.ktLineNumber() == patchedLineNumber }
@@ -398,12 +390,25 @@ fun getStepOverAction(
398
390
.dropWhile { it.ktLineNumber() == patchedLineNumber }
399
391
400
392
if (! probablyInlinedLocations.isEmpty()) {
401
- return Action .STEP_OVER_INLINED (
393
+ // Some Kotlin inlined methods with 'for' (and maybe others) generates bytecode that after dexing have a strange artifact.
394
+ // GOTO instructions are moved to the end of method and as they don't have proper line, line is obtained from the previous
395
+ // instruction. It might be method return or previous GOTO from the inlining. Simple stepping over such function is really
396
+ // terrible. On each iteration position jumps to the method end or some previous inline call and then returns back. To prevent
397
+ // this filter locations with too big code indexes manually
398
+ val returnCodeIndex: Long = if (isDexDebug) {
399
+ // TODO: won't work for situation when breakpoint is in inlined method
400
+ val locationsOfLine = location.method().locationsOfLine(range.last)
401
+ locationsOfLine.map { it.codeIndex() }.max() ? : - 1L
402
+ }
403
+ else - 1L
404
+
405
+ return Action .STEP_OVER_INLINED (StepOverFilterData (
402
406
patchedLineNumber,
403
407
probablyInlinedLocations.map { it.ktLineNumber() }.toSet(),
404
408
inlineRangeVariables,
405
- isDexDebug
406
- )
409
+ isDexDebug,
410
+ returnCodeIndex
411
+ ))
407
412
}
408
413
409
414
return Action .STEP_OVER ()
0 commit comments