From 1f39fa4ba165e2ada409f523e907201ca9888099 Mon Sep 17 00:00:00 2001 From: "dima.avdeev" <99798741+dima-avdeev-jb@users.noreply.github.com> Date: Mon, 5 Sep 2022 19:59:29 +0400 Subject: [PATCH] Check experimental flags in gradle.properties (#2268) --- .../examples/chat-mpp/gradle.properties | 3 + .../falling-balls-mpp/gradle.properties | 3 + .../examples/minesweeper/gradle.properties | 3 + .../org/jetbrains/compose/ComposePlugin.kt | 2 + .../internal/checkExperimentalTargets.kt | 77 +++++++++++++++++++ 5 files changed, 88 insertions(+) create mode 100644 gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/experimental/internal/checkExperimentalTargets.kt diff --git a/experimental/examples/chat-mpp/gradle.properties b/experimental/examples/chat-mpp/gradle.properties index 193eedd8cd..ac08e49268 100644 --- a/experimental/examples/chat-mpp/gradle.properties +++ b/experimental/examples/chat-mpp/gradle.properties @@ -11,3 +11,6 @@ compose.version=1.2.0-alpha01-dev725 kotlin.version=1.6.21 agp.version=7.0.4 kotlin.js.webpack.major.version=4 +org.jetbrains.compose.experimental.jscanvas.enabled=true +org.jetbrains.compose.experimental.macos.enabled=true +org.jetbrains.compose.experimental.uikit.enabled=true diff --git a/experimental/examples/falling-balls-mpp/gradle.properties b/experimental/examples/falling-balls-mpp/gradle.properties index 702363f570..db26638086 100644 --- a/experimental/examples/falling-balls-mpp/gradle.properties +++ b/experimental/examples/falling-balls-mpp/gradle.properties @@ -11,3 +11,6 @@ kotlin.native.binary.memoryModel=experimental compose.desktop.verbose=true agp.version=7.0.4 android.useAndroidX=true +org.jetbrains.compose.experimental.jscanvas.enabled=true +org.jetbrains.compose.experimental.macos.enabled=true +org.jetbrains.compose.experimental.uikit.enabled=true diff --git a/experimental/examples/minesweeper/gradle.properties b/experimental/examples/minesweeper/gradle.properties index a0fbe1f957..f3991bafab 100644 --- a/experimental/examples/minesweeper/gradle.properties +++ b/experimental/examples/minesweeper/gradle.properties @@ -6,3 +6,6 @@ kotlin.native.enableDependencyPropagation=false # Enable kotlin/native experimental memory model kotlin.native.binary.memoryModel=experimental compose.desktop.verbose=true +org.jetbrains.compose.experimental.jscanvas.enabled=true +org.jetbrains.compose.experimental.macos.enabled=true +org.jetbrains.compose.experimental.uikit.enabled=true diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposePlugin.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposePlugin.kt index 1755055ed6..75e5c6947c 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposePlugin.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposePlugin.kt @@ -24,6 +24,7 @@ import org.jetbrains.compose.desktop.application.internal.configureDesktop import org.jetbrains.compose.desktop.application.internal.currentTarget import org.jetbrains.compose.desktop.preview.internal.initializePreview import org.jetbrains.compose.experimental.dsl.ExperimentalExtension +import org.jetbrains.compose.experimental.internal.checkExperimentalTargetsWithSkikoIsEnabled import org.jetbrains.compose.experimental.internal.configureExperimental import org.jetbrains.compose.internal.COMPOSE_PLUGIN_ID import org.jetbrains.compose.internal.KOTLIN_JS_PLUGIN_ID @@ -53,6 +54,7 @@ class ComposePlugin : Plugin { project.afterEvaluate { configureDesktop(project, desktopExtension) project.configureExperimental(composeExtension, experimentalExtension) + project.checkExperimentalTargetsWithSkikoIsEnabled() if (androidExtension.useAndroidX) { project.logger.warn("useAndroidX is an experimental feature at the moment!") diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/experimental/internal/checkExperimentalTargets.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/experimental/internal/checkExperimentalTargets.kt new file mode 100644 index 0000000000..0523517dd4 --- /dev/null +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/experimental/internal/checkExperimentalTargets.kt @@ -0,0 +1,77 @@ +/* + * Copyright 2020-2022 JetBrains s.r.o. and respective authors and developers. + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. + */ + +package org.jetbrains.compose.experimental.internal + +import org.gradle.api.Project +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension +import org.jetbrains.kotlin.gradle.plugin.KotlinTarget + +private const val SKIKO_ARTIFACT_PREFIX = "org.jetbrains.skiko:skiko" + +private class TargetType( + val id: String, + val presets: List +) + +private val TargetType.gradlePropertyName get() = "org.jetbrains.compose.experimental.$id.enabled" + +private val EXPERIMENTAL_TARGETS: Set = setOf( + TargetType("uikit", presets = listOf("iosSimulatorArm64", "iosArm64", "iosX64")), + TargetType("macos", presets = listOf("macosX64", "macosArm64")), + TargetType("jscanvas", presets = listOf("jsIr", "js")), +) + +private sealed interface CheckResult { + object Success : CheckResult + class Fail(val target: TargetType) : CheckResult +} + +internal fun Project.checkExperimentalTargetsWithSkikoIsEnabled() = afterEvaluate { + val mppExt = project.extensions.findByType(KotlinMultiplatformExtension::class.java) ?: return@afterEvaluate + val failedResults = mppExt.targets.map { checkTarget(it) } + .filterIsInstance() + .distinctBy { it.target } + + if (failedResults.isNotEmpty()) { + val ids = failedResults.map { it.target.id } + val msg = buildString { + appendLine("ERROR: Compose targets '$ids' are experimental and may have bugs!") + appendLine("But, if you still want to use them, add to gradle.properties:") + failedResults.forEach { + appendLine("${it.target.gradlePropertyName}=true") + } + } + + project.logger.error(msg) + error(msg) + } +} + +private fun Project.checkTarget(target: KotlinTarget): CheckResult { + val presetName = target.preset?.name ?: return CheckResult.Success + + val targetType = EXPERIMENTAL_TARGETS.firstOrNull { + it.presets.contains(presetName) + } ?: return CheckResult.Success + + val targetConfigurationNames = target.compilations.map { compilation -> + compilation.compileDependencyConfigurationName + } + + configurations.forEach { configuration -> + if (configuration.isCanBeResolved && configuration.name in targetConfigurationNames) { + val containsSkikoArtifact = configuration.resolvedConfiguration.resolvedArtifacts.any { + it.id.displayName.contains(SKIKO_ARTIFACT_PREFIX) + } + if (containsSkikoArtifact) { + if (project.findProperty(targetType.gradlePropertyName) != "true") { + return CheckResult.Fail(targetType) + } + } + } + } + return CheckResult.Success +}