Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added JaCoCo reports filtering #225

Merged
merged 1 commit into from Aug 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -9,7 +9,7 @@ internal class ReportsFilteringTests : BaseGradleScriptTest() {

@Test
fun testExclude() {
val build = diverseBuild(languages = ALL_LANGUAGES)
val build = diverseBuild(languages = ALL_LANGUAGES, engines = ALL_ENGINES)
build.addKoverRootProject {
sourcesFrom("simple")

Expand All @@ -32,7 +32,7 @@ internal class ReportsFilteringTests : BaseGradleScriptTest() {

@Test
fun testExcludeInclude() {
val build = diverseBuild(languages = ALL_LANGUAGES)
val build = diverseBuild(languages = ALL_LANGUAGES, engines = ALL_ENGINES)
build.addKoverRootProject {
sourcesFrom("simple")

Expand Down
Expand Up @@ -43,7 +43,7 @@ internal object EngineManager {
if (details.variant.vendor == CoverageEngineVendor.INTELLIJ) {
task.intellijReport(exec, projectFiles, classFilter, xmlFile, htmlDir, details.classpath)
} else {
task.jacocoReport(projectFiles, xmlFile, htmlDir, details.classpath)
task.jacocoReport(projectFiles, classFilter, xmlFile, htmlDir, details.classpath)
}
}

Expand All @@ -58,7 +58,7 @@ internal object EngineManager {
return if (details.variant.vendor == CoverageEngineVendor.INTELLIJ) {
task.intellijVerification(exec, projectFiles, classFilter, rules, details.classpath)
} else {
task.jacocoVerification(projectFiles, rules, details.classpath)
task.jacocoVerification(projectFiles, classFilter, rules, details.classpath)
}
}

Expand Down
6 changes: 6 additions & 0 deletions src/main/kotlin/kotlinx/kover/engines/commons/Reports.kt
Expand Up @@ -5,6 +5,7 @@
package kotlinx.kover.engines.commons

import kotlinx.kover.api.*
import java.io.File
import java.math.BigDecimal


Expand All @@ -26,6 +27,11 @@ internal class ReportVerificationBound(

private val regexMetacharactersSet = "<([{\\^-=$!|]})+.>".toSet()

internal fun String.wildcardsToClassFileRegex(): String {
val filenameWithWildcards = "*" + File.separatorChar + this.replace('.', File.separatorChar) + ".class"
return filenameWithWildcards.wildcardsToRegex()
}

/**
* Replaces characters `*` or `.` to `.*` and `.` regexp characters.
*/
Expand Down
32 changes: 28 additions & 4 deletions src/main/kotlin/kotlinx/kover/engines/jacoco/JacocoReports.kt
Expand Up @@ -6,8 +6,9 @@ package kotlinx.kover.engines.jacoco

import groovy.lang.*
import kotlinx.kover.api.*
import kotlinx.kover.engines.commons.ReportVerificationRule
import kotlinx.kover.engines.commons.*
import kotlinx.kover.engines.commons.ONE_HUNDRED
import kotlinx.kover.engines.commons.ReportVerificationRule
import kotlinx.kover.tasks.*
import org.gradle.api.*
import org.gradle.api.file.*
Expand All @@ -18,11 +19,12 @@ import java.util.*

internal fun Task.jacocoReport(
projectFiles: Map<String, ProjectFiles>,
filters: KoverClassFilter,
xmlFile: File?,
htmlDir: File?,
classpath: FileCollection
) {
callJacocoAntReportTask(projectFiles, classpath) {
callJacocoAntReportTask(projectFiles, filters, classpath) {
if (xmlFile != null) {
xmlFile.parentFile.mkdirs()
invokeMethod("xml", mapOf("destfile" to xmlFile))
Expand All @@ -37,10 +39,11 @@ internal fun Task.jacocoReport(

internal fun Task.jacocoVerification(
projectFiles: Map<String, ProjectFiles>,
filters: KoverClassFilter,
rules: List<ReportVerificationRule>,
classpath: FileCollection
): String? {
callJacocoAntReportTask(projectFiles, classpath) {
callJacocoAntReportTask(projectFiles, filters, classpath) {
invokeWithBody("check", mapOf("failonviolation" to "false", "violationsproperty" to "jacocoErrors")) {
rules.forEach {
val entityType = when(it.target) {
Expand Down Expand Up @@ -97,6 +100,7 @@ internal fun Task.jacocoVerification(

private fun Task.callJacocoAntReportTask(
projectFiles: Map<String, ProjectFiles>,
filters: KoverClassFilter,
classpath: FileCollection,
block: GroovyObject.() -> Unit
) {
Expand All @@ -119,6 +123,26 @@ private fun Task.callJacocoAntReportTask(
outputs += pf.value.outputs
}


val filteredOutput = if (filters.excludes.isNotEmpty() || filters.includes.isNotEmpty()) {
val excludeRegexes = filters.excludes.map { Regex(it.wildcardsToClassFileRegex()) }
val includeRegexes = filters.includes.map { Regex(it.wildcardsToClassFileRegex()) }
val trees = outputs.map {
project.fileTree(it).filter { file ->
// the `canonicalPath` is used because a `File.separatorChar` was used to construct the class-file regex
val path = file.canonicalPath
// if the inclusion rules are declared, then the file must fit at least one of them
(includeRegexes.isEmpty() || includeRegexes.any { regex -> path.matches(regex) })
// if the exclusion rules are declared, then the file should not fit any of them
&& excludeRegexes.none { regex -> path.matches(regex) }
}
}
project.files(trees)
} else {
project.files(outputs)
}


builder.invokeWithBody("jacocoReport") {
invokeWithBody("executiondata") {
project.files(binaries).addToAntBuilder(this, "resources")
Expand All @@ -128,7 +152,7 @@ private fun Task.callJacocoAntReportTask(
project.files(sources).addToAntBuilder(this, "resources")
}
invokeWithBody("classfiles") {
project.files(outputs).addToAntBuilder(this, "resources")
filteredOutput.addToAntBuilder(this, "resources")
}
}
block()
Expand Down