1+ apply (plugin = " jacoco" )
2+
3+ // Check if this is a Kotlin Multiplatform project
4+ val isKmpProject = plugins.hasPlugin(" org.jetbrains.kotlin.multiplatform" )
5+ val isAndroidProject = plugins.hasPlugin(" com.android.library" ) || plugins.hasPlugin(" com.android.application" )
6+
7+ tasks.register(" jacocoReport" , JacocoReport ::class ) {
8+ group = " Coverage"
9+ description = " Generate XML/HTML code coverage reports"
10+
11+ // Set source directories based on project type
12+ if (isKmpProject) {
13+ // For KMP projects, include all source sets
14+ sourceDirectories.setFrom(
15+ layout.projectDirectory.dir(" src/commonMain/kotlin" ),
16+ layout.projectDirectory.dir(" src/androidMain/kotlin" ),
17+ layout.projectDirectory.dir(" src/commonTest/kotlin" ),
18+ layout.projectDirectory.dir(" src/androidUnitTest/kotlin" )
19+ )
20+ } else {
21+ // For Android projects
22+ sourceDirectories.setFrom(" ${project.projectDir} /src/main/java" )
23+ }
24+
25+ val excludes = mutableSetOf<String >(
26+ " android/databinding/**/*.class" ,
27+ " **/android/databinding/*Binding.class" ,
28+ " **/android/databinding/*" ,
29+ " **/androidx/databinding/*" ,
30+ " **/BR.*" ,
31+ " **/R.class" ,
32+ " **/R\$ *.class" ,
33+ " **/BuildConfig.*" ,
34+ " **/Manifest*.*" ,
35+ " **/*Test*.*" ,
36+ " android/**/*.*" ,
37+ " **/*MapperImpl*.*" ,
38+ " **/*\$ ViewInjector*.*" ,
39+ " **/*\$ ViewBinder*.*" ,
40+ " **/BuildConfig.*" ,
41+ " **/*Component*.*" ,
42+ " **/*BR*.*" ,
43+ " **/Manifest*.*" ,
44+ " **/*\$ Lambda\$ *.*" ,
45+ " **/*Companion*.*" ,
46+ " **/*Module*.*" ,
47+ " **/*Dagger*.*" ,
48+ " **/*MembersInjector*.*" ,
49+ " **/*_MembersInjector.class" ,
50+ " **/*_Factory*.*" ,
51+ " **/*_Provide*Factory*.*" ,
52+ " **/*Extensions*.*" ,
53+ " **/*\$ Result.*" ,
54+ " **/*\$ Result\$ *.*" ,
55+ " **/*JsonAdapter.*" ,
56+ " **/databinding/*.*" ,
57+ " **/customviews/*.*" ,
58+ " **/ui/*.class" ,
59+ " **/*Activity.*" ,
60+ " **/Activity*.*" ,
61+ " **/*Activity*.*" ,
62+ " **/*Fragment.*" ,
63+ " **/Fragment*.*" ,
64+ " **/*View.*" ,
65+ " **/*Adapter.*" ,
66+ " **/*Contract*.*" ,
67+ " **/*Bindings*.*" ,
68+ " **/AutoValue*.*" ,
69+ " **/*\$ *" ,
70+ " **/*Navigator.*" ,
71+ " **/*\$ *\$ *.*" ,
72+ " **/animations/*.*" ,
73+ " **/*Holder*.*" ,
74+ " **/*Dialog*.*" ,
75+ " **/*Service*.*" ,
76+ " **/*Button*.*" ,
77+ " **/SearchTEList.*" ,
78+ " **/lambda\$ *\$ *.*"
79+ )
80+
81+ // Set class directories based on project type
82+ val classDirectoriesList = mutableListOf<Any >()
83+
84+ if (isAndroidProject) {
85+ // Android project class directories
86+ val javaClassesApp = fileTree(layout.buildDirectory.dir(" intermediates/javac/dhisDebug" )){
87+ exclude(excludes)
88+ }
89+ val kotlinClassesApp = fileTree(layout.buildDirectory.dir(" tmp/kotlin-classes/dhisDebug" )){
90+ exclude(excludes)
91+ }
92+ val javaClasses = fileTree(layout.buildDirectory.dir(" intermediates/javac/debug" )){
93+ exclude(excludes)
94+ }
95+ val kotlinClasses = fileTree(layout.buildDirectory.dir(" tmp/kotlin-classes/debug" )){
96+ exclude(excludes)
97+ }
98+
99+ classDirectoriesList.addAll(listOf (javaClassesApp, kotlinClassesApp, javaClasses, kotlinClasses))
100+ }
101+
102+ if (isKmpProject) {
103+ // KMP project class directories
104+ val commonClasses = fileTree(layout.buildDirectory.dir(" classes/kotlin/common" )){
105+ exclude(excludes)
106+ }
107+ val androidClasses = fileTree(layout.buildDirectory.dir(" classes/kotlin/android" )){
108+ exclude(excludes)
109+ }
110+ val jvmClasses = fileTree(layout.buildDirectory.dir(" classes/kotlin/jvm" )){
111+ exclude(excludes)
112+ }
113+
114+ classDirectoriesList.addAll(listOf (commonClasses, androidClasses, jvmClasses))
115+ }
116+
117+ classDirectories.setFrom(files(classDirectoriesList))
118+
119+ // Execution data - look for both .exec and .ec files
120+ val unitTestsData = fileTree(layout.buildDirectory.dir(" jacoco" )) {
121+ include(" *.exec" )
122+ }
123+ val androidTestsData = fileTree(layout.buildDirectory.dir(" outputs/code_coverage" )) {
124+ include(listOf (" **/*.ec" ))
125+ }
126+
127+ executionData.setFrom(files(listOf (unitTestsData, androidTestsData)))
128+
129+ // Add test task dependencies based on project type
130+ if (isAndroidProject) {
131+ val testTask = tasks.findByName(" testDebugUnitTest" )
132+ val androidTestTask = tasks.findByName(" connectedDebugAndroidTest" )
133+
134+ if (testTask != null ) dependsOn(testTask)
135+ if (androidTestTask != null ) dependsOn(androidTestTask)
136+ }
137+
138+ if (isKmpProject) {
139+ val commonTestTask = tasks.findByName(" test" )
140+ val androidTestTask = tasks.findByName(" androidTest" )
141+
142+ if (commonTestTask != null ) dependsOn(commonTestTask)
143+ if (androidTestTask != null ) dependsOn(androidTestTask)
144+ }
145+
146+ fun JacocoReportsContainer.reports () {
147+ xml.required.set(true )
148+ xml.outputLocation.set(layout.buildDirectory.file(" coverage-report/jacocoTestReport.xml" ))
149+
150+ html.required.set(true )
151+ html.outputLocation.set(layout.buildDirectory.dir(" coverage-report" ))
152+ }
153+
154+ reports {
155+ reports()
156+ }
157+ }
0 commit comments