Debugger, tests: Change ADDITIONAL_BREAKPOINT directive format
- Make it extendable and easier to parse - Allow to create additional function breakpoints
This commit is contained in:
+26
-21
@@ -87,7 +87,7 @@ internal class BreakpointCreator(
|
||||
createLineBreakpoint(breakpointManager, file, lineIndex, ordinal, condition)
|
||||
}
|
||||
comment.startsWith("//FunctionBreakpoint!") -> {
|
||||
createFunctionBreakpoint(breakpointManager, file, lineIndex)
|
||||
createFunctionBreakpoint(breakpointManager, file, lineIndex, false)
|
||||
}
|
||||
else -> throw AssertionError("Cannot create breakpoint at line ${lineIndex + 1}")
|
||||
}
|
||||
@@ -104,19 +104,23 @@ internal class BreakpointCreator(
|
||||
fun createAdditionalBreakpoints(fileContents: String) {
|
||||
val breakpoints = findLinesWithPrefixesRemoved(fileContents, "// ADDITIONAL_BREAKPOINT: ")
|
||||
for (breakpoint in breakpoints) {
|
||||
val position = breakpoint.split(".kt:")
|
||||
assert(position.size == 2) { "Couldn't parse position from test directive: directive = $breakpoint" }
|
||||
val chunks = breakpoint.split('/').map { it.trim() }
|
||||
val fileName = chunks.getOrNull(0) ?: continue
|
||||
val lineMarker = chunks.getOrNull(1) ?: continue
|
||||
val kind = chunks.getOrElse(2) { "line" }
|
||||
val ordinal = chunks.getOrNull(3)?.toInt()
|
||||
|
||||
var lineMarker = position[1]
|
||||
var ordinal: Int? = null
|
||||
val breakpointManager = XDebuggerManager.getInstance(project).breakpointManager
|
||||
|
||||
if (lineMarker.contains(":(") && lineMarker.endsWith(")")) {
|
||||
val lineMarkerAndOrdinal = lineMarker.split(":(")
|
||||
lineMarker = lineMarkerAndOrdinal[0]
|
||||
ordinal = lineMarkerAndOrdinal[1].substringBefore(")").toInt()
|
||||
when (kind) {
|
||||
"line" -> createBreakpoint(fileName, lineMarker) { psiFile, lineNumber ->
|
||||
createLineBreakpoint(breakpointManager, psiFile, lineNumber + 1, ordinal, null)
|
||||
}
|
||||
"fun" -> createBreakpoint(fileName, lineMarker) { psiFile, lineNumber ->
|
||||
createFunctionBreakpoint(breakpointManager, psiFile, lineNumber, true)
|
||||
}
|
||||
else -> error("Unknown breakpoint kind: $kind")
|
||||
}
|
||||
|
||||
createBreakpoint(position[0], lineMarker, ordinal)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,34 +137,35 @@ internal class BreakpointCreator(
|
||||
return null
|
||||
}
|
||||
|
||||
private fun createBreakpoint(fileName: String, lineMarker: String, ordinal: Int?) {
|
||||
private fun createBreakpoint(fileName: String, lineMarker: String, action: (PsiFile, Int) -> Unit) {
|
||||
val sourceFiles = runReadAction {
|
||||
FilenameIndex.getAllFilesByExt(project, "kt")
|
||||
.filter { it.name.contains(fileName) && it.contentsToByteArray().toString(Charsets.UTF_8).contains(lineMarker) }
|
||||
.filter { it.name == fileName && it.contentsToByteArray().toString(Charsets.UTF_8).contains(lineMarker) }
|
||||
}
|
||||
|
||||
assert(sourceFiles.size == 1) { "One source file should be found: name = $fileName, sourceFiles = $sourceFiles" }
|
||||
val sourceFile = sourceFiles.singleOrNull()
|
||||
?: error("Single source file should be found: name = $fileName, sourceFiles = $sourceFiles")
|
||||
|
||||
val runnable = Runnable {
|
||||
val psiSourceFile = PsiManager.getInstance(project).findFile(sourceFiles.first())!!
|
||||
val psiSourceFile = PsiManager.getInstance(project).findFile(sourceFile)
|
||||
?: error("Psi file not found for $sourceFile")
|
||||
|
||||
val breakpointManager = XDebuggerManager.getInstance(project).breakpointManager
|
||||
val document = PsiDocumentManager.getInstance(project).getDocument(psiSourceFile)!!
|
||||
|
||||
val index = psiSourceFile.text!!.indexOf(lineMarker)
|
||||
val lineNumber = document.getLineNumber(index) + 1 // lineMarker is for previous line
|
||||
|
||||
createLineBreakpoint(breakpointManager, psiSourceFile, lineNumber, ordinal, null)
|
||||
val lineNumber = document.getLineNumber(index)
|
||||
action(psiSourceFile, lineNumber)
|
||||
}
|
||||
|
||||
DebuggerInvocationUtil.invokeAndWait(project, runnable, ModalityState.defaultModalityState())
|
||||
}
|
||||
|
||||
private fun createFunctionBreakpoint(breakpointManager: XBreakpointManager, file: PsiFile, lineIndex: Int) {
|
||||
private fun createFunctionBreakpoint(breakpointManager: XBreakpointManager, file: PsiFile, lineIndex: Int, fromLibrary: Boolean) {
|
||||
val breakpointType = findBreakpointType(KotlinFunctionBreakpointType::class.java)
|
||||
val breakpoint = createBreakpointOfType(breakpointManager, breakpointType, lineIndex, file.virtualFile)
|
||||
if (breakpoint is KotlinFunctionBreakpoint) {
|
||||
logger("FunctionBreakpoint created at ${file.virtualFile.name}:${lineIndex + 1}")
|
||||
val lineNumberSuffix = if (fromLibrary) "" else ":${lineIndex + 1}"
|
||||
logger("FunctionBreakpoint created at ${file.virtualFile.name}$lineNumberSuffix")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vendored
+5
-5
@@ -55,23 +55,23 @@ class A {
|
||||
}
|
||||
}
|
||||
|
||||
// ADDITIONAL_BREAKPOINT: isInsideInlineLambdaInLibrary.kt:Breakpoint1:(1)
|
||||
// ADDITIONAL_BREAKPOINT: isInsideInlineLambdaInLibrary.kt / Breakpoint1 / line / 1
|
||||
// EXPRESSION: it + 11
|
||||
// RESULT: 12: I
|
||||
|
||||
// ADDITIONAL_BREAKPOINT: isInsideInlineLambdaInLibrary.kt:Breakpoint2:(1)
|
||||
// ADDITIONAL_BREAKPOINT: isInsideInlineLambdaInLibrary.kt / Breakpoint2 / line / 1
|
||||
// EXPRESSION: it + 12
|
||||
// RESULT: 14: I
|
||||
|
||||
// ADDITIONAL_BREAKPOINT: isInsideInlineLambdaInLibrary.kt:Breakpoint3:(1)
|
||||
// ADDITIONAL_BREAKPOINT: isInsideInlineLambdaInLibrary.kt / Breakpoint3 / line / 1
|
||||
// EXPRESSION: it + 13
|
||||
// RESULT: 16: I
|
||||
|
||||
// ADDITIONAL_BREAKPOINT: isInsideInlineLambdaInLibrary.kt:Breakpoint4:(1)
|
||||
// ADDITIONAL_BREAKPOINT: isInsideInlineLambdaInLibrary.kt / Breakpoint4 / line / 1
|
||||
// EXPRESSION: it + 14
|
||||
// RESULT: 18: I
|
||||
|
||||
// ADDITIONAL_BREAKPOINT: isInsideInlineLambdaInLibrary.kt:Breakpoint5:(1)
|
||||
// ADDITIONAL_BREAKPOINT: isInsideInlineLambdaInLibrary.kt / Breakpoint5 / line / 1
|
||||
// EXPRESSION: it + 15
|
||||
// RESULT: 20: I
|
||||
|
||||
|
||||
+5
-5
@@ -9,23 +9,23 @@ fun main(args: Array<String>) {
|
||||
customLib.simpleLibFile.foo()
|
||||
}
|
||||
|
||||
// ADDITIONAL_BREAKPOINT: 1.kt:public fun oneFunSameFileNameFun(): Int {
|
||||
// ADDITIONAL_BREAKPOINT: a1.kt / public fun oneFunSameFileNameFun(): Int {
|
||||
// EXPRESSION: 1 + 1
|
||||
// RESULT: 2: I
|
||||
|
||||
// ADDITIONAL_BREAKPOINT: 1.kt:public fun twoFunDifferentSignatureFun(): Int {
|
||||
// ADDITIONAL_BREAKPOINT: a1.kt / public fun twoFunDifferentSignatureFun(): Int {
|
||||
// EXPRESSION: 1 + 2
|
||||
// RESULT: 3: I
|
||||
|
||||
// ADDITIONAL_BREAKPOINT: 1.kt:public val foo: Int =
|
||||
// ADDITIONAL_BREAKPOINT: a1.kt / public val foo: Int =
|
||||
// EXPRESSION: 1 + 3
|
||||
// RESULT: 4: I
|
||||
|
||||
// ADDITIONAL_BREAKPOINT: 1.kt:public fun breakpointOnLocalPropertyFun(): Int {
|
||||
// ADDITIONAL_BREAKPOINT: a1.kt / public fun breakpointOnLocalPropertyFun(): Int {
|
||||
// EXPRESSION: 1 + 4
|
||||
// RESULT: 5: I
|
||||
|
||||
// ADDITIONAL_BREAKPOINT: simpleLibFile.kt:public fun foo() {
|
||||
// ADDITIONAL_BREAKPOINT: simpleLibFile.kt / public fun foo() {
|
||||
// EXPRESSION: 1 + 5
|
||||
// RESULT: 6: I
|
||||
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ fun main(args: Array<String>) {
|
||||
customLib.localFunInLibraryCustomLib.localFunInLibraryCustomLibMainFun()
|
||||
}
|
||||
|
||||
// ADDITIONAL_BREAKPOINT: localFunCustomLib.kt:localFunInLibraryCustomLibProperty
|
||||
// ADDITIONAL_BREAKPOINT: localFunCustomLib.kt / localFunInLibraryCustomLibProperty
|
||||
// EXPRESSION: localFun()
|
||||
// RESULT: 1: I
|
||||
|
||||
|
||||
Vendored
+2
-2
@@ -9,8 +9,8 @@ fun main(args: Array<String>) {
|
||||
|
||||
// RESUME: 2
|
||||
|
||||
// ADDITIONAL_BREAKPOINT: inlineFunInLibrary.kt:public inline fun inlineFun
|
||||
// ADDITIONAL_BREAKPOINT: inlineFunInLibrary.kt: Breakpoint 2
|
||||
// ADDITIONAL_BREAKPOINT: inlineFunInLibrary.kt / public inline fun inlineFun
|
||||
// ADDITIONAL_BREAKPOINT: inlineFunInLibrary.kt / Breakpoint 2
|
||||
|
||||
// FILE: customLib/inlineFunInLibrary/inlineFunInLibrary.kt
|
||||
package customLib.inlineFunInLibrary
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ fun main(args: Array<String>) {
|
||||
fileWithInternal.test()
|
||||
}
|
||||
|
||||
// ADDITIONAL_BREAKPOINT: fileWithInternal.kt:Breakpoint
|
||||
// ADDITIONAL_BREAKPOINT: fileWithInternal.kt / Breakpoint
|
||||
|
||||
// EXPRESSION: 1
|
||||
// RESULT: 1: I
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ fun main(args: Array<String>) {
|
||||
}
|
||||
}
|
||||
|
||||
// ADDITIONAL_BREAKPOINT: inlineFunctionWithBreakpoint.kt:inline fun myFun
|
||||
// ADDITIONAL_BREAKPOINT: inlineFunctionWithBreakpoint.kt / inline fun myFun
|
||||
|
||||
// FILE: inlineFunctionWithBreakpoint.kt
|
||||
package inlineFunctionWithBreakpoint
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ fun unused() {
|
||||
secondInline()
|
||||
}
|
||||
|
||||
// ADDITIONAL_BREAKPOINT: manyFilesWithInlineCalls1.First.kt: Breakpoint 1
|
||||
// ADDITIONAL_BREAKPOINT: manyFilesWithInlineCalls1.First.kt / Breakpoint 1
|
||||
|
||||
// FILE: manyFilesWithInlineCalls1.First.kt
|
||||
package manyFilesWithInlineCalls1.first
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ fun unused() {
|
||||
firstInline()
|
||||
}
|
||||
|
||||
// ADDITIONAL_BREAKPOINT: manyFilesWithInlineCalls2.Second.kt: Breakpoint 1
|
||||
// ADDITIONAL_BREAKPOINT: manyFilesWithInlineCalls2.Second.kt / Breakpoint 1
|
||||
|
||||
// FILE: manyFilesWithInlineCalls2.First.kt
|
||||
package manyFilesWithInlineCalls2.first
|
||||
|
||||
Vendored
+1
-1
@@ -16,7 +16,7 @@ fun secondCall() {
|
||||
}
|
||||
|
||||
// RESUME: 2
|
||||
// ADDITIONAL_BREAKPOINT: severalInlineCallsFromOtherFile.Other.kt: Breakpoint 1
|
||||
// ADDITIONAL_BREAKPOINT: severalInlineCallsFromOtherFile.Other.kt / Breakpoint 1
|
||||
|
||||
// FILE: severalInlineCallsFromOtherFile.Other.kt
|
||||
package severalInlineCallsFromOtherFile
|
||||
|
||||
Vendored
+1
-1
@@ -5,7 +5,7 @@ fun main(args: Array<String>) {
|
||||
customLib.functionInLibrary.simpleFun()
|
||||
}
|
||||
|
||||
// ADDITIONAL_BREAKPOINT: functionInLibrary.kt:public inline fun simpleFun()
|
||||
// ADDITIONAL_BREAKPOINT: functionInLibrary.kt / public inline fun simpleFun()
|
||||
// STEP_INTO: 5
|
||||
|
||||
// FILE: customLib/functionInLibrary/functionInLibrary.kt
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ fun main(args: Array<String>) {
|
||||
inlineInObject.other.TestInlineInObject.inlineFun()
|
||||
}
|
||||
|
||||
// ADDITIONAL_BREAKPOINT: inlineInObject.Other.kt: Breakpoint 1
|
||||
// ADDITIONAL_BREAKPOINT: inlineInObject.Other.kt / Breakpoint 1
|
||||
|
||||
// FILE: inlineInObject.Other.kt
|
||||
package inlineInObject.other
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ fun main(args: Array<String>) {
|
||||
inlineFun()
|
||||
}
|
||||
|
||||
// ADDITIONAL_BREAKPOINT: stopInInlineInOtherFile.Other.kt: Breakpoint 1
|
||||
// ADDITIONAL_BREAKPOINT: stopInInlineInOtherFile.Other.kt / Breakpoint 1
|
||||
|
||||
// FILE: stopInInlineInOtherFile.Other.kt
|
||||
package stopInInlineInOtherFile
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ fun main(args: Array<String>) {
|
||||
val i = 1
|
||||
}
|
||||
|
||||
// ADDITIONAL_BREAKPOINT: stopInInlineInOtherFileWithLambdaArgument.Other.kt: Breakpoint 1
|
||||
// ADDITIONAL_BREAKPOINT: stopInInlineInOtherFileWithLambdaArgument.Other.kt / Breakpoint 1
|
||||
|
||||
// FILE: stopInInlineInOtherFileWithLambdaArgument.Other.kt
|
||||
package stopInInlineInOtherFileWithLambdaArgument
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ fun main(args: Array<String>) {
|
||||
AA().other()
|
||||
}
|
||||
|
||||
// ADDITIONAL_BREAKPOINT: stopInWrongClass.Other.kt: Breakpoint 1
|
||||
// ADDITIONAL_BREAKPOINT: stopInWrongClass.Other.kt / Breakpoint 1
|
||||
|
||||
// FILE: stopInWrongClass.Other.kt
|
||||
package stopInWrongClass
|
||||
|
||||
Reference in New Issue
Block a user