Debugger: support stepping over inline function

This commit is contained in:
Natalia Ukhorskaya
2015-08-26 21:18:17 +03:00
parent ff4d557eac
commit 73946050c1
16 changed files with 384 additions and 39 deletions
@@ -637,6 +637,7 @@ fun main(args: Array<String>) {
model("debugger/tinyApp/src/stepping/stepIntoAndSmartStepInto", testMethod = "doSmartStepIntoTest", testClassName = "SmartStepInto")
model("debugger/tinyApp/src/stepping/stepInto", testMethod = "doStepIntoTest", testClassName = "StepIntoOnly")
model("debugger/tinyApp/src/stepping/stepOut", testMethod = "doStepOutTest")
model("debugger/tinyApp/src/stepping/stepOver", testMethod = "doStepOverTest")
model("debugger/tinyApp/src/stepping/filters", testMethod = "doStepIntoTest")
model("debugger/tinyApp/src/stepping/custom", testMethod = "doCustomTest")
}
+4 -1
View File
@@ -447,8 +447,11 @@
<debugger.extraSteppingFilter implementation="org.jetbrains.kotlin.idea.ExtraSteppingFilter"/>
<xdebugger.settings implementation="org.jetbrains.kotlin.idea.debugger.KotlinDebuggerSettings"/>
<xdebugger.breakpointType implementation="org.jetbrains.kotlin.idea.debugger.breakpoints.KotlinFieldBreakpointType"/>
<xdebugger.breakpointType implementation="org.jetbrains.kotlin.idea.debugger.breakpoints.KotlinLineBreakpointType" order="first"/>
<debugger.syntheticProvider implementation="org.jetbrains.kotlin.idea.debugger.filter.KotlinSyntheticTypeComponentProvider"/>
<debugger.javaBreakpointHandlerFactory implementation="org.jetbrains.kotlin.idea.debugger.breakpoints.KotlinBreakpointHandlerFactory"/>
<debugger.javaBreakpointHandlerFactory implementation="org.jetbrains.kotlin.idea.debugger.breakpoints.KotlinFieldBreakpointHandlerFactory"/>
<debugger.javaBreakpointHandlerFactory implementation="org.jetbrains.kotlin.idea.debugger.breakpoints.KotlinLineBreakpointHandlerFactory"/>
<debugger.jvmSteppingCommandProvider implementation="org.jetbrains.kotlin.idea.debugger.stepping.KotlinSteppingCommandProvider"/>
<codeInsight.implementMethod language="jet" implementationClass="org.jetbrains.kotlin.idea.core.overrideImplement.ImplementMembersHandler"/>
<codeInsight.overrideMethod language="jet" implementationClass="org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMembersHandler"/>
@@ -21,10 +21,17 @@ import com.intellij.debugger.engine.JavaBreakpointHandler
import com.intellij.debugger.engine.JavaBreakpointHandlerFactory
import com.intellij.debugger.ui.breakpoints.JavaLineBreakpointType
public class KotlinBreakpointHandlerFactory: JavaBreakpointHandlerFactory {
public class KotlinFieldBreakpointHandlerFactory : JavaBreakpointHandlerFactory {
override fun createHandler(process: DebugProcessImpl): JavaBreakpointHandler? {
return KotlinFieldBreakpointHandler(process)
}
}
public class KotlinFieldBreakpointHandler(process: DebugProcessImpl) : JavaBreakpointHandler(javaClass<KotlinFieldBreakpointType>(), process)
public class KotlinLineBreakpointHandlerFactory: JavaBreakpointHandlerFactory {
override fun createHandler(process: DebugProcessImpl): JavaBreakpointHandler? {
return KotlinLineBreakpointHandler(process)
}
}
public class KotlinFieldBreakpointHandler(process: DebugProcessImpl) : JavaBreakpointHandler(javaClass<KotlinFieldBreakpointType>(), process)
public class KotlinLineBreakpointHandler(process: DebugProcessImpl) : JavaBreakpointHandler(javaClass<KotlinLineBreakpointType>(), process)
@@ -0,0 +1,73 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.debugger.breakpoints;
import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.SourcePosition;
import com.intellij.debugger.ui.breakpoints.JavaLineBreakpointType;
import com.intellij.debugger.ui.breakpoints.LineBreakpoint;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.psi.JetFunction;
public class KotlinLineBreakpointType extends JavaLineBreakpointType {
public KotlinLineBreakpointType() {
super("kotlin-line", "Kotlin Line Breakpoints");
}
@Override
public boolean matchesPosition(@NotNull LineBreakpoint<?> breakpoint, @NotNull SourcePosition position) {
if (super.matchesPosition(breakpoint, position)) return true;
PsiElement containingMethod = getContainingMethod(breakpoint);
if (containingMethod == null) return false;
return inTheMethod(position, containingMethod);
}
@Override
@Nullable
public PsiElement getContainingMethod(@NotNull LineBreakpoint<?> breakpoint) {
SourcePosition position = breakpoint.getSourcePosition();
if (position == null) return null;
return getContainingMethod(position.getElementAt());
}
@Nullable
public static PsiElement getContainingMethod(@Nullable PsiElement elem) {
//noinspection unchecked
return PsiTreeUtil.getParentOfType(elem, JetFunction.class);
}
public static boolean inTheMethod(@NotNull SourcePosition pos, @NotNull PsiElement method) {
PsiElement elem = pos.getElementAt();
if (elem == null) return false;
return Comparing.equal(getContainingMethod(elem), method);
}
@Override
public boolean canPutAt(@NotNull VirtualFile file, int line, @NotNull Project project) {
return BreakpointsPackage.canPutAt(file, line, project, getClass());
}
}
@@ -16,34 +16,30 @@
package org.jetbrains.kotlin.idea.debugger.breakpoints
import com.intellij.debugger.ui.breakpoints.JavaLineBreakpointType
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiComment
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiManager
import com.intellij.psi.PsiWhiteSpace
import com.intellij.psi.*
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.xdebugger.XDebuggerUtil
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.idea.JetFileType
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.psi.JetElement
import org.jetbrains.kotlin.psi.JetParameter
import org.jetbrains.kotlin.psi.JetProperty
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
fun canPutAt(file: VirtualFile, line: Int, project: Project, breakpointTypeClass: Class<*>): Boolean {
val psiFile = PsiManager.getInstance(project).findFile(file)
if (psiFile == null || psiFile.getVirtualFile().getFileType() != JetFileType.INSTANCE) {
if (psiFile == null || psiFile.virtualFile.fileType != JetFileType.INSTANCE) {
return false
}
val document = FileDocumentManager.getInstance().getDocument(file) ?: return false
var canPutAt = false
var result: Class<*>? = null
XDebuggerUtil.getInstance().iterateLine(project, document, line, fun (el: PsiElement): Boolean {
// avoid comments
if (el is PsiWhiteSpace || PsiTreeUtil.getParentOfType(el, javaClass<PsiComment>(), false) != null) {
@@ -51,13 +47,13 @@ fun canPutAt(file: VirtualFile, line: Int, project: Project, breakpointTypeClass
}
var element = el
var parent = element.getParent()
var parent = element.parent
while (parent != null) {
val offset = parent.getTextOffset()
val offset = parent.textOffset
if (offset >= 0 && document.getLineNumber(offset) != line) break
element = parent
parent = element.getParent()
parent = element.parent
}
if (element is JetProperty || element is JetParameter) {
@@ -67,15 +63,21 @@ fun canPutAt(file: VirtualFile, line: Int, project: Project, breakpointTypeClass
descriptor = bindingContext.get(BindingContext.VALUE_PARAMETER_AS_PROPERTY, descriptor)
}
if (descriptor is PropertyDescriptor) {
canPutAt = true
result = KotlinFieldBreakpointType::class.java
}
else {
result = KotlinLineBreakpointType::class.java
}
return false
}
else {
result = KotlinLineBreakpointType::class.java
}
return true
})
return canPutAt
return result == breakpointTypeClass
}
@@ -0,0 +1,120 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.debugger.stepping
import com.intellij.debugger.SourcePosition
import com.intellij.debugger.engine.ContextUtil
import com.intellij.debugger.engine.DebugProcessImpl
import com.intellij.debugger.engine.SuspendContextImpl
import com.intellij.debugger.engine.events.DebuggerCommandImpl
import com.intellij.debugger.impl.JvmSteppingCommandProvider
import com.intellij.util.concurrency.Semaphore
import com.intellij.xdebugger.impl.XSourcePositionImpl
import com.sun.jdi.ReferenceType
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
import org.jetbrains.kotlin.idea.core.refactoring.getLineCount
import org.jetbrains.kotlin.idea.core.refactoring.getLineStartOffset
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
public class KotlinSteppingCommandProvider: JvmSteppingCommandProvider() {
override fun getStepOverCommand(
suspendContext: SuspendContextImpl?,
ignoreBreakpoints: Boolean,
stepSize: Int
): DebugProcessImpl.ResumeCommand? {
if (suspendContext == null) return null
val semaphore = Semaphore()
semaphore.down()
var sourcePosition : SourcePosition? = null
var allClasses: List<ReferenceType>? = null
val worker = object : DebuggerCommandImpl() {
override fun action() {
try {
sourcePosition = runReadAction { ContextUtil.getSourcePosition(suspendContext) }
if (sourcePosition != null) {
allClasses = suspendContext.debugProcess.positionManager.getAllClasses(sourcePosition!!)
}
}
finally {
semaphore.up()
}
}
}
suspendContext.debugProcess.managerThread?.invoke(worker)
for (i in 0..25) {
if (semaphore.waitFor(20)) break
}
val computedSourcePosition = sourcePosition ?: return null
val computedReferenceType = allClasses?.firstOrNull() ?: return null
val file = computedSourcePosition.file as? JetFile ?: return null
val inlinedArguments = getInlinedArgumentsIfAny(computedSourcePosition) ?: return null
val locations = computedReferenceType.allLineLocations()
val countOfLinesInFile = file.getLineCount()
val nextLine = computedSourcePosition.line + 2 /* +1 - because of locations are counted from 1 and +1 - because we want next line */
for (lineNumber in nextLine..countOfLinesInFile) {
val location = locations.firstOrNull { it.lineNumber() == lineNumber }
if (location != null) {
val lineStartOffset = file.getLineStartOffset(lineNumber - 1) ?: continue
if (inlinedArguments.any { it.textRange.contains(lineStartOffset) }) continue
val elementAt = file.findElementAt(lineStartOffset)
val xPosition = XSourcePositionImpl.createByElement(elementAt) ?: return null
return suspendContext.debugProcess.createRunToCursorCommand(suspendContext, xPosition, ignoreBreakpoints)
}
}
return null
}
private fun getInlinedArgumentsIfAny(sourcePosition: SourcePosition): List<JetFunction>? {
val file = sourcePosition.file as? JetFile ?: return null
val lineNumber = sourcePosition.line
val elementAt = CodeInsightUtils.getTopmostElementAtOffset(
sourcePosition.elementAt,
file.getLineStartOffset(lineNumber) ?: sourcePosition.elementAt.startOffset
) ?: return null
val start = elementAt.startOffset
val end = elementAt.endOffset
return CodeInsightUtils.
findElementsOfClassInRange(file, start, end, JetFunctionLiteral::class.java, JetNamedFunction::class.java)
.filter { JetPsiUtil.getParentCallIfPresent(it as JetExpression) != null }
.filterIsInstance<JetFunction>()
.filter {
val context = it.analyze(BodyResolveMode.PARTIAL)
InlineUtil.isInlinedArgument(it, context, false)
}
}
}
@@ -82,8 +82,7 @@ import org.jetbrains.kotlin.resolve.AnalyzingUtils
import org.jetbrains.kotlin.resolve.BindingContext
import java.io.File
import java.lang.annotation.Retention
import java.util.ArrayList
import java.util.Collections
import java.util.*
import javax.swing.Icon
fun <T: Any> PsiElement.getAndRemoveCopyableUserData(key: Key<T>): T? {
@@ -280,6 +279,18 @@ public class SelectionAwareScopeHighlighter(val editor: Editor) {
}
}
fun PsiFile.getLineStartOffset(line: Int): Int? {
val doc = this.let { file -> PsiDocumentManager.getInstance(getProject()).getDocument(file) }
if (doc != null) {
val startOffset = doc.getLineStartOffset(line)
val element = findElementAt(startOffset) ?: return startOffset
return PsiTreeUtil.skipSiblingsForward(element, PsiWhiteSpace::class.java, PsiComment::class.java)?.startOffset ?: startOffset
}
return null
}
fun PsiElement.getLineCount(): Int {
val doc = getContainingFile()?.let { file -> PsiDocumentManager.getInstance(getProject()).getDocument(file) }
if (doc != null) {
@@ -0,0 +1,17 @@
LineBreakpoint created at stepOverInlinedLambda.kt:6
!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! stepOverInlinedLambda.StepOverInlinedLambdaPackage
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
stepOverInlinedLambda.kt:6
stepOverInlinedLambda.kt:7
stepOverInlinedLambda.kt:10
stepOverInlinedLambda.kt:11
stepOverInlinedLambda.kt:16
stepOverInlinedLambda.kt:17
stepOverInlinedLambda.kt:19
stepOverInlinedLambda.kt:20
stepOverInlinedLambda.kt:23
stepOverInlinedLambda.kt:29
stepOverInlinedLambda.kt:30
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
@@ -0,0 +1,11 @@
LineBreakpoint created at stepOverInlinedLambdaStdlib.kt:5
!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! stepOverInlinedLambdaStdlib.StepOverInlinedLambdaStdlibPackage
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
stepOverInlinedLambdaStdlib.kt:5
stepOverInlinedLambdaStdlib.kt:6
stepOverInlinedLambdaStdlib.kt:8
stepOverInlinedLambdaStdlib.kt:10
stepOverInlinedLambdaStdlib.kt:15
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
@@ -0,0 +1,50 @@
package stepOverInlinedLambda
fun main(args: Array<String>) {
val a = A()
//Breakpoint!
foo { test(1) }
foo {
test(2)
}
a.foo { test(3) }.foo { test(4) }
a.foo {
test(5)
}.foo {
test(6)
}
a.foo { test(7) }
.foo { test(8) }
foo({ test(9) }) { test(10) }
foo({ test(11) }) {
test(12)
}
foo({
test(13)
}, {
test(14)
})
val b = foo { test(1) }
}
inline fun foo(f: () -> Unit) {
f()
}
inline fun foo(f1: () -> Unit, f2: () -> Unit) {
f1()
f2()
}
class A {
inline fun foo(f: () -> Unit): A {
f()
return this
}
}
fun test(i: Int) = 1
// STEP_OVER: 11
@@ -0,0 +1,18 @@
package stepOverInlinedLambdaStdlib
fun main(args: Array<String>) {
//Breakpoint!
val a = listOf(1, 2, 3)
a.filter { it > 1 }
a.filter { it > 1 }.map { it * 2 }
a.filter {
it > 1
}.map {
it * 2
}
}
// TRACING_FILTERS_ENABLED: false
// STEP_OVER: 4
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.idea.debugger
import com.intellij.openapi.util.io.FileUtil
import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.test.InTextDirectivesUtils.getPrefixedInt
import java.io.File
@@ -29,6 +30,10 @@ public abstract class AbstractKotlinSteppingTest : KotlinDebuggerTestBase() {
doTest(path, "STEP_OUT")
}
protected fun doStepOverTest(path: String) {
doTest(path, "STEP_OVER")
}
protected fun doSmartStepIntoTest(path: String) {
doTest(path, "SMART_STEP_INTO")
}
@@ -51,15 +56,9 @@ public abstract class AbstractKotlinSteppingTest : KotlinDebuggerTestBase() {
createDebugProcess(path)
for (i in 1..(getPrefixedInt(fileText, "// $command: ") ?: 1)) {
doOnBreakpoint {
when(command) {
"STEP_INTO" -> stepInto(this)
"STEP_OUT" -> stepOut()
"SMART_STEP_INTO" -> smartStepInto()
}
}
}
val prefix = "// $command: "
val count = InTextDirectivesUtils.getPrefixedInt(fileText, prefix) ?: "1"
processSteppingInstruction("$prefix$count")
finish()
}
@@ -43,6 +43,7 @@ import com.intellij.xdebugger.breakpoints.XBreakpoint
import com.intellij.xdebugger.breakpoints.XBreakpointProperties
import com.intellij.xdebugger.breakpoints.XBreakpointType
import com.intellij.xdebugger.breakpoints.XLineBreakpointType
import com.sun.jdi.request.StepRequest
import org.jetbrains.kotlin.idea.debugger.breakpoints.KotlinFieldBreakpoint
import org.jetbrains.kotlin.idea.debugger.breakpoints.KotlinFieldBreakpointType
import org.jetbrains.kotlin.idea.debugger.stepping.*
@@ -138,24 +139,34 @@ abstract class KotlinDebuggerTestBase : KotlinDebuggerTestCase() {
dp.getManagerThread()!!.schedule(dp.createStepOutCommand(this))
}
protected fun SuspendContextImpl.stepOver() {
val stepOverCommand = runReadAction { KotlinSteppingCommandProvider().getStepOverCommand(this, false, StepRequest.STEP_LINE) }
?: dp.createStepOverCommand(this, false)
dp.getManagerThread()!!.schedule(stepOverCommand)
}
protected fun doStepping(path: String) {
val file = File(path)
val fileText = file.readText()
file.readLines().forEach {
val line = it.trim()
processSteppingInstruction(line)
}
}
protected fun processSteppingInstruction(line: String) {
fun repeat(indexPrefix: String, f: SuspendContextImpl.() -> Unit) {
for (i in 1..(InTextDirectivesUtils.getPrefixedInt(fileText, indexPrefix) ?: 1)) {
for (i in 1..(InTextDirectivesUtils.getPrefixedInt(line, indexPrefix) ?: 1)) {
doOnBreakpoint(f)
}
}
file.readLines().forEach {
val line = it.trim()
when {
line.startsWith("// STEP_INTO: ") -> repeat("// STEP_INTO: ") { stepInto(this) }
line.startsWith("// STEP_OUT: ") -> repeat("// STEP_OUT: ") { stepOut() }
line.startsWith("// SMART_STEP_INTO_BY_INDEX: ") -> doOnBreakpoint { smartStepInto(InTextDirectivesUtils.getPrefixedInt(it, "// SMART_STEP_INTO_BY_INDEX: ")!!) }
line.startsWith("// SMART_STEP_INTO: ") -> repeat("// SMART_STEP_INTO: ") { smartStepInto() }
line.startsWith("// RESUME: ") -> repeat("// RESUME: ") { resume(this) }
}
when {
line.startsWith("// STEP_INTO: ") -> repeat("// STEP_INTO: ") { stepInto(this) }
line.startsWith("// STEP_OUT: ") -> repeat("// STEP_OUT: ") { stepOut() }
line.startsWith("// STEP_OVER: ") -> repeat("// STEP_OVER: ") { stepOver() }
line.startsWith("// SMART_STEP_INTO_BY_INDEX: ") -> doOnBreakpoint { smartStepInto(InTextDirectivesUtils.getPrefixedInt(line, "// SMART_STEP_INTO_BY_INDEX: ")!!) }
line.startsWith("// SMART_STEP_INTO: ") -> repeat("// SMART_STEP_INTO: ") { smartStepInto() }
line.startsWith("// RESUME: ") -> repeat("// RESUME: ") { resume(this) }
}
}
@@ -216,6 +216,7 @@ public abstract class KotlinDebuggerTestCase extends DescriptorTestCase {
@SuppressWarnings("MethodMayBeStatic")
protected void createDebugProcess(@NotNull String path) throws Exception {
VfsUtil.markDirty(true, true, VfsUtil.findFileByIoFile(new File(TINY_APP), true));
File file = new File(path);
String packageName = file.getName().replace(".kt", "");
createLocalProcess(PackageClassUtils.getPackageClassFqName(new FqName(packageName)).asString());
@@ -299,6 +299,27 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest {
}
}
@TestMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class StepOver extends AbstractKotlinSteppingTest {
public void testAllFilesPresentInStepOver() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/stepping/stepOver"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("stepOverInlinedLambda.kt")
public void testStepOverInlinedLambda() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverInlinedLambda.kt");
doStepOverTest(fileName);
}
@TestMetadata("stepOverInlinedLambdaStdlib.kt")
public void testStepOverInlinedLambdaStdlib() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverInlinedLambdaStdlib.kt");
doStepOverTest(fileName);
}
}
@TestMetadata("idea/testData/debugger/tinyApp/src/stepping/filters")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)