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:
Yan Zhulanow
2020-02-06 21:14:48 +09:00
parent 4244f05307
commit bf890a1540
15 changed files with 49 additions and 44 deletions
@@ -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")
}
}
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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