Skip to content

Commit 756d837

Browse files
authored
Implemented the use of the full path to the project for the exclusion
Fixes #151
1 parent e1f3fbc commit 756d837

File tree

12 files changed

+108
-34
lines changed

12 files changed

+108
-34
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ kover {
332332
intellijEngineVersion.set("1.0.656") // change version of IntelliJ agent and reporter
333333
jacocoEngineVersion.set("0.8.7") // change version of JaCoCo agent and reporter
334334
generateReportOnCheck = true // false to do not execute `koverMergedReport` task before `check` task
335-
disabledProjects = setOf() // setOf("project-name") to disable coverage for project with name `project-name`
335+
disabledProjects = setOf() // setOf("project-name") or setOf(":project-name") to disable coverage for project with path `:project-name` (`:` for the root project)
336336
instrumentAndroidPackage = false // true to instrument packages `android.*` and `com.android.*`
337337
runAllTestsForProjectTask = false // true to run all tests in all projects if `koverHtmlReport`, `koverXmlReport`, `koverReport`, `koverVerify` or `check` tasks executed on some project
338338
}
@@ -349,7 +349,7 @@ kover {
349349
intellijEngineVersion.set('1.0.656') // change version of IntelliJ agent and reporter
350350
jacocoEngineVersion.set('0.8.7') // change version of JaCoCo agent and reporter
351351
generateReportOnCheck = true // false to do not execute `koverMergedReport` task before `check` task
352-
disabledProjects = [] // ["project-name"] to disable coverage for project with name `project-name`
352+
disabledProjects = [] // ["project-name"] or [":project-name"] to disable coverage for project with path `:project-name` (`:` for the root project)
353353
instrumentAndroidPackage = false // true to instrument packages `android.*` and `com.android.*`
354354
runAllTestsForProjectTask = false // true to run all tests in all projects if `koverHtmlReport`, `koverXmlReport`, `koverReport`, `koverVerify` or `check` tasks executed on some project
355355
}

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version=0.5.0
1+
version=0.5.1-SNAPSHOT
22
group=org.jetbrains.kotlinx
33

44
kotlin.code.style=official

src/functionalTest/kotlin/kotlinx/kover/test/functional/cases/MultiProjectTests.kt

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,6 @@ internal class MultiProjectTests : BaseGradleScriptTest() {
118118
@Test
119119
fun testDisableSubproject() {
120120
builder("Testing disabling one of subproject")
121-
.types(ProjectType.KOTLIN_JVM, ProjectType.KOTLIN_MULTIPLATFORM)
122-
.engines(CoverageEngine.INTELLIJ, CoverageEngine.JACOCO)
123121
.sources("multiproject-user")
124122
.subproject(subprojectName) {
125123
sources("multiproject-common")
@@ -145,4 +143,33 @@ internal class MultiProjectTests : BaseGradleScriptTest() {
145143
}
146144
}
147145
}
146+
147+
@Test
148+
fun testDisableSubprojectByPath() {
149+
builder("Testing disabling one of subproject by path")
150+
.sources("multiproject-user")
151+
.subproject(subprojectName) {
152+
sources("multiproject-common")
153+
}
154+
.configKover { disabledProjects += ":$subprojectName" }
155+
.build()
156+
.run("build", "koverReport") {
157+
checkDefaultBinaryReport()
158+
checkDefaultMergedReports()
159+
checkDefaultReports()
160+
xml(defaultMergedXmlReport()) {
161+
classCounter("org.jetbrains.UserClass").assertFullyCovered()
162+
163+
// classes from disabled project should not be included in the merged report
164+
classCounter("org.jetbrains.CommonClass").assertAbsent()
165+
classCounter("org.jetbrains.CommonInternalClass").assertAbsent()
166+
}
167+
168+
subproject(subprojectName) {
169+
checkDefaultBinaryReport(false)
170+
checkDefaultMergedReports(false)
171+
checkDefaultReports(false)
172+
}
173+
}
174+
}
148175
}

src/main/kotlin/kotlinx/kover/KoverPlugin.kt

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ class KoverPlugin : Plugin<Project> {
5555

5656
private fun Project.applyToProject(providers: BuildProviders, agents: Map<CoverageEngine, CoverageAgent>) {
5757
val projectProviders =
58-
providers.projects[name] ?: throw GradleException("Kover: Providers for project '$name' was not found")
58+
providers.projects[path]
59+
?: throw GradleException("Kover: Providers for project '$name' ('$path') was not found")
5960

6061
val xmlReportTask = createKoverProjectTask(
6162
XML_REPORT_TASK_NAME,
@@ -165,10 +166,10 @@ class KoverPlugin : Plugin<Project> {
165166

166167
task.group = VERIFICATION_GROUP
167168

168-
providers.projects.forEach { (projectName, m) ->
169-
task.binaryReportFiles.put(projectName, NestedFiles(task.project.objects, m.reports))
170-
task.srcDirs.put(projectName, NestedFiles(task.project.objects, m.sources))
171-
task.outputDirs.put(projectName, NestedFiles(task.project.objects, m.output))
169+
providers.projects.forEach { (projectPath, m) ->
170+
task.binaryReportFiles.put(projectPath, NestedFiles(task.project.objects, m.reports))
171+
task.srcDirs.put(projectPath, NestedFiles(task.project.objects, m.sources))
172+
task.outputDirs.put(projectPath, NestedFiles(task.project.objects, m.output))
172173
}
173174

174175
task.coverageEngine.set(providers.engine)
@@ -199,8 +200,8 @@ class KoverPlugin : Plugin<Project> {
199200
task.mustRunAfter(xmlReportTask)
200201
task.mustRunAfter(htmlReportTask)
201202

202-
task.xmlFiles[proj.name] = xmlReportTask.xmlReportFile
203-
task.htmlDirs[proj.name] = htmlReportTask.htmlReportDir
203+
task.xmlFiles[proj.path] = xmlReportTask.xmlReportFile
204+
task.htmlDirs[proj.path] = htmlReportTask.htmlReportDir
204205
}
205206
}
206207
}
@@ -244,6 +245,9 @@ class KoverPlugin : Plugin<Project> {
244245
extension.coverageEngine.set(CoverageEngine.INTELLIJ)
245246
extension.intellijEngineVersion.set(defaultIntellijVersion.toString())
246247
extension.jacocoEngineVersion.set(defaultJacocoVersion)
248+
249+
afterEvaluate(CollectDisabledProjectsPathsAction(extension))
250+
247251
return extension
248252
}
249253

@@ -279,7 +283,7 @@ class KoverPlugin : Plugin<Project> {
279283
}
280284
val targetErrorProvider = project.layout.buildDirectory.file("kover/errors/$name.log").map { it.asFile }
281285

282-
doFirst(BinaryReportCleanupAction(project.name, providers.koverExtension, taskExtension))
286+
doFirst(BinaryReportCleanupAction(project.path, providers.koverExtension, taskExtension))
283287
doLast(MoveIntellijErrorLogAction(sourceErrorProvider, targetErrorProvider))
284288
}
285289
}
@@ -289,7 +293,7 @@ class KoverPlugin : Plugin<Project> {
289293
For this reason, before starting the tests, it is necessary to clear the file from the results of previous runs.
290294
*/
291295
private class BinaryReportCleanupAction(
292-
private val projectName: String,
296+
private val projectPath: String,
293297
private val koverExtensionProvider: Provider<KoverExtension>,
294298
private val taskExtension: KoverTaskExtension
295299
) : Action<Task> {
@@ -302,7 +306,7 @@ private class BinaryReportCleanupAction(
302306

303307
if (!taskExtension.isDisabled
304308
&& !koverExtension.isDisabled
305-
&& !koverExtension.disabledProjects.contains(projectName)
309+
&& !koverExtension.disabledProjectsPaths.contains(projectPath)
306310
&& koverExtension.coverageEngine.get() == CoverageEngine.INTELLIJ
307311
) {
308312
// IntelliJ engine expected empty file for parallel test execution.
@@ -312,6 +316,32 @@ private class BinaryReportCleanupAction(
312316
}
313317
}
314318

319+
private class CollectDisabledProjectsPathsAction(
320+
private val koverExtension: KoverExtension,
321+
) : Action<Project> {
322+
override fun execute(project: Project) {
323+
val allProjects = project.allprojects
324+
val paths = allProjects.associate { it.name to mutableListOf<String>() }
325+
allProjects.forEach { paths.getValue(it.name) += it.path }
326+
327+
val result: MutableSet<String> = mutableSetOf()
328+
329+
koverExtension.disabledProjects.map {
330+
if (it.startsWith(':')) {
331+
result += it
332+
} else {
333+
val projectPaths = paths[it] ?: return@map
334+
if (projectPaths.size > 1) {
335+
throw GradleException("Kover configuring error: ambiguous name of the excluded project '$it': suitable projects with paths $projectPaths. Consider using fully-qualified name starting with ':'")
336+
}
337+
result += projectPaths
338+
}
339+
}
340+
341+
koverExtension.disabledProjectsPaths = result
342+
}
343+
}
344+
315345
private class MoveIntellijErrorLogAction(
316346
private val sourceFile: Provider<File>,
317347
private val targetFile: Provider<File>
@@ -333,7 +363,7 @@ private class CoverageArgumentProvider(
333363
@get:Input val excludeAndroidPackage: Provider<Boolean>
334364
) : CommandLineArgumentProvider, Named {
335365

336-
private val projectName: String = task.project.name
366+
private val projectPath: String = task.project.path
337367

338368
@Internal
339369
override fun getName(): String {
@@ -345,7 +375,7 @@ private class CoverageArgumentProvider(
345375

346376
if (taskExtension.isDisabled
347377
|| koverExtensionValue.isDisabled
348-
|| koverExtensionValue.disabledProjects.contains(projectName)
378+
|| koverExtensionValue.disabledProjectsPaths.contains(projectPath)
349379
) {
350380
return mutableListOf()
351381
}

src/main/kotlin/kotlinx/kover/Providers.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ internal fun Project.createProviders(agents: Map<CoverageEngine, CoverageAgent>)
1515
val projects: MutableMap<String, ProjectProviders> = mutableMapOf()
1616

1717
allprojects {
18-
projects[it.name] = ProjectProviders(
18+
projects[it.path] = ProjectProviders(
1919
it.provider { it.files(if (runAllTests()) allBinaryReports() else it.binaryReports(this)) },
2020
it.provider { if (runAllTests()) allTestTasks() else it.testTasks(this) },
2121
it.provider { it.collectDirs(this).first },
@@ -108,7 +108,7 @@ private fun Project.collectDirs(root: Project): Pair<FileCollection, FileCollect
108108

109109
private fun Project.isDisabled(root: Project): Boolean {
110110
val koverExtension = root.extensions.getByType(KoverExtension::class.java)
111-
return koverExtension.isDisabled || koverExtension.disabledProjects.contains(name)
111+
return koverExtension.isDisabled || koverExtension.disabledProjectsPaths.contains(path)
112112
}
113113

114114
private fun Project.runAllTests(): Boolean {

src/main/kotlin/kotlinx/kover/api/KoverExtension.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@ open class KoverExtension(objects: ObjectFactory) {
5858
*/
5959
@get:Input
6060
public var runAllTestsForProjectTask: Boolean = false
61+
62+
/**
63+
* Fully-qualified path of disabled projects.
64+
* It is filled in only automatically based on custom values in `disabledProjects'.
65+
*/
66+
@get:Internal
67+
internal var disabledProjectsPaths: Set<String> = emptySet()
6168
}
6269

6370
public enum class CoverageEngine {

src/main/kotlin/kotlinx/kover/engines/commons/Reports.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,5 @@ internal fun String.wildcardsToRegex(): String {
3030

3131
return builder.toString()
3232
}
33+
34+
internal val ONE_HUNDRED = 100.toBigDecimal()

src/main/kotlin/kotlinx/kover/engines/intellij/IntellijReports.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,9 @@ private fun Task.checkRule(counters: Map<VerificationValueType, Int>, rule: Veri
189189

190190
val ruleName = if (rule.name != null) "'${rule.name}' " else ""
191191
return if (boundsViolations.size > 1) {
192-
"Rule ${ruleName}violated for '${project.name}':" + boundsViolations.joinToString("\n ", "\n ")
192+
"Rule ${ruleName}violated for '${project.path}':" + boundsViolations.joinToString("\n ", "\n ")
193193
} else if (boundsViolations.size == 1) {
194-
"Rule ${ruleName}violated for '${project.name}': ${boundsViolations[0]}"
194+
"Rule ${ruleName}violated for '${project.path}': ${boundsViolations[0]}"
195195
} else {
196196
null
197197
}

src/main/kotlin/kotlinx/kover/engines/jacoco/JacocoReports.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ package kotlinx.kover.engines.jacoco
66

77
import groovy.lang.*
88
import kotlinx.kover.api.*
9+
import kotlinx.kover.engines.commons.*
10+
import kotlinx.kover.engines.commons.ONE_HUNDRED
911
import kotlinx.kover.engines.commons.Report
1012
import org.gradle.api.*
1113
import org.gradle.api.file.*
@@ -40,7 +42,7 @@ private fun Task.callJacocoAntReportTask(
4042
invokeWithBody("executiondata") {
4143
project.files(report.files).addToAntBuilder(this, "resources")
4244
}
43-
invokeWithBody("structure", mapOf("name" to project.name)) {
45+
invokeWithBody("structure", mapOf("name" to project.path)) {
4446
invokeWithBody("sourcefiles") {
4547
project.files(sources).addToAntBuilder(this, "resources")
4648
}
@@ -93,8 +95,8 @@ internal fun Task.jacocoVerification(
9395
}
9496
VerificationValueType.COVERED_LINES_PERCENTAGE -> {
9597
limitArgs["value"] = "COVEREDRATIO"
96-
min = min?.divide(BigDecimal(100))
97-
max = max?.divide(BigDecimal(100))
98+
min = min?.divide(ONE_HUNDRED)
99+
max = max?.divide(ONE_HUNDRED)
98100
}
99101
}
100102

src/main/kotlin/kotlinx/kover/tasks/KoverCollectingTask.kt

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,26 @@ open class KoverCollectingTask : DefaultTask() {
2424
it.into(outputDir)
2525
xmlFiles.forEach { (p, f) ->
2626
it.from(f) { c ->
27-
c.rename { "$p.xml" }
27+
c.rename { "${p.pathAsFilename()}.xml" }
2828
}
2929
}
3030
}
3131

3232

3333
htmlDirs.forEach { (p, d) ->
34+
val name = p.pathAsFilename()
35+
3436
// delete directory for HTML reports so that the old reports do not overlap with the new ones
35-
project.delete(outputDir.dir("html/$p"))
37+
project.delete(outputDir.dir("html/$name"))
3638

3739
project.copy {
3840
it.from(d)
39-
it.into(outputDir.dir("html/$p"))
41+
it.into(outputDir.dir("html/$name"))
4042
}
4143
}
4244
}
45+
46+
private fun String.pathAsFilename(): String {
47+
return if (this == ":") "_root_" else replace(':', '_')
48+
}
4349
}

src/main/kotlin/kotlinx/kover/tasks/KoverHtmlReport.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ open class KoverMergedHtmlReportTask : KoverMergedTask() {
4444

4545
@CacheableTask
4646
open class KoverHtmlReportTask : KoverProjectTask() {
47-
private val projectName = project.name
47+
private val projectPath = project.path
4848

4949
/**
5050
* Specifies directory path of generated HTML report.
@@ -72,6 +72,6 @@ open class KoverHtmlReportTask : KoverProjectTask() {
7272
classpath.get(),
7373
)
7474
}
75-
logger.lifecycle("Kover: HTML report for '$projectName' file://${htmlDirFile.canonicalPath}/index.html")
75+
logger.lifecycle("Kover: HTML report for '$projectPath' file://${htmlDirFile.canonicalPath}/index.html")
7676
}
7777
}

src/main/kotlin/kotlinx/kover/tasks/KoverMergedTask.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,16 +71,16 @@ open class KoverMergedTask : DefaultTask() {
7171
val sourcesMap = srcDirs.get()
7272
val outputsMap = outputDirs.get()
7373

74-
val projectsNames = sourcesMap.keys
74+
val projectsPaths = sourcesMap.keys
7575

7676
val reportFiles: MutableList<File> = mutableListOf()
7777
val projects: MutableList<ProjectInfo> = mutableListOf()
7878

79-
projectsNames.map { projectName ->
80-
reportFiles += binariesMap.getValue(projectName).files.get()
79+
projectsPaths.map { projectPath ->
80+
reportFiles += binariesMap.getValue(projectPath).files.get()
8181
projects += ProjectInfo(
82-
sources = sourcesMap.getValue(projectName).files.get(),
83-
outputs = outputsMap.getValue(projectName).files.get()
82+
sources = sourcesMap.getValue(projectPath).files.get(),
83+
outputs = outputsMap.getValue(projectPath).files.get()
8484
)
8585
}
8686

0 commit comments

Comments
 (0)