[Coverage] Record methods regions correctly

This commit is contained in:
Anastasiya Shadrina
2019-11-26 22:38:19 +07:00
committed by Sergey Bogolepov
parent bd0396c71e
commit 9a980920d1
3 changed files with 90 additions and 8 deletions
@@ -11,8 +11,10 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.util.nameForIrSerialization
import org.jetbrains.kotlin.ir.util.statements
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
/**
* Collect all regions in the module.
@@ -40,7 +42,7 @@ internal class CoverageRegionCollector(private val fileFilter: (IrFile) -> Boole
override fun visitFunction(declaration: IrFunction) {
if (!declaration.isInline && !declaration.isExternal && !declaration.isGeneratedByCompiler) {
val regionsCollector = IrFunctionRegionsCollector(fileFilter, file)
regionsCollector.visitFunction(declaration)
declaration.acceptVoid(regionsCollector)
if (regionsCollector.regions.isNotEmpty()) {
functionRegions += FunctionRegions(declaration, regionsCollector.regions)
}
@@ -80,13 +82,30 @@ private class IrFunctionRegionsCollector(
element.acceptChildrenVoid(this)
}
override fun visitFunction(declaration: IrFunction) {
override fun visitSimpleFunction(declaration: IrSimpleFunction) {
declaration.body?.let {
recordRegion(it)
it.acceptChildrenVoid(this)
}
}
override fun visitConstructor(declaration: IrConstructor) {
val statements = declaration.body?.statements ?: return
statements.forEach {
if (it is IrDelegatingConstructorCall && !declaration.isPrimary
|| it !is IrDelegatingConstructorCall && it !is IrReturn) {
recordRegion(it)
it.acceptVoid(this)
}
}
}
// TODO: The following implementation produces correct region mapping, but something goes wrong later
// override fun visitFieldAccess(expression: IrFieldAccessExpression) {
// expression.receiver?.let { recordRegion(it) }
// expression.acceptChildrenVoid(this)
// }
override fun visitWhen(expression: IrWhen) {
val branches = expression.branches
branches.forEach {
+21 -6
View File
@@ -3936,6 +3936,21 @@ if (UtilsKt.testTargetSupportsCodeCoverage(project)) {
}
}
task coverage_controlflow(type: CoverageTest) {
binaryName = "CoverageControlFlow"
numberOfCoveredFunctions = 1
numberOfCoveredLines = 102
konanArtifacts {
program(binaryName, targets: [ target ]) {
srcDir 'coverage/basic/controlflow'
baseDir "$testOutputCoverage/$binaryName"
entryPoint "coverage.basic.controlflow.main"
extraOpts "-Xcoverage", "-Xcoverage-file=$profrawFile"
}
}
}
task coverage_smoke0(type: CoverageTest) {
binaryName = "CoverageSmoke0"
numberOfCoveredFunctions = 2
@@ -3951,16 +3966,16 @@ if (UtilsKt.testTargetSupportsCodeCoverage(project)) {
}
}
task coverage_controlflow(type: CoverageTest) {
binaryName = "CoverageControlFlow"
numberOfCoveredFunctions = 1
numberOfCoveredLines = 102
task coverage_smoke1(type: CoverageTest) {
binaryName = "CoverageSmoke1"
numberOfCoveredFunctions = 9
numberOfCoveredLines = 33
konanArtifacts {
program(binaryName, targets: [ target ]) {
srcDir 'coverage/basic/controlflow'
srcDir 'coverage/basic/smoke1'
baseDir "$testOutputCoverage/$binaryName"
entryPoint "coverage.basic.controlflow.main"
entryPoint "coverage.basic.smoke1.main"
extraOpts "-Xcoverage", "-Xcoverage-file=$profrawFile"
}
}
@@ -0,0 +1,48 @@
package coverage.basic.smoke1
class A(val prop: Int) {
constructor() : this(1)
fun action1() {
println(prop)
}
fun action2() {
}
}
class B private constructor(val prop: String) {
init {
println("init block")
}
constructor(prop1: String, prop2: String) : this("$prop1, $prop2")
constructor() : this("dummy") {
if (1 > 2) {
println("uncovered")
} else {
println("foo")
}
println("bar")
}
override fun toString() = prop
}
fun main(args: Array<String>) {
val a1 = A(2)
a1.action1()
a1.action2()
val a2 = A()
a2.action1()
a2.action1()
val b1 = B("Hello", "world")
val b2 = B()
println(b1)
println(b2)
}