Add external APIs to publish multiplatform resources in a target

^KT-65540
This commit is contained in:
Timofey Solonin
2024-02-26 18:21:02 +01:00
committed by Space Team
parent 4e10dcd808
commit 3dd33e5aa7
5 changed files with 159 additions and 2 deletions
@@ -910,6 +910,8 @@ public final class org/jetbrains/kotlin/gradle/plugin/mpp/external/ExternalKotli
public abstract interface class org/jetbrains/kotlin/gradle/plugin/mpp/resources/KotlinTargetResourcesPublication {
public static final field Companion Lorg/jetbrains/kotlin/gradle/plugin/mpp/resources/KotlinTargetResourcesPublication$Companion;
public static final field EXTENSION_NAME Ljava/lang/String;
public abstract fun canPublishResources (Lorg/jetbrains/kotlin/gradle/plugin/KotlinTarget;)Z
public abstract fun publishResourcesAsKotlinComponent (Lorg/jetbrains/kotlin/gradle/plugin/KotlinTarget;Lkotlin/jvm/functions/Function1;Lorg/gradle/api/provider/Provider;)V
}
public abstract class org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/SourceSetTreeClassifier {
@@ -776,6 +776,16 @@ object KotlinToolingDiagnostics {
)
}
object ResourceMayNotBePublishedForTarget : ToolingDiagnosticFactory(ERROR) {
operator fun invoke(targetName: String) = build(
"""
Resources publication for target $targetName is not supported yet.
$resourcesBugReportRequest
""".trimIndent()
)
}
object DependencyDoesNotPhysicallyExist : ToolingDiagnosticFactory(WARNING) {
operator fun invoke(dependency: File) = build(
"""
@@ -21,6 +21,14 @@ interface KotlinTargetResourcesPublication {
val excludes: List<String>,
)
fun canPublishResources(target: KotlinTarget): Boolean
fun publishResourcesAsKotlinComponent(
target: KotlinTarget,
resourcePathForSourceSet: (KotlinSourceSet) -> (ResourceRoot),
relativeResourcePlacement: Provider<File>,
)
companion object {
const val EXTENSION_NAME = "multiplatformResourcesPublication"
}
@@ -11,6 +11,8 @@ import org.gradle.api.provider.Provider
import org.gradle.api.tasks.TaskProvider
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics
import org.jetbrains.kotlin.gradle.plugin.diagnostics.reportDiagnostic
import org.jetbrains.kotlin.gradle.plugin.launchInStage
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
@@ -32,8 +34,11 @@ internal abstract class KotlinTargetResourcesPublicationImpl @Inject constructor
val relativeResourcePlacement: Provider<File>,
)
private val targetToResourcesMap: MutableMap<KotlinTarget, TargetResources> = mutableMapOf()
private val targetsThatSupportPublication = listOf(
KotlinJvmTarget::class,
)
private val targetToResourcesMap: MutableMap<KotlinTarget, TargetResources> = mutableMapOf()
private val targetResourcesSubscribers: MutableMap<KotlinTarget, MutableList<(TargetResources) -> (Unit)>> = mutableMapOf()
internal fun subscribeOnPublishResources(
@@ -45,8 +50,36 @@ internal abstract class KotlinTargetResourcesPublicationImpl @Inject constructor
}
override fun canPublishResources(target: KotlinTarget): Boolean {
if (targetsThatSupportPublication.none { it.isInstance(target) }) return false
return true
}
override fun publishResourcesAsKotlinComponent(
target: KotlinTarget,
resourcePathForSourceSet: (KotlinSourceSet) -> (KotlinTargetResourcesPublication.ResourceRoot),
relativeResourcePlacement: Provider<File>,
) {
if (!canPublishResources(target)) {
target.project.reportDiagnostic(KotlinToolingDiagnostics.ResourceMayNotBePublishedForTarget(target.name))
return
}
if (targetToResourcesMap[target] != null) {
target.project.reportDiagnostic(KotlinToolingDiagnostics.ResourcePublishedMoreThanOncePerTarget(target.name))
return
}
val resources = TargetResources(
resourcePathForSourceSet = resourcePathForSourceSet,
relativeResourcePlacement = relativeResourcePlacement,
)
targetToResourcesMap[target] = resources
targetResourcesSubscribers[target].orEmpty().forEach { notify ->
notify(resources)
}
}
internal companion object {
const val MULTIPLATFORM_RESOURCES_DIRECTORY = "kotlin-multiplatform-resources"
}
}
}
@@ -0,0 +1,104 @@
/*
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.gradle.unitTests
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics
import org.jetbrains.kotlin.gradle.plugin.mpp.resources.KotlinTargetResourcesPublication
import org.jetbrains.kotlin.gradle.plugin.mpp.resources.resourcesPublicationExtension
import org.jetbrains.kotlin.gradle.util.assertContainsDiagnostic
import org.jetbrains.kotlin.gradle.util.buildProjectWithMPP
import org.jetbrains.kotlin.gradle.util.kotlin
import org.junit.Test
import java.io.File
import kotlin.test.assertEquals
class KotlinTargetResourcesPublicationImplTests {
@Test
fun `test publication callback - after resources publication`() {
val project = buildProjectWithMPP {
kotlin {
jvm()
}
}
val target = project.multiplatformExtension.jvm()
var callbacks = 0
project.publishFakeResources(target)
project.multiplatformExtension.resourcesPublicationExtension?.subscribeOnPublishResources(
target
) {
callbacks += 1
}
assertEquals(callbacks, 1)
project.multiplatformExtension.resourcesPublicationExtension?.subscribeOnPublishResources(
target
) {
callbacks += 1
}
assertEquals(callbacks, 2)
}
@Test
fun `test publication callback - before and after resources publication`() {
val project = buildProjectWithMPP {
kotlin {
jvm()
}
}
val target = project.multiplatformExtension.jvm()
var callbacks = 0
project.multiplatformExtension.resourcesPublicationExtension?.subscribeOnPublishResources(
target
) {
callbacks += 1
}
project.publishFakeResources(target)
assertEquals(callbacks, 1)
project.multiplatformExtension.resourcesPublicationExtension?.subscribeOnPublishResources(
target
) {
callbacks += 1
}
assertEquals(callbacks, 2)
}
@Test
fun `test publication - reports a diagnostic when publishing multiple times per target`() {
val project = buildProjectWithMPP {
kotlin {
jvm()
}
}
val target = project.multiplatformExtension.jvm()
project.publishFakeResources(target)
project.publishFakeResources(target)
project.assertContainsDiagnostic(KotlinToolingDiagnostics.ResourcePublishedMoreThanOncePerTarget)
}
private fun Project.publishFakeResources(target: KotlinTarget) {
project.multiplatformExtension.resourcesPublicationExtension?.publishResourcesAsKotlinComponent(
target,
resourcePathForSourceSet = {
KotlinTargetResourcesPublication.ResourceRoot(
project.provider { File(it.name) },
emptyList(),
emptyList(),
)
},
relativeResourcePlacement = project.provider { File("test") },
)
}
}