All Downloads are FREE. Search and download functionalities are using the official Maven repository.

kotlinx.kover.gradle.plugin.tools.Verification.kt Maven / Gradle / Ivy

There is a newer version: 0.9.0-RC
Show newest version
/*
 * Copyright 2017-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
 */

package kotlinx.kover.gradle.plugin.tools

import kotlinx.kover.gradle.plugin.dsl.*
import java.io.File
import java.io.Serializable
import java.math.*
import java.nio.charset.Charset

internal fun CoverageMeasures.writeToFile(file: File, header: String?, lineFormat: String) {
    file.bufferedWriter(Charset.forName("UTF-8")).use { writer ->
        header?.let { h -> writer.appendLine(h) }

        values.forEach { coverage ->
            val entityName = coverage.entityName ?: "application"
            writer.appendLine(
                lineFormat.replace("", coverage.value.stripTrailingZeros().toPlainString())
                    .replace("", entityName)
            )
        }
    }
}

internal fun File.writeNoSources(header: String?) {
    this.bufferedWriter(Charset.forName("UTF-8")).use { writer ->
        header?.let { h -> writer.appendLine(h) }
        writer.appendLine("No sources")
    }
}


internal data class CoverageRequest(
    val entity: GroupingEntityType,
    val metric: MetricType,
    val aggregation: AggregationType,
    val header: String?,
    val lineFormat: String,
): Serializable

internal data class CoverageMeasures(
    val values: List
)

internal data class CoverageValue(
    val value: BigDecimal,
    val entityName: String? = null,
)

internal data class RuleViolations(
    val entityType: GroupingEntityType,
    val bounds: List,
    val name: String? = null
)

internal data class BoundViolations(
    val isMax: Boolean,
    val expectedValue: BigDecimal,
    val actualValue: BigDecimal,
    val metric: MetricType,
    val aggregation: AggregationType,
    val entityName: String? = null
)

internal fun generateErrorMessage(violations: List): String {
    val messageBuilder = StringBuilder()

    violations.forEach { rule ->
        val namedRule = if (rule.name != null) "Rule '${rule.name}'" else "Rule"

        if (rule.bounds.size == 1) {
            messageBuilder.appendLine("$namedRule violated: ${rule.bounds[0].format(rule)}")
        } else {
            messageBuilder.appendLine("$namedRule violated:")

            rule.bounds.forEach { bound ->
                messageBuilder.append("  ")
                messageBuilder.appendLine(bound.format(rule))
            }
        }
    }

    return messageBuilder.toString()
}

private fun BoundViolations.format(rule: RuleViolations): String {
    val directionText = if (isMax) "maximum" else "minimum"

    val metricText = when (metric) {
        MetricType.LINE -> "lines"
        MetricType.INSTRUCTION -> "instructions"
        MetricType.BRANCH -> "branches"
    }

    val valueTypeText = when (aggregation) {
        AggregationType.COVERED_COUNT -> "covered count"
        AggregationType.MISSED_COUNT -> "missed count"
        AggregationType.COVERED_PERCENTAGE -> "covered percentage"
        AggregationType.MISSED_PERCENTAGE -> "missed percentage"
    }

    val entityText = when (rule.entityType) {
        GroupingEntityType.APPLICATION -> ""
        GroupingEntityType.CLASS -> " for class '$entityName'"
        GroupingEntityType.PACKAGE -> " for package '$entityName'"
    }

    return "$metricText $valueTypeText$entityText is $actualValue, but expected $directionText is $expectedValue"
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy