From db21bfe13b401332a1519988e04bf79ac07b1968 Mon Sep 17 00:00:00 2001 From: "sebastian.sellmair" Date: Wed, 10 Nov 2021 15:14:31 +0100 Subject: [PATCH] [Gradle, MPP] findAndroidTarget: Return null when missing Prior to this change a 'Collection is empty.' error was reported when the Android plugin was applied without an Android Kotlin target being registered. ^KT-41641 Verification Pending --- .../gradle/KT41641AbsentAndroidTarget.kt | 32 +++++++++++++++++++ .../internal/KotlinDependenciesManagement.kt | 10 +----- .../plugin/sources/KotlinDependencyScope.kt | 2 +- .../targets/android/FindAndroidTarget.kt | 20 ++++++++++++ 4 files changed, 54 insertions(+), 10 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/KT41641AbsentAndroidTarget.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/android/FindAndroidTarget.kt diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/KT41641AbsentAndroidTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/KT41641AbsentAndroidTarget.kt new file mode 100644 index 00000000000..2d56955a434 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/KT41641AbsentAndroidTarget.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2021 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. + */ + +@file:Suppress("FunctionName") + +package org.jetbrains.kotlin.gradle + +import com.android.build.gradle.LibraryExtension +import org.jetbrains.kotlin.gradle.targets.android.findAndroidTarget +import org.junit.Test +import kotlin.test.assertNull +import kotlin.test.assertSame + +class KT41641AbsentAndroidTarget : MultiplatformExtensionTest() { + @Test + fun `test android plugin without android target`() { + project.plugins.apply("kotlin-multiplatform") + project.plugins.apply("android-library") + + /* Arbitrary minimal Android setup */ + val android = project.extensions.getByName("android") as LibraryExtension + android.compileSdkVersion(30) + + kotlin.jvm() + + /* Previously failed with 'Collection is empty.' */ + assertNull(project.findAndroidTarget()) + assertSame(kotlin.android(), project.findAndroidTarget()) + } +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinDependenciesManagement.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinDependenciesManagement.kt index 7b0cd2b9868..9c96ae69d3d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinDependenciesManagement.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinDependenciesManagement.kt @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope import org.jetbrains.kotlin.gradle.plugin.sources.resolveAllDependsOnSourceSets import org.jetbrains.kotlin.gradle.plugin.sources.sourceSetDependencyConfigurationByScope import org.jetbrains.kotlin.gradle.plugin.sources.withAllDependsOnSourceSets +import org.jetbrains.kotlin.gradle.targets.android.findAndroidTarget import org.jetbrains.kotlin.gradle.targets.jvm.JvmCompilationsTestRunSource import org.jetbrains.kotlin.gradle.tasks.locateTask import org.jetbrains.kotlin.gradle.testing.KotlinTaskTestRun @@ -207,15 +208,6 @@ private fun chooseAndAddStdlibDependency( } } -private fun Project.findAndroidTarget(): KotlinAndroidTarget? { - val kotlinExtension = project.kotlinExtension - return when (kotlinExtension) { - is KotlinMultiplatformExtension -> kotlinExtension.targets.withType(KotlinAndroidTarget::class.java).single() - is KotlinAndroidProjectExtension -> kotlinExtension.target - else -> null - } -} - private fun androidMainSourceSetName(project: Project): String { val target = project.findAndroidTarget() ?: error("No Android target found") return AbstractAndroidProjectHandler.kotlinSourceSetNameForAndroidSourceSet(target, "main") diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/KotlinDependencyScope.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/KotlinDependencyScope.kt index c5ce224f41c..17a568a7d66 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/KotlinDependencyScope.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/KotlinDependencyScope.kt @@ -58,4 +58,4 @@ internal fun Project.sourceSetMetadataConfigurationByScope(sourceSet: KotlinSour COMPILE_ONLY_SCOPE -> sourceSet.compileOnlyMetadataConfigurationName RUNTIME_ONLY_SCOPE -> sourceSet.runtimeOnlyMetadataConfigurationName } - ) \ No newline at end of file + ) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/android/FindAndroidTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/android/FindAndroidTarget.kt new file mode 100644 index 00000000000..395490f3728 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/android/FindAndroidTarget.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2021 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.targets.android + +import org.gradle.api.Project +import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension +import org.jetbrains.kotlin.gradle.dsl.kotlinExtension +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget + +internal fun Project.findAndroidTarget(): KotlinAndroidTarget? { + return when (val kotlinExtension = project.kotlinExtension) { + is KotlinMultiplatformExtension -> kotlinExtension.targets.withType(KotlinAndroidTarget::class.java).singleOrNull() + is KotlinAndroidProjectExtension -> kotlinExtension.target + else -> null + } +}