diff --git a/.idea/dictionaries/yan.xml b/.idea/dictionaries/yan.xml
index 6e6a8ec005f..2b004b50aa3 100644
--- a/.idea/dictionaries/yan.xml
+++ b/.idea/dictionaries/yan.xml
@@ -6,6 +6,7 @@
destructured
hacky
impls
+ inlined
kapt
kotlinc
mutators
diff --git a/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/stepping/DebuggerSteppingHelper.java b/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/stepping/DebuggerSteppingHelper.java
index f550fdf4372..da4645436f3 100644
--- a/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/stepping/DebuggerSteppingHelper.java
+++ b/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/stepping/DebuggerSteppingHelper.java
@@ -59,7 +59,8 @@ public class DebuggerSteppingHelper {
if (frameProxy != null) {
Location location = frameProxy.location();
- KotlinStepAction action = KotlinSteppingCommandProviderKt.getStepOverAction(location, sourcePosition, frameProxy);
+ KotlinStepAction action = KotlinSteppingCommandProviderKt
+ .getStepOverAction(location, sourcePosition, suspendContext, frameProxy);
createStepRequest(
suspendContext, getContextThread(),
diff --git a/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/stepping/KotlinSteppingCommandProvider.kt b/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/stepping/KotlinSteppingCommandProvider.kt
index 56a08113866..2ae80b56bc3 100644
--- a/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/stepping/KotlinSteppingCommandProvider.kt
+++ b/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/stepping/KotlinSteppingCommandProvider.kt
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.idea.debugger.stepping
+import com.intellij.debugger.PositionManager
import com.intellij.debugger.SourcePosition
import com.intellij.debugger.engine.DebugProcessImpl
import com.intellij.debugger.engine.MethodFilter
@@ -12,12 +13,14 @@ import com.intellij.debugger.engine.SuspendContextImpl
import com.intellij.debugger.impl.DebuggerContextImpl
import com.intellij.debugger.impl.JvmSteppingCommandProvider
import com.intellij.debugger.jdi.StackFrameProxyImpl
+import com.intellij.debugger.settings.DebuggerSettings
import com.intellij.psi.PsiElement
import com.sun.jdi.AbsentInformationException
import com.sun.jdi.LocalVariable
import com.sun.jdi.Location
import com.sun.jdi.StackFrame
import org.jetbrains.annotations.TestOnly
+import org.jetbrains.kotlin.asJava.unwrapped
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
import org.jetbrains.kotlin.idea.core.util.CodeInsightUtils
import org.jetbrains.kotlin.idea.core.util.getLineNumber
@@ -25,9 +28,12 @@ import org.jetbrains.kotlin.idea.debugger.*
import org.jetbrains.kotlin.idea.debugger.stepping.filter.KotlinSuspendCallStepOverFilter
import org.jetbrains.kotlin.idea.debugger.stepping.filter.LocationToken
import org.jetbrains.kotlin.idea.debugger.stepping.filter.StepOverCallerInfo
+import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
import org.jetbrains.kotlin.idea.util.application.runReadAction
+import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.resolve.inline.InlineUtil
import kotlin.math.max
@@ -156,12 +162,16 @@ interface KotlinMethodFilter : MethodFilter {
fun locationMatches(context: SuspendContextImpl, location: Location): Boolean
}
-fun getStepOverAction(location: Location, sourcePosition: SourcePosition, frameProxy: StackFrameProxyImpl): KotlinStepAction {
+fun getStepOverAction(
+ location: Location, sourcePosition: SourcePosition,
+ suspendContext: SuspendContextImpl, frameProxy: StackFrameProxyImpl
+): KotlinStepAction {
val stackFrame = frameProxy.safeStackFrame() ?: return KotlinStepAction.StepOver
val method = location.safeMethod() ?: return KotlinStepAction.StepOver
val token = LocationToken.from(stackFrame).takeIf { it.lineNumber > 0 } ?: return KotlinStepAction.StepOver
val inlinedFunctionArgumentRanges = sourcePosition.collectInlineFunctionArgumentRanges()
+ val positionManager = suspendContext.debugProcess.positionManager
val tokensToSkip = mutableSetOf(token)
@@ -174,6 +184,7 @@ fun getStepOverAction(location: Location, sourcePosition: SourcePosition, frameP
&& candidateToken.lineNumber != token.lineNumber
&& inlinedFunctionArgumentRanges.none { range -> range.contains(candidateKotlinLineNumber) }
&& candidateToken.inlineVariables.none { it !in token.inlineVariables }
+ && !isInlineFunctionFromLibrary(positionManager, candidate, candidateToken)
if (!isAcceptable) {
tokensToSkip += candidateToken
@@ -183,6 +194,36 @@ fun getStepOverAction(location: Location, sourcePosition: SourcePosition, frameP
return KotlinStepAction.StepOverInlined(tokensToSkip, StepOverCallerInfo.from(location))
}
+private fun isInlineFunctionFromLibrary(positionManager: PositionManager, location: Location, token: LocationToken): Boolean {
+ if (token.inlineVariables.isEmpty()) {
+ return false
+ }
+
+ val debuggerSettings = DebuggerSettings.getInstance()
+ if (!debuggerSettings.TRACING_FILTERS_ENABLED) {
+ return false
+ }
+
+ tailrec fun getDeclarationName(element: PsiElement?): FqName? {
+ val declaration = element?.getNonStrictParentOfType() ?: return null
+ declaration.getKotlinFqName()?.let { return it }
+ return getDeclarationName(declaration.parent)
+ }
+
+ val fqn = runReadAction {
+ val element = positionManager.getSourcePosition(location)?.elementAt
+ getDeclarationName(element)?.takeIf { !it.isRoot }?.asString()
+ } ?: return false
+
+ for (filter in debuggerSettings.steppingFilters) {
+ if (filter.isEnabled && filter.matches(fqn)) {
+ return true
+ }
+ }
+
+ return false
+}
+
private fun SourcePosition.collectInlineFunctionArgumentRanges(): List {
return runReadAction {
val ranges = mutableListOf()
diff --git a/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/KotlinSteppingTestGenerated.java b/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/KotlinSteppingTestGenerated.java
index 6192fb1e831..4ecb7fbefb0 100644
--- a/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/KotlinSteppingTestGenerated.java
+++ b/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/KotlinSteppingTestGenerated.java
@@ -467,6 +467,26 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest {
runTest("idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/kt24343.kt");
}
+ @TestMetadata("lambdaToInlineFold.kt")
+ public void testLambdaToInlineFold() throws Exception {
+ runTest("idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineFold.kt");
+ }
+
+ @TestMetadata("lambdaToInlineFoldFiltersDisabled.kt")
+ public void testLambdaToInlineFoldFiltersDisabled() throws Exception {
+ runTest("idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineFoldFiltersDisabled.kt");
+ }
+
+ @TestMetadata("lambdaToInlineMap.kt")
+ public void testLambdaToInlineMap() throws Exception {
+ runTest("idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineMap.kt");
+ }
+
+ @TestMetadata("lambdaToInlineMapFiltersDisabled.kt")
+ public void testLambdaToInlineMapFiltersDisabled() throws Exception {
+ runTest("idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineMapFiltersDisabled.kt");
+ }
+
@TestMetadata("noParameterExtensionLambdaArgumentCallInInline.kt")
public void testNoParameterExtensionLambdaArgumentCallInInline() throws Exception {
runTest("idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/noParameterExtensionLambdaArgumentCallInInline.kt");
diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineFold.kt b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineFold.kt
new file mode 100644
index 00000000000..2bb98f3c863
--- /dev/null
+++ b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineFold.kt
@@ -0,0 +1,11 @@
+package test
+
+fun main() {
+ val l = listOf(1, 2, 3, 4)
+ val res = l.foldRightIndexed(0) { index, elem, akk ->
+ //Breakpoint!
+ akk + index - 4
+ }
+}
+
+// STEP_OVER: 5
\ No newline at end of file
diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineFold.out b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineFold.out
new file mode 100644
index 00000000000..4f97453adc9
--- /dev/null
+++ b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineFold.out
@@ -0,0 +1,12 @@
+LineBreakpoint created at lambdaToInlineFold.kt:7
+Run Java
+Connected to the target VM
+lambdaToInlineFold.kt:7
+lambdaToInlineFold.kt:7
+lambdaToInlineFold.kt:7
+lambdaToInlineFold.kt:7
+lambdaToInlineFold.kt:5
+lambdaToInlineFold.kt:9
+Disconnected from the target VM
+
+Process finished with exit code 0
diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineFoldFiltersDisabled.kt b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineFoldFiltersDisabled.kt
new file mode 100644
index 00000000000..c3f8bb8aad0
--- /dev/null
+++ b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineFoldFiltersDisabled.kt
@@ -0,0 +1,12 @@
+package test
+
+fun main() {
+ val l = listOf(1, 2, 3, 4)
+ val res = l.foldRightIndexed(0) { index, elem, akk ->
+ //Breakpoint!
+ akk + index - 4
+ }
+}
+
+// TRACING_FILTERS_ENABLED: false
+// STEP_OVER: 5
\ No newline at end of file
diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineFoldFiltersDisabled.out b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineFoldFiltersDisabled.out
new file mode 100644
index 00000000000..ef125803fad
--- /dev/null
+++ b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineFoldFiltersDisabled.out
@@ -0,0 +1,14 @@
+LineBreakpoint created at lambdaToInlineFoldFiltersDisabled.kt:7
+Run Java
+Connected to the target VM
+lambdaToInlineFoldFiltersDisabled.kt:7
+_Collections.!EXT!
+_Collections.!EXT!
+_Collections.!EXT!
+lambdaToInlineFoldFiltersDisabled.kt:7
+_Collections.!EXT!
+resuming lambdaToInlineFoldFiltersDisabled.kt:7
+resuming lambdaToInlineFoldFiltersDisabled.kt:7
+Disconnected from the target VM
+
+Process finished with exit code 0
diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineMap.kt b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineMap.kt
new file mode 100644
index 00000000000..7a8f7f9c47f
--- /dev/null
+++ b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineMap.kt
@@ -0,0 +1,13 @@
+package test
+
+fun main() {
+ val l = listOf(1, 2, 3, 4)
+ l.map { element ->
+ //Breakpoint!
+ bar(element * 2)
+ }
+}
+
+fun bar(n: Int) = n
+
+// STEP_OVER: 5
\ No newline at end of file
diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineMap.out b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineMap.out
new file mode 100644
index 00000000000..cc1c2aed9b7
--- /dev/null
+++ b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineMap.out
@@ -0,0 +1,11 @@
+LineBreakpoint created at lambdaToInlineMap.kt:7
+Run Java
+Connected to the target VM
+lambdaToInlineMap.kt:7
+lambdaToInlineMap.kt:7
+lambdaToInlineMap.kt:7
+lambdaToInlineMap.kt:7
+lambdaToInlineMap.kt:9
+Disconnected from the target VM
+
+Process finished with exit code 0
diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineMapFiltersDisabled.kt b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineMapFiltersDisabled.kt
new file mode 100644
index 00000000000..7cdcaf1a243
--- /dev/null
+++ b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineMapFiltersDisabled.kt
@@ -0,0 +1,14 @@
+package test
+
+fun main() {
+ val l = listOf(1, 2, 3, 4)
+ l.map { element ->
+ //Breakpoint!
+ bar(element * 2)
+ }
+}
+
+fun bar(n: Int) = n
+
+// TRACING_FILTERS_ENABLED: false
+// STEP_OVER: 5
\ No newline at end of file
diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineMapFiltersDisabled.out b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineMapFiltersDisabled.out
new file mode 100644
index 00000000000..4cb660fd787
--- /dev/null
+++ b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/lambdaToInlineMapFiltersDisabled.out
@@ -0,0 +1,14 @@
+LineBreakpoint created at lambdaToInlineMapFiltersDisabled.kt:7
+Run Java
+Connected to the target VM
+lambdaToInlineMapFiltersDisabled.kt:7
+_Collections.!EXT!
+_Collections.!EXT!
+lambdaToInlineMapFiltersDisabled.kt:7
+_Collections.!EXT!
+_Collections.!EXT!
+resuming lambdaToInlineMapFiltersDisabled.kt:7
+resuming lambdaToInlineMapFiltersDisabled.kt:7
+Disconnected from the target VM
+
+Process finished with exit code 0