diff --git a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index 8d9cb03f124..6640e660ee5 100644 --- a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -744,13 +744,13 @@ fun main(args: Array) { } testClass() { - model("debugger/tinyApp/src/stepping/stepIntoAndSmartStepInto", testMethod = "doStepIntoTest", testClassName = "StepInto") - 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") + model("debugger/tinyApp/src/stepping/stepIntoAndSmartStepInto", pattern = KT_WITHOUT_DOTS_IN_NAME, testMethod = "doStepIntoTest", testClassName = "StepInto") + model("debugger/tinyApp/src/stepping/stepIntoAndSmartStepInto", pattern = KT_WITHOUT_DOTS_IN_NAME, testMethod = "doSmartStepIntoTest", testClassName = "SmartStepInto") + model("debugger/tinyApp/src/stepping/stepInto", pattern = KT_WITHOUT_DOTS_IN_NAME, testMethod = "doStepIntoTest", testClassName = "StepIntoOnly") + model("debugger/tinyApp/src/stepping/stepOut", pattern = KT_WITHOUT_DOTS_IN_NAME, testMethod = "doStepOutTest") + model("debugger/tinyApp/src/stepping/stepOver", pattern = KT_WITHOUT_DOTS_IN_NAME, testMethod = "doStepOverTest") + model("debugger/tinyApp/src/stepping/filters", pattern = KT_WITHOUT_DOTS_IN_NAME, testMethod = "doStepIntoTest") + model("debugger/tinyApp/src/stepping/custom", pattern = KT_WITHOUT_DOTS_IN_NAME, testMethod = "doCustomTest") } testClass() { diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/DebuggerUtils.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/DebuggerUtils.kt index b4f604a881c..1e6f38348f4 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/DebuggerUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/DebuggerUtils.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil.findFilesWithExactPackage import org.jetbrains.kotlin.idea.stubindex.StaticFacadeIndexUtil +import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.CompositeBindingContext @@ -46,11 +47,13 @@ object DebuggerUtils { scope: GlobalSearchScope, className: JvmClassName, fileName: String): KtFile? { - return findSourceFileForClass( - project, - listOf(scope, KotlinSourceFilterScope.librarySources(GlobalSearchScope.allScope(project), project)), - className, - fileName) + return runReadAction { + findSourceFileForClass( + project, + listOf(scope, KotlinSourceFilterScope.librarySources(GlobalSearchScope.allScope(project), project)), + className, + fileName) + } } fun findSourceFileForClass( diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/KotlinPositionManager.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/KotlinPositionManager.kt index 3331c39d735..efd6de8ed5e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/KotlinPositionManager.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/KotlinPositionManager.kt @@ -256,12 +256,24 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq throw NoDataException.INSTANCE } try { + if (myDebugProcess.isDexDebug()) { + val inlineLocations = noStrataLocationsOfLineForInlineFunctions(type, position, myDebugProcess.searchScope) + if (!inlineLocations.isEmpty()) { + return inlineLocations + } + } + val line = position.line + 1 + val locations = if (myDebugProcess.virtualMachineProxy.versionHigher("1.4")) type.locationsOfLine(KOTLIN_STRATA_NAME, null, line).filter { it.sourceName(KOTLIN_STRATA_NAME) == position.file.name } else type.locationsOfLine(line) - if (locations == null || locations.isEmpty()) throw NoDataException.INSTANCE + + if (locations == null || locations.isEmpty()) { + throw NoDataException.INSTANCE + } + return locations } catch (e: AbsentInformationException) { diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/NoStrataPositionManagerHelper.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/NoStrataPositionManagerHelper.kt new file mode 100644 index 00000000000..3074e212d73 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/NoStrataPositionManagerHelper.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2016 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 + +import com.intellij.debugger.SourcePosition +import com.intellij.psi.search.GlobalSearchScope +import com.sun.jdi.Location +import com.sun.jdi.ReferenceType +import org.jetbrains.kotlin.idea.refactoring.getLineStartOffset +import org.jetbrains.kotlin.idea.util.application.runReadAction +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.KtFunction +import org.jetbrains.kotlin.psi.psiUtil.parents + +fun noStrataLocationsOfLineForInlineFunctions(type: ReferenceType, position: SourcePosition, sourceSearchScope: GlobalSearchScope): List { + val line = position.line + val file = position.file + val project = position.file.project + + val lineStartOffset = file.getLineStartOffset(line) ?: return listOf() + val element = file.findElementAt(lineStartOffset) ?: return listOf() + + val isInInline = runReadAction { element.parents.any { it is KtFunction && it.hasModifier(KtTokens.INLINE_KEYWORD) } } + if (!isInInline) return listOf() + + val lines = inlinedLinesNumbers(line + 1, position.file.name, FqName(type.name()), type.sourceName(), project, sourceSearchScope) + val inlineLocations = lines.flatMap { type.locationsOfLine(it) } + + return inlineLocations +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/smapUtil.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/smapUtil.kt index 14ee0b6171d..c2f4c116d5e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/smapUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/smapUtil.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.idea.debugger +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.compiler.CompilerPaths import com.intellij.openapi.project.Project import com.intellij.openapi.roots.ProjectFileIndex @@ -53,6 +54,27 @@ fun inlineLineAndFileByPosition(lineNumber: Int, fqName: FqName, fileName: Strin return mapStacktraceLineToSource(smapData, lineNumber, project, SourceLineKind.EXECUTED_LINE, searchScope) } +internal fun inlinedLinesNumbers( + inlineLineNumber: Int, inlineFileName: String, + destinationTypeFqName: FqName, destinationFileName: String, + project: Project, sourceSearchScope: GlobalSearchScope): List { + val internalName = destinationTypeFqName.asString().replace('.', '/') + val jvmClassName = JvmClassName.byInternalName(internalName) + + val file = DebuggerUtils.findSourceFileForClassIncludeLibrarySources(project, sourceSearchScope, jvmClassName, destinationFileName) ?: + return listOf() + + val virtualFile = file.virtualFile ?: return listOf() + + val bytes = readClassFile(project, jvmClassName, virtualFile) ?: return listOf() + val smapData = readDebugInfo(bytes) ?: return listOf() + + val smap = smapData.kotlinStrata ?: return listOf() + + val mappingToInlinedFile = smap.fileMappings.firstOrNull() { it.name == inlineFileName } ?: return listOf() + return mappingToInlinedFile.lineMappings.map { it.mapSourceToDest(inlineLineNumber) } +} + fun isInlineFunctionLineNumber(file: VirtualFile, lineNumber: Int, project: Project): Boolean { val linesInFile = file.toPsiFile(project)?.getLineCount() ?: return false return lineNumber > linesInFile @@ -79,9 +101,9 @@ fun readClassFile(project: Project, val outputDir = CompilerPaths.getModuleOutputDirectory(module, /*forTests = */ false) ?: return null val className = fqNameWithInners.asString().replace('.', '$') - val classByByDirectory = findClassFileByPath(jvmName.packageFqName.asString(), className, outputDir) ?: return null + val classByDirectory = findClassFileByPath(jvmName.packageFqName.asString(), className, outputDir) ?: return null - return classByByDirectory.readBytes() + return classByDirectory.readBytes() } else -> return null @@ -94,6 +116,13 @@ private fun findClassFileByPath(packageName: String, className: String, outputDi val parentDirectory = File(outDirFile, packageName.replace(".", File.separator)) if (!parentDirectory.exists()) return null + if (ApplicationManager.getApplication().isUnitTestMode) { + val beforeDexFileClassFile = File(parentDirectory, className + ".class.before_dex") + if (beforeDexFileClassFile.exists()) { + return beforeDexFileClassFile + } + } + val classFile = File(parentDirectory, className + ".class") if (classFile.exists()) { return classFile diff --git a/idea/testData/debugger/tinyApp/outs/dexManyFilesWithInlineCalls1.out b/idea/testData/debugger/tinyApp/outs/dexManyFilesWithInlineCalls1.out new file mode 100644 index 00000000000..c3f14d00d66 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/dexManyFilesWithInlineCalls1.out @@ -0,0 +1,7 @@ +LineBreakpoint created at dexManyFilesWithInlineCalls1.First.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! dexManyFilesWithInlineCalls1.DexManyFilesWithInlineCalls1Kt +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +dexManyFilesWithInlineCalls1.First.kt:5 +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/dexManyFilesWithInlineCalls2.out b/idea/testData/debugger/tinyApp/outs/dexManyFilesWithInlineCalls2.out new file mode 100644 index 00000000000..547fc8d02a8 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/dexManyFilesWithInlineCalls2.out @@ -0,0 +1,7 @@ +LineBreakpoint created at dexManyFilesWithInlineCalls2.Second.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! dexManyFilesWithInlineCalls2.DexManyFilesWithInlineCalls2Kt +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +dexManyFilesWithInlineCalls2.Second.kt:5 +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/dexSeveralInlineCallsFromOtherFile.out b/idea/testData/debugger/tinyApp/outs/dexSeveralInlineCallsFromOtherFile.out new file mode 100644 index 00000000000..0e33ed23c4a --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/dexSeveralInlineCallsFromOtherFile.out @@ -0,0 +1,10 @@ +LineBreakpoint created at dexSeveralInlineCallsFromOtherFile.Other.kt:6 +LineBreakpoint created at dexSeveralInlineCallsFromOtherFile.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! dexSeveralInlineCallsFromOtherFile.DexSeveralInlineCallsFromOtherFileKt +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +dexSeveralInlineCallsFromOtherFile.kt:5 +dexSeveralInlineCallsFromOtherFile.Other.kt:6 +dexSeveralInlineCallsFromOtherFile.Other.kt:6 +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/dexStopInInlineFun.out b/idea/testData/debugger/tinyApp/outs/dexStopInInlineFun.out new file mode 100644 index 00000000000..97e95cf34e9 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/dexStopInInlineFun.out @@ -0,0 +1,8 @@ +LineBreakpoint created at dexStopInInlineFun.kt:10 +!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! dexStopInInlineFun.DexStopInInlineFunKt +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +dexStopInInlineFun.kt:10 +dexStopInInlineFun.kt:11 +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/dexStopInInlineInOtherFile.out b/idea/testData/debugger/tinyApp/outs/dexStopInInlineInOtherFile.out new file mode 100644 index 00000000000..a56a0bb9027 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/dexStopInInlineInOtherFile.out @@ -0,0 +1,8 @@ +LineBreakpoint created at dexStopInInlineInOtherFile.Other.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! dexStopInInlineInOtherFile.DexStopInInlineInOtherFileKt +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +dexStopInInlineInOtherFile.Other.kt:6 +dexStopInInlineInOtherFile.Other.kt:7 +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/src/stepping/custom/dexManyFilesWithInlineCalls1.First.kt b/idea/testData/debugger/tinyApp/src/stepping/custom/dexManyFilesWithInlineCalls1.First.kt new file mode 100644 index 00000000000..12444f5e76c --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/custom/dexManyFilesWithInlineCalls1.First.kt @@ -0,0 +1,6 @@ +package dexManyFilesWithInlineCalls1.first + +inline fun firstInline() { + // Breakpoint 1 + 1 + 1 +} diff --git a/idea/testData/debugger/tinyApp/src/stepping/custom/dexManyFilesWithInlineCalls1.Second.kt b/idea/testData/debugger/tinyApp/src/stepping/custom/dexManyFilesWithInlineCalls1.Second.kt new file mode 100644 index 00000000000..dedc5a04c16 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/custom/dexManyFilesWithInlineCalls1.Second.kt @@ -0,0 +1,5 @@ +package dexManyFilesWithInlineCalls1.second + +inline fun secondInline() { + 1 + 1 +} diff --git a/idea/testData/debugger/tinyApp/src/stepping/custom/dexManyFilesWithInlineCalls1.kt b/idea/testData/debugger/tinyApp/src/stepping/custom/dexManyFilesWithInlineCalls1.kt new file mode 100644 index 00000000000..559c91ca389 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/custom/dexManyFilesWithInlineCalls1.kt @@ -0,0 +1,14 @@ +package dexManyFilesWithInlineCalls1 + +import dexManyFilesWithInlineCalls1.first.* +import dexManyFilesWithInlineCalls1.second.* + +fun main(args: Array) { + firstInline() +} + +fun unused() { + secondInline() +} + +// ADDITIONAL_BREAKPOINT: dexManyFilesWithInlineCalls1.First.kt: Breakpoint 1 \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/stepping/custom/dexManyFilesWithInlineCalls2.First.kt b/idea/testData/debugger/tinyApp/src/stepping/custom/dexManyFilesWithInlineCalls2.First.kt new file mode 100644 index 00000000000..32d79f85935 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/custom/dexManyFilesWithInlineCalls2.First.kt @@ -0,0 +1,5 @@ +package dexManyFilesWithInlineCalls2.first + +inline fun firstInline() { + 1 + 1 +} diff --git a/idea/testData/debugger/tinyApp/src/stepping/custom/dexManyFilesWithInlineCalls2.Second.kt b/idea/testData/debugger/tinyApp/src/stepping/custom/dexManyFilesWithInlineCalls2.Second.kt new file mode 100644 index 00000000000..40c61d46159 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/custom/dexManyFilesWithInlineCalls2.Second.kt @@ -0,0 +1,6 @@ +package dexManyFilesWithInlineCalls2.second + +inline fun secondInline() { + // Breakpoint 1 + 1 + 1 +} diff --git a/idea/testData/debugger/tinyApp/src/stepping/custom/dexManyFilesWithInlineCalls2.kt b/idea/testData/debugger/tinyApp/src/stepping/custom/dexManyFilesWithInlineCalls2.kt new file mode 100644 index 00000000000..15900c480a3 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/custom/dexManyFilesWithInlineCalls2.kt @@ -0,0 +1,14 @@ +package dexManyFilesWithInlineCalls2 + +import dexManyFilesWithInlineCalls2.first.* +import dexManyFilesWithInlineCalls2.second.* + +fun main(args: Array) { + secondInline() +} + +fun unused() { + firstInline() +} + +// ADDITIONAL_BREAKPOINT: dexManyFilesWithInlineCalls2.Second.kt: Breakpoint 1 \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/stepping/custom/dexSeveralInlineCallsFromOtherFile.Other.kt b/idea/testData/debugger/tinyApp/src/stepping/custom/dexSeveralInlineCallsFromOtherFile.Other.kt new file mode 100644 index 00000000000..90905a85f41 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/custom/dexSeveralInlineCallsFromOtherFile.Other.kt @@ -0,0 +1,8 @@ +package dexSeveralInlineCallsFromOtherFile + +inline fun inlineFun() { + var i = 1 + // Breakpoint 1 + i++ + i++ +} \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/stepping/custom/dexSeveralInlineCallsFromOtherFile.kt b/idea/testData/debugger/tinyApp/src/stepping/custom/dexSeveralInlineCallsFromOtherFile.kt new file mode 100644 index 00000000000..1a8b4590ce8 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/custom/dexSeveralInlineCallsFromOtherFile.kt @@ -0,0 +1,18 @@ +package dexSeveralInlineCallsFromOtherFile + +fun main(args: Array) { + //Breakpoint! + firstCall() + secondCall() +} + +fun firstCall() { + inlineFun() +} + +fun secondCall() { + inlineFun() +} + +// RESUME: 2 +// ADDITIONAL_BREAKPOINT: dexSeveralInlineCallsFromOtherFile.Other.kt: Breakpoint 1 diff --git a/idea/testData/debugger/tinyApp/src/stepping/stepOver/dexStopInInlineFun.kt b/idea/testData/debugger/tinyApp/src/stepping/stepOver/dexStopInInlineFun.kt new file mode 100644 index 00000000000..149060e8416 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/stepOver/dexStopInInlineFun.kt @@ -0,0 +1,12 @@ +package dexStopInInlineFun + +fun main(args: Array) { + inlineFun() +} + +inline fun inlineFun() { + var i = 1 + //Breakpoint! + i++ + i++ +} \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/stepping/stepOver/dexStopInInlineInOtherFile.Other.kt b/idea/testData/debugger/tinyApp/src/stepping/stepOver/dexStopInInlineInOtherFile.Other.kt new file mode 100644 index 00000000000..a8d1a8aba17 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/stepOver/dexStopInInlineInOtherFile.Other.kt @@ -0,0 +1,8 @@ +package dexStopInInlineInOtherFile + +inline fun inlineFun() { + var i = 1 + // Breakpoint 1 + i++ + i++ +} \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/stepping/stepOver/dexStopInInlineInOtherFile.kt b/idea/testData/debugger/tinyApp/src/stepping/stepOver/dexStopInInlineInOtherFile.kt new file mode 100644 index 00000000000..59ef2f4c512 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/stepOver/dexStopInInlineInOtherFile.kt @@ -0,0 +1,7 @@ +package dexStopInInlineInOtherFile + +fun main(args: Array) { + inlineFun() +} + +// ADDITIONAL_BREAKPOINT: dexStopInInlineInOtherFile.Other.kt: Breakpoint 1 \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/AbstractKotlinSteppingTest.kt b/idea/tests/org/jetbrains/kotlin/idea/debugger/AbstractKotlinSteppingTest.kt index 1101546798b..0d8470bc8d5 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/AbstractKotlinSteppingTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/AbstractKotlinSteppingTest.kt @@ -52,7 +52,7 @@ abstract class AbstractKotlinSteppingTest : KotlinDebuggerTestBase() { val fileText = FileUtil.loadFile(File(path)) configureSettings(fileText) - + createAdditionalBreakpoints(fileText) createDebugProcess(path) val prefix = "// $command: " diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinSteppingTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinSteppingTestGenerated.java index c7229aa7355..36a09ce5272 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinSteppingTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinSteppingTestGenerated.java @@ -34,7 +34,7 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest { @RunWith(JUnit3RunnerWithInners.class) public static class StepInto extends AbstractKotlinSteppingTest { public void testAllFilesPresentInStepInto() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/stepping/stepIntoAndSmartStepInto"), Pattern.compile("^(.+)\\.kt$"), true); + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/stepping/stepIntoAndSmartStepInto"), Pattern.compile("^([^.]+)\\.kt$"), true); } @TestMetadata("classObjectFunFromClass.kt") @@ -121,7 +121,7 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest { @RunWith(JUnit3RunnerWithInners.class) public static class SmartStepInto extends AbstractKotlinSteppingTest { public void testAllFilesPresentInSmartStepInto() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/stepping/stepIntoAndSmartStepInto"), Pattern.compile("^(.+)\\.kt$"), true); + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/stepping/stepIntoAndSmartStepInto"), Pattern.compile("^([^.]+)\\.kt$"), true); } @TestMetadata("classObjectFunFromClass.kt") @@ -214,7 +214,7 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest { } public void testAllFilesPresentInStepIntoOnly() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/stepping/stepInto"), Pattern.compile("^(.+)\\.kt$"), true); + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/stepping/stepInto"), Pattern.compile("^([^.]+)\\.kt$"), true); } @TestMetadata("continueLabel.kt") @@ -313,7 +313,7 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest { @RunWith(JUnit3RunnerWithInners.class) public static class StepOut extends AbstractKotlinSteppingTest { public void testAllFilesPresentInStepOut() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/stepping/stepOut"), Pattern.compile("^(.+)\\.kt$"), true); + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/stepping/stepOut"), Pattern.compile("^([^.]+)\\.kt$"), true); } @TestMetadata("fwBackingField.kt") @@ -370,7 +370,19 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest { @RunWith(JUnit3RunnerWithInners.class) public static class StepOver extends AbstractKotlinSteppingTest { public void testAllFilesPresentInStepOver() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/stepping/stepOver"), Pattern.compile("^(.+)\\.kt$"), true); + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/stepping/stepOver"), Pattern.compile("^([^.]+)\\.kt$"), true); + } + + @TestMetadata("dexStopInInlineFun.kt") + public void testDexStopInInlineFun() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/dexStopInInlineFun.kt"); + doStepOverTest(fileName); + } + + @TestMetadata("dexStopInInlineInOtherFile.kt") + public void testDexStopInInlineInOtherFile() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/dexStopInInlineInOtherFile.kt"); + doStepOverTest(fileName); } @TestMetadata("ifCapturedVariableKt9118.kt") @@ -475,7 +487,7 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest { @RunWith(JUnit3RunnerWithInners.class) public static class Filters extends AbstractKotlinSteppingTest { public void testAllFilesPresentInFilters() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/stepping/filters"), Pattern.compile("^(.+)\\.kt$"), true); + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/stepping/filters"), Pattern.compile("^([^.]+)\\.kt$"), true); } @TestMetadata("checkNotNull.kt") @@ -556,7 +568,7 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest { @RunWith(JUnit3RunnerWithInners.class) public static class Custom extends AbstractKotlinSteppingTest { public void testAllFilesPresentInCustom() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/stepping/custom"), Pattern.compile("^(.+)\\.kt$"), true); + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/stepping/custom"), Pattern.compile("^([^.]+)\\.kt$"), true); } @TestMetadata("crossinlineLiteral.kt") @@ -565,6 +577,24 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest { doCustomTest(fileName); } + @TestMetadata("dexManyFilesWithInlineCalls1.kt") + public void testDexManyFilesWithInlineCalls1() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/custom/dexManyFilesWithInlineCalls1.kt"); + doCustomTest(fileName); + } + + @TestMetadata("dexManyFilesWithInlineCalls2.kt") + public void testDexManyFilesWithInlineCalls2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/custom/dexManyFilesWithInlineCalls2.kt"); + doCustomTest(fileName); + } + + @TestMetadata("dexSeveralInlineCallsFromOtherFile.kt") + public void testDexSeveralInlineCallsFromOtherFile() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/custom/dexSeveralInlineCallsFromOtherFile.kt"); + doCustomTest(fileName); + } + @TestMetadata("funLiteral.kt") public void testFunLiteral() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/custom/funLiteral.kt"); diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/dexLikeBytecodePatch.kt b/idea/tests/org/jetbrains/kotlin/idea/debugger/dexLikeBytecodePatch.kt index 0844b6150d5..9082dd2b526 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/dexLikeBytecodePatch.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/dexLikeBytecodePatch.kt @@ -22,16 +22,16 @@ import org.jetbrains.org.objectweb.asm.ClassWriter import org.jetbrains.org.objectweb.asm.Opcodes import java.io.File +val DEX_BEFORE_PATCH_EXTENSION = "before_dex" + fun patchDexTests(dir: File) { dir.listFiles({ file -> file.isDirectory && file.name.startsWith("dex") }).forEach { dir -> - dir.listFiles { testOutputFile -> testOutputFile.extension == "class" }.forEach { classFile -> - applyDexLikePatch(classFile) - } + dir.listFiles { testOutputFile -> testOutputFile.extension == "class" }.forEach(::applyDexLikePatch) } } private fun applyDexLikePatch(file: File) { - file.copyTo(File(file.absolutePath + ".temp")) + file.copyTo(File(file.absolutePath + ".$DEX_BEFORE_PATCH_EXTENSION")) val reader = ClassReader(file.readBytes()) val writer = ClassWriter(ClassWriter.COMPUTE_FRAMES)