[Coverage] Handle return inside nested loop

This commit is contained in:
Anastasiya Shadrina
2020-01-20 01:36:15 +07:00
committed by Sergey Bogolepov
parent d8c2d2acd9
commit 04b8bc9539
4 changed files with 32 additions and 28 deletions
@@ -20,26 +20,11 @@ import org.jetbrains.kotlin.ir.declarations.name
* Besides the obvious [file] and line/column borders, it has [RegionKind] which is described later. * Besides the obvious [file] and line/column borders, it has [RegionKind] which is described later.
*/ */
class Region( class Region(
startOffset: Int, val startOffset: Int,
endOffset: Int, val endOffset: Int,
val file: IrFile, val file: IrFile,
val kind: RegionKind val kind: RegionKind
) { ) {
var startOffset: Int = startOffset
set(value) {
if (value != UNDEFINED_OFFSET) {
field = value
}
}
var endOffset: Int = endOffset
set(value) {
if (value != UNDEFINED_OFFSET) {
field = value
}
}
val startLine: Int val startLine: Int
get() = file.fileEntry.line(startOffset) get() = file.fileEntry.line(startOffset)
@@ -165,19 +165,21 @@ private class IrFunctionRegionsCollector(
body.acceptVoid(this) body.acceptVoid(this)
} }
override fun visitReturn(expression: IrReturn) {
val next = irStatementsStack.lastOrNull()?.next ?: return
val nextRegion = recordRegion(next, expression.endOffset, currentRegion.endOffset) ?: return
currentRegion.endOffset = expression.endOffset
regionStack.pop()
regionStack.push(nextRegion)
}
override fun visitBreakContinue(jump: IrBreakContinue) { override fun visitBreakContinue(jump: IrBreakContinue) {
val (current, next) = irStatementsStack.lastOrNull() ?: return val (current, next) = irStatementsStack.lastOrNull() ?: return
recordRegion(next ?: return, current.endOffset, jump.loop.endOffset) recordRegion(next ?: return, current.endOffset, jump.loop.endOffset)
} }
override fun visitReturn(expression: IrReturn) {
irStatementsStack.subList(0, irStatementsStack.lastIndex)
.filter { (current, next) -> next != null && current.endOffset > expression.endOffset }
.forEach { (current, next) -> recordRegion(next!!, expression.endOffset, current.endOffset) }
val next = irStatementsStack.lastOrNull()?.next ?: return
val nextRegion = recordRegion(next, expression.endOffset, currentRegion.endOffset) ?: return
regionStack.pop()
regionStack.push(nextRegion)
}
private fun visitInFileContext(file: IrFile, visit: () -> Unit) { private fun visitInFileContext(file: IrFile, visit: () -> Unit) {
irFileStack.push(file) irFileStack.push(file)
visit() visit()
@@ -199,7 +201,8 @@ private class IrFunctionRegionsCollector(
if (!current.hasValidOffsets()) { if (!current.hasValidOffsets()) {
continue continue
} }
val next = if (i < statements.lastIndex && statements[i + 1].hasValidOffsets()) statements[i + 1] else null val nextInContext = irStatementsStack.lastOrNull()?.next
val next = if (i < statements.lastIndex && statements[i + 1].hasValidOffsets()) statements[i + 1] else nextInContext
irStatementsStack.push(StatementContext(current, next)) irStatementsStack.push(StatementContext(current, next))
visit(current) visit(current)
irStatementsStack.pop() irStatementsStack.pop()
+2 -2
View File
@@ -4021,8 +4021,8 @@ if (UtilsKt.getTestTargetSupportsCodeCoverage(project)) {
task coverage_jumps(type: CoverageTest) { task coverage_jumps(type: CoverageTest) {
binaryName = "CoverageJumps" binaryName = "CoverageJumps"
numberOfCoveredFunctions = 7 numberOfCoveredFunctions = 8
numberOfCoveredLines = 66 numberOfCoveredLines = 74
konanArtifacts { konanArtifacts {
program(binaryName, targets: [ target ]) { program(binaryName, targets: [ target ]) {
@@ -55,6 +55,21 @@ fun singleReturn() {
return return
} }
fun nestedReturn() {
while (true) {
while (true) {
while (true) {
if (1 < 2) {
return
}
println()
}
println()
}
}
println()
}
fun main() { fun main() {
simpleReturn(0) simpleReturn(0)
simpleReturn(1) simpleReturn(1)
@@ -71,4 +86,5 @@ fun main() {
breakFromWhile() breakFromWhile()
continueFromDoWhile() continueFromDoWhile()
singleReturn() singleReturn()
nestedReturn()
} }