[Gradle] Change withPluginId to isPluginApplied
It is more convenient to use. Also added test coverage for cases when plugin is applied too late. ^KT-62877 Verification Pending
This commit is contained in:
committed by
Space Team
parent
5607ae1bc3
commit
d3f25d81de
-13
@@ -325,19 +325,6 @@ private val Project.allProjectsData: Map<String, GranularMetadataTransformation.
|
|||||||
|
|
||||||
private fun Project.collectAllProjectsData(): Map<String, GranularMetadataTransformation.ProjectData> {
|
private fun Project.collectAllProjectsData(): Map<String, GranularMetadataTransformation.ProjectData> {
|
||||||
return rootProject.allprojects.associateBy { it.path }.mapValues { (path, currentProject) ->
|
return rootProject.allprojects.associateBy { it.path }.mapValues { (path, currentProject) ->
|
||||||
|
|
||||||
/*
|
|
||||||
We're calling into various different projects (Note: This implementation will change with Project Isolation)
|
|
||||||
Since not all projects might have the Kotlin Gradle Plugin applied we do call into 'idOfRootModule' in two different ways:
|
|
||||||
|
|
||||||
1) If KGP is applied, we use the lifecycle APIs to safely get a value after the DSL was finalised.
|
|
||||||
2) If KGP was *not* applied, we create a Future which
|
|
||||||
- creates a lazy once the project is evaluated
|
|
||||||
- only evaluates the lazy once the moduleId is actually accessed
|
|
||||||
|
|
||||||
This double deferral ensures that the value indeed is accessed as late as possible.
|
|
||||||
Unwrapping the lazy before the buildscript is evaluated will fail with 'future not completed'
|
|
||||||
*/
|
|
||||||
val moduleId = currentProject.future { ModuleIds.idOfRootModuleSafe(currentProject) }.lenient
|
val moduleId = currentProject.future { ModuleIds.idOfRootModuleSafe(currentProject) }.lenient
|
||||||
|
|
||||||
GranularMetadataTransformation.ProjectData(
|
GranularMetadataTransformation.ProjectData(
|
||||||
|
|||||||
+17
-19
@@ -26,34 +26,32 @@ import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.sources.sourceSetDependencyConfigurationByScope
|
import org.jetbrains.kotlin.gradle.plugin.sources.sourceSetDependencyConfigurationByScope
|
||||||
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
|
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
|
||||||
import org.jetbrains.kotlin.gradle.tooling.buildKotlinToolingMetadataTask
|
import org.jetbrains.kotlin.gradle.tooling.buildKotlinToolingMetadataTask
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.*
|
||||||
import org.jetbrains.kotlin.gradle.utils.CompletableFuture
|
import org.jetbrains.kotlin.gradle.utils.CompletableFuture
|
||||||
import org.jetbrains.kotlin.gradle.utils.Future
|
import org.jetbrains.kotlin.gradle.utils.Future
|
||||||
import org.jetbrains.kotlin.gradle.utils.projectStoredProperty
|
import org.jetbrains.kotlin.gradle.utils.projectStoredProperty
|
||||||
import org.jetbrains.kotlin.gradle.utils.whenEvaluated
|
import org.jetbrains.kotlin.gradle.utils.whenEvaluated
|
||||||
import org.jetbrains.kotlin.gradle.utils.withPluginId
|
|
||||||
|
|
||||||
private val Project.completableFutureForKotlinMultiplatformRootPublication: CompletableFuture<MavenPublication?>
|
private val Project.kotlinMultiplatformRootPublicationImpl: CompletableFuture<MavenPublication?>
|
||||||
by projectStoredProperty { CompletableFuture() }
|
by projectStoredProperty { CompletableFuture() }
|
||||||
internal val Project.kotlinMultiplatformRootPublication: Future<MavenPublication?>
|
internal val Project.kotlinMultiplatformRootPublication: Future<MavenPublication?>
|
||||||
get() = completableFutureForKotlinMultiplatformRootPublication
|
get() = kotlinMultiplatformRootPublicationImpl
|
||||||
|
|
||||||
internal val MultiplatformPublishingSetupAction = KotlinProjectSetupAction {
|
internal val MultiplatformPublishingSetupAction = KotlinProjectSetupCoroutine {
|
||||||
project.withPluginId(
|
if (!project.kotlinPropertiesProvider.createDefaultMultiplatformPublications) {
|
||||||
pluginId = "maven-publish",
|
kotlinMultiplatformRootPublicationImpl.complete(null)
|
||||||
whenApplied = {
|
return@KotlinProjectSetupCoroutine
|
||||||
if (project.kotlinPropertiesProvider.createDefaultMultiplatformPublications) {
|
}
|
||||||
project.extensions.configure(PublishingExtension::class.java) { publishing ->
|
|
||||||
createRootPublication(project, publishing).also(completableFutureForKotlinMultiplatformRootPublication::complete)
|
|
||||||
createTargetPublications(project, publishing)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
completableFutureForKotlinMultiplatformRootPublication.complete(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
project.components.add(project.multiplatformExtension.rootSoftwareComponent)
|
if (isPluginApplied("maven-publish")) {
|
||||||
},
|
project.extensions.configure(PublishingExtension::class.java) { publishing ->
|
||||||
whenNotApplied = { completableFutureForKotlinMultiplatformRootPublication.complete(null) }
|
createRootPublication(project, publishing).also(kotlinMultiplatformRootPublicationImpl::complete)
|
||||||
)
|
createTargetPublications(project, publishing)
|
||||||
|
}
|
||||||
|
project.components.add(project.multiplatformExtension.rootSoftwareComponent)
|
||||||
|
} else {
|
||||||
|
kotlinMultiplatformRootPublicationImpl.complete(null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+14
-11
@@ -10,18 +10,21 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.AfterEvalu
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.launchInStage
|
import org.jetbrains.kotlin.gradle.plugin.launchInStage
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes the given block of code if the Gradle Plugin with [pluginId] is applied to the project. Otherwise,
|
* Returns true as soon as Gradle plugin with [pluginId] is applied.
|
||||||
* executes another block of code.
|
* Returns false if plugin wasn't applied during
|
||||||
*/
|
*/
|
||||||
internal fun <T> Project.withPluginId(
|
internal suspend fun Project.isPluginApplied(pluginId: String): Boolean {
|
||||||
pluginId: String,
|
val result = CompletableFuture<Boolean>()
|
||||||
whenApplied: () -> T,
|
pluginManager.withPlugin(pluginId) {
|
||||||
whenNotApplied: () -> T,
|
check(!result.isCompleted) {
|
||||||
): Future<T> {
|
"Plugin '$pluginId' was applied too late. It was expected to be applied during build script evaluation"
|
||||||
val result = CompletableFuture<T>()
|
}
|
||||||
pluginManager.withPlugin(pluginId) { result.complete(whenApplied()) }
|
result.complete(true)
|
||||||
|
}
|
||||||
// All plugins must be applied during evaluation of build script
|
// All plugins must be applied during evaluation of build script
|
||||||
launchInStage(AfterEvaluateBuildscript) { if (!result.isCompleted) result.complete(whenNotApplied()) }
|
launchInStage(AfterEvaluateBuildscript) {
|
||||||
|
if (!result.isCompleted) result.complete(false)
|
||||||
|
}
|
||||||
|
|
||||||
return result
|
return result.await()
|
||||||
}
|
}
|
||||||
+34
-30
@@ -8,15 +8,17 @@
|
|||||||
package org.jetbrains.kotlin.gradle.unitTests
|
package org.jetbrains.kotlin.gradle.unitTests
|
||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.ProjectConfigurationException
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.AfterEvaluateBuildscript
|
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.AfterEvaluateBuildscript
|
||||||
import org.jetbrains.kotlin.gradle.plugin.currentKotlinPluginLifecycle
|
import org.jetbrains.kotlin.gradle.plugin.currentKotlinPluginLifecycle
|
||||||
import org.jetbrains.kotlin.gradle.util.buildProject
|
import org.jetbrains.kotlin.gradle.plugin.launch
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.launchInStage
|
||||||
|
import org.jetbrains.kotlin.gradle.util.allCauses
|
||||||
import org.jetbrains.kotlin.gradle.util.buildProjectWithMPP
|
import org.jetbrains.kotlin.gradle.util.buildProjectWithMPP
|
||||||
import org.jetbrains.kotlin.gradle.util.kotlin
|
import org.jetbrains.kotlin.gradle.util.kotlin
|
||||||
import org.jetbrains.kotlin.gradle.util.runLifecycleAwareTest
|
import org.jetbrains.kotlin.gradle.util.runLifecycleAwareTest
|
||||||
import org.jetbrains.kotlin.gradle.utils.withPluginId
|
import org.jetbrains.kotlin.gradle.utils.isPluginApplied
|
||||||
import kotlin.test.Test
|
import kotlin.test.*
|
||||||
import kotlin.test.assertTrue
|
|
||||||
|
|
||||||
class PluginManagerUtilTest {
|
class PluginManagerUtilTest {
|
||||||
|
|
||||||
@@ -30,46 +32,48 @@ class PluginManagerUtilTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test - withPluginId - when plugin applied`() {
|
fun `test - isPluginApplied - when plugin applied`() {
|
||||||
val project = buildProject {
|
val project = buildSampleProject {
|
||||||
plugins.apply("maven-publish")
|
plugins.apply("maven-publish")
|
||||||
}
|
}
|
||||||
val future = project.withPluginId(
|
project.runLifecycleAwareTest {
|
||||||
pluginId = "maven-publish",
|
assertTrue(isPluginApplied("maven-publish"))
|
||||||
whenApplied = { true },
|
}
|
||||||
whenNotApplied = { false }
|
|
||||||
)
|
|
||||||
|
|
||||||
assertTrue(future.getOrThrow())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test - withPluginId - call withPluginId before plugin is applied`() {
|
fun `test - isPluginApplied - call withPluginId before plugin is applied`() {
|
||||||
val project = buildProject {}
|
val project = buildSampleProject {}
|
||||||
val future = project.withPluginId(
|
project.runLifecycleAwareTest {
|
||||||
pluginId = "maven-publish",
|
launch { assertTrue(isPluginApplied("maven-publish")) }
|
||||||
whenApplied = { true },
|
project.plugins.apply("maven-publish")
|
||||||
whenNotApplied = { false }
|
}
|
||||||
)
|
|
||||||
project.plugins.apply("maven-publish")
|
|
||||||
|
|
||||||
assertTrue(future.getOrThrow())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test - withPluginId - plugin not applied`() {
|
fun `test - withPluginId - plugin not applied`() {
|
||||||
val project = buildSampleProject()
|
val project = buildSampleProject()
|
||||||
|
|
||||||
val future = project.withPluginId(
|
|
||||||
pluginId = "some-plugin-id",
|
|
||||||
whenApplied = { false },
|
|
||||||
whenNotApplied = { true },
|
|
||||||
)
|
|
||||||
|
|
||||||
project.runLifecycleAwareTest {
|
project.runLifecycleAwareTest {
|
||||||
assertTrue(future.await())
|
assertFalse(isPluginApplied("maven-publish"))
|
||||||
val currentStage = currentKotlinPluginLifecycle().stage
|
val currentStage = currentKotlinPluginLifecycle().stage
|
||||||
assertTrue(currentStage <= AfterEvaluateBuildscript)
|
assertTrue(currentStage <= AfterEvaluateBuildscript)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test - withPluginId - plugin can't be applied after build script evaluation`() {
|
||||||
|
val project = buildSampleProject()
|
||||||
|
|
||||||
|
val error = assertFails {
|
||||||
|
project.runLifecycleAwareTest {
|
||||||
|
launchInStage(AfterEvaluateBuildscript.nextOrLast) { plugins.apply("maven-publish") }
|
||||||
|
isPluginApplied("maven-publish")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val errorMessages = error.allCauses.map { it.message }
|
||||||
|
val expectedErrorMessage = "Plugin 'maven-publish' was applied too late. It was expected to be applied during build script evaluation"
|
||||||
|
if (expectedErrorMessage !in errorMessages) fail("Expected to fail with: $expectedErrorMessage")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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.util
|
||||||
|
|
||||||
|
import org.gradle.internal.exceptions.MultiCauseException
|
||||||
|
|
||||||
|
val Throwable.allCauses: Set<Throwable>
|
||||||
|
get() {
|
||||||
|
val result = mutableSetOf<Throwable>()
|
||||||
|
val queue = ArrayDeque<Throwable>()
|
||||||
|
queue.add(this)
|
||||||
|
|
||||||
|
while (queue.isNotEmpty()) {
|
||||||
|
val error = queue.removeFirst()
|
||||||
|
if (!result.add(error)) continue
|
||||||
|
|
||||||
|
if (error is MultiCauseException) {
|
||||||
|
queue.addAll(error.causes)
|
||||||
|
} else {
|
||||||
|
if (error.cause != null) queue.addLast(error.cause!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user