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

Add possibility of lazy configuration of Kover extensions #410

Closed
shanshin opened this issue Jun 14, 2023 · 1 comment
Closed

Add possibility of lazy configuration of Kover extensions #410

shanshin opened this issue Jun 14, 2023 · 1 comment
Assignees
Labels
Feature Feature request issue type S: ready for release Status: merged in the main branch

Comments

@shanshin
Copy link
Collaborator

shanshin commented Jun 14, 2023

Motivation

In order not to write the same boilerplate configuration code, it can be placed in a convention plugin.

koverReport {
    verify {
        rule {
            bound {
                minValue = 50
                metric = MetricType.BRANCH
            }
        } 
    }
    // ...
}

Since the expected coverage may vary for each subproject, so if you put this code in a convention plugin, you will have to write something like this

plugins {
    id("org.jetbrains.kotlinx.kover")
}

koverReport {
    if (project.name in specialProjects) {
        verify {
            rule {
                bound {
                    minValue = 90
                    metric = MetricType.BRANCH
                }
            }
        }
        // ...
    } else {
        verify {
            rule {
                bound {
                    minValue = 50
                    metric = MetricType.BRANCH
                }
            }
        }
        // ...
    }
}

This is less flexible, because we must constantly remember to add new subprojects, as well as if the values differ for a large number of projects, then there will be a lot of lists and if .

In such cases, an project extension is added through which you can configure the behavior of the plugin.

plugins {
    id("org.jetbrains.kotlinx.kover")
}

interface MyExtension {
    val minVal: Property<Int>
}

val exten = extensions.create<MyExtension>("my")

koverReport {
    verify {
        rule {
            bound {
                println("read value")
                minValue = exten.minVal.get()
                metric = MetricType.BRANCH
            }
        } 
    }
    // ...
}

in the user project project itself

plugins {
    id("my.kover.convention")
}

extensions.configure<MyExtension> {
    println("write value")
    minVal.set(10)
}

The convention plugin is applied before the project is evaluated.
In logs will be:

read value
write value

Accordingly, it is not possible in the current form to configure Kover through the convention plugin.
afterEvaluate is often used to circumvent this limitation, which in many cases is performed in an unpredictable order.

This problem goes away if the Kaver properties are of the Property<...> type, and not of the primitive type:

plugins {
    id("org.jetbrains.kotlinx.kover")
}

interface MyExtension {
    val minVal: Property<Int>
}

val exten = extensions.create<MyExtension>("my")

koverReport {
    verify {
        rule {
            bound {
                println("read value")
                minValue.set(exten.minVal)
                metric.set(MetricType.BRANCH)
            }
        } 
    }
    // ...
}

example project and issue.

Solution

Replace all configurable values of the primitive type with wrappers-providers over this type.

Example of new DSL

kover {
    disabled.set(false) // instead: disable()

    excludeJavaCode.set(false) // instead: excludeJavaCode()
 
    useJacoco.set(false) // instead: useJacoco()
    jacocoVersion.set("0.8.8")


    excludedTestTasks.add("taskName")
    /* instead: 
      excludeTests {
          tasks("taskName")
      }
    */
 

    excludedSourceSets.add("aaa")
    /* instead:
      excludeSourceSets {
          names("aaa")
      }
    */

    excludeInstrumentation {
        classes("*Foo*", "*Bar") // old DSL
        classes.addAll("*Foo*", "*Bar")
 
        packages("com.project") // old DSL
        packages.add("com.project")
    }
}

koverReport {
    filters {
        excludes {
            classes("*.foo.Bar", "*.M?Class") // old DSL
            classes.addAll("*.foo.Bar", "*.M?Class")
            
            packages("foo.b?r", "com.*.example") // old DSL
            packages.addAll("foo.b?r", "com.*.example")
            
            annotatedBy("*Generated*", "com.example.KoverExclude") // old DSL
            annotatedBy.addAll("*Generated*", "com.example.KoverExclude")
        }
        
        includes {
            classes("*.foo.Bar", "*.M?Class") // old DSL
            classes.addAll("*.foo.Bar", "*.M?Class")
            
            packages("foo.b?r", "com.*.example") // old DSL
            packages.addAll("foo.b?r", "com.*.example")
        }
    }
    
    
    verify {
       rule {
           filters { ... }
         
           // `is` erased in the Groove
           isEnabled = true
           // errors in old Gradle kts < 8.0
           name.set("my rule")
                
           groupBy.set(GroupingEntityType.APPLICATION) // instead: entity = kotlinx.kover.gradle.plugin.dsl.GroupingEntityType.APPLICATION 
           
           bound {
              // errors in old Gradle kts < 8.0
              minValue.set(1)
              maxValue.set(99)
  
              coverageUnits.set(MetricType.LINE) // instead: metric = kotlinx.kover.gradle.plugin.dsl.MetricType.LINE
  
              aggregationForGroup.set(AggregationType.COVERED_PERCENTAGE) // instead: aggregation = kotlinx.kover.gradle.plugin.dsl.AggregationType.COVERED_PERCENTAGE
          }
       }
    }
   
   total {
       filters { ... }
       
       html {
           filters { ... }
           
           // errors in old Gradle kts < 8.0
           title.set("Title")
           charset.set("UTF-8")
           onCheck.set(true)
           
           reportDir.set(file) // instead: setReportDir(file)
       }
   
       xml {
           filters { ... }  
           
           // errors in old Gradle kts < 8.0
           onCheck.set(true)
           
           reportFile.set(file) // instead: setReportFile(file)
       }
       
       binary {
           filters { ... }
           onCheck.set(false)
           file.set(file)
       }
       
       verify {
           // errors in old Gradle kts < 8.0
           onCheck.set(true)  
           
           rule { ... }
       }
       
       log {
           filters { ... }
           
           // errors in old Gradle kts < 8.0
           onCheck.set(true)
           header.set(null)
           format.set("header")
           groupBy.set(GroupingEntityType.APPLICATION)
           coverageUnits.set(MetricType.LINE)
           aggregationForGroup.set(AggregationType.COVERED_PERCENTAGE)
       }
   } 
    
}
@shanshin shanshin added Feature Feature request issue type S: untriaged Status: issue reported but unprocessed labels Jun 14, 2023
@shanshin shanshin self-assigned this Jun 14, 2023
@shanshin shanshin added S: in progress Status: implementing or design in process and removed S: untriaged Status: issue reported but unprocessed labels Jun 27, 2023
shanshin added a commit that referenced this issue Feb 19, 2024
- blocks kover and koverReports are merged
- added possibility of lazy configuration of Kover extensions
- removed the concept of default reports
- added the ability to create custom report variants
- Created interfaces for Kover tasks

Resolves #461
Resolves #410
Resolves #462
Resolves #463
Resolves #338
@shanshin shanshin reopened this Feb 20, 2024
@shanshin shanshin added S: ready for release Status: merged in the main branch and removed S: in progress Status: implementing or design in process labels Feb 20, 2024
@shanshin
Copy link
Collaborator Author

Implemented in 0.8.0-Beta.
This is not a production ready release, the plugin DSL is experimental and can be changed after receiving feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature Feature request issue type S: ready for release Status: merged in the main branch
Projects
None yet
Development

No branches or pull requests

1 participant