[Coverage] Record methods regions correctly
This commit is contained in:
committed by
Sergey Bogolepov
parent
bd0396c71e
commit
9a980920d1
+21
-2
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
Reference in New Issue
Block a user