diff --git a/src/functionalTest/kotlin/kotlinx/kover/gradle/plugin/test/functional/cases/ArtifactGenerationTests.kt b/src/functionalTest/kotlin/kotlinx/kover/gradle/plugin/test/functional/cases/ArtifactGenerationTests.kt index 98f5c2eb..bb18bc08 100644 --- a/src/functionalTest/kotlin/kotlinx/kover/gradle/plugin/test/functional/cases/ArtifactGenerationTests.kt +++ b/src/functionalTest/kotlin/kotlinx/kover/gradle/plugin/test/functional/cases/ArtifactGenerationTests.kt @@ -3,8 +3,11 @@ */ package kotlinx.kover.gradle.plugin.test.functional.cases +import kotlinx.kover.gradle.plugin.test.functional.framework.checker.CheckerContext import kotlinx.kover.gradle.plugin.test.functional.framework.configurator.BuildConfigurator +import kotlinx.kover.gradle.plugin.test.functional.framework.starter.ExamplesTest import kotlinx.kover.gradle.plugin.test.functional.framework.starter.GeneratedTest +import kotlin.test.* internal class ArtifactGenerationTests { @@ -21,4 +24,24 @@ internal class ArtifactGenerationTests { taskNotCalled("koverGenerateArtifact") } } + + /** + * Check that Kover artifact files are not resolved during the task dependency tree construction process. + * + * The task tree is built at the configuration stage, so getting artifacts from dependencies can lead to premature task launches, deadlocks, and performance degradation. + * + * If a resolution is detected during configuration, the message "Configuration 'koverExternalArtifactsRelease' was resolved during configuration time" is printed. + * This message may be changed in future versions, so it's worth double-checking for this error. + */ + @ExamplesTest("android/multiproject", [":app:koverXmlReportRelease"]) + fun CheckerContext.testResolveConfigurationInExecuteTime() { + assertFalse( + output.contains("Configuration 'koverExternalArtifactsRelease' was resolved during configuration time"), + "Kover Configuration was resolved during configuration time" + ) + assertFalse( + output.contains("This is a build performance and scalability issue"), + "Some Configuration was resolved during configuration time, perhaps this is the Kover Configuration" + ) + } } \ No newline at end of file diff --git a/src/main/kotlin/kotlinx/kover/gradle/plugin/tasks/AbstractKoverReportTask.kt b/src/main/kotlin/kotlinx/kover/gradle/plugin/tasks/AbstractKoverReportTask.kt index b2478945..56fe48d7 100644 --- a/src/main/kotlin/kotlinx/kover/gradle/plugin/tasks/AbstractKoverReportTask.kt +++ b/src/main/kotlin/kotlinx/kover/gradle/plugin/tasks/AbstractKoverReportTask.kt @@ -33,20 +33,42 @@ internal abstract class AbstractKoverReportTask(@Internal protected val tool: Co val reportClasspath: ConfigurableFileCollection = project.objects.fileCollection() /** - * This will cause the task to be considered out-of-date when source files have changed. + * This will cause the task to be considered out-of-date when source files of dependencies have changed. */ @get:InputFiles @get:PathSensitive(PathSensitivity.RELATIVE) - internal val sources: Collection - get() = collectAllFiles().sources + internal val externalSources: Provider> = externalArtifacts.elements.map { + val content = ArtifactContent(emptySet(), emptySet(), emptySet()) + content.joinWith(it.map { file -> file.asFile.parseArtifactFile() }).sources + } + + /** + * This will cause the task to be considered out-of-date when coverage measurements of dependencies have changed. + */ + @get:InputFiles + @get:PathSensitive(PathSensitivity.RELATIVE) + internal val externalReports: Provider> = externalArtifacts.elements.map { + val content = ArtifactContent(emptySet(), emptySet(), emptySet()) + content.joinWith(it.map { file -> file.asFile.parseArtifactFile() }).reports + } /** - * This will cause the task to be considered out-of-date when binary reports have changed. + * This will cause the task to be considered out-of-date when source files of this project have changed. */ @get:InputFiles @get:PathSensitive(PathSensitivity.RELATIVE) - internal val reports: Collection - get() = collectAllFiles().reports + internal val localSources: Provider> = localArtifact.map { + it.asFile.parseArtifactFile().sources + } + + /** + * This will cause the task to be considered out-of-date when coverage measurements of this project have changed. + */ + @get:InputFiles + @get:PathSensitive(PathSensitivity.RELATIVE) + internal val localReports: Provider> = localArtifact.map { + it.asFile.parseArtifactFile().reports + } @get:Nested val toolVariant: CoverageToolVariant = tool.variant