From 0039be6972e22f98ab9bcf9ce9d779e9b1207b61 Mon Sep 17 00:00:00 2001 From: Sergey Igushkin Date: Tue, 13 Mar 2018 20:56:59 +0300 Subject: [PATCH] Fix binary incompatibility with Android Gradle plugin 3.2.0-alpha06 Remove a non-reflective usage of the ResourceSet class, which has been moved to a different package between versions. Access it through reflection instead. This is a workaround. We can introduce a proper fix once we have a public API in the Android plugin. The test case that could detect the compatibility issue is `testAndroidExtensionsManyVariants` (it uses experimental Android extensions), but we did not run it with 3.2.0-alpha6. This commit adds a test class with the same tests for 3.2.0-alpha6. Issue #KT-23192 Fixed --- .../AbstractKotlinAndroidGradleTests.kt | 13 ++++++++--- .../testProject/AndroidProject/build.gradle | 2 +- .../plugin/android/Android25ProjectHandler.kt | 22 +++++++++++++------ 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt index 2b06543ab1e..8e86530253f 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt @@ -13,7 +13,15 @@ import java.io.File class KotlinAndroidGradleIT : AbstractKotlinAndroidGradleTests(gradleVersion = GradleVersionRequired.AtLeast("3.4"), androidGradlePluginVersion = "2.3.0") class KotlinAndroidWithJackGradleIT : AbstractKotlinAndroidWithJackGradleTests(androidGradlePluginVersion = "2.3.+") -class KotlinAndroid30GradleIT : AbstractKotlinAndroidGradleTests(gradleVersion = GradleVersionRequired.AtLeast("4.1"), androidGradlePluginVersion = "3.0.0-beta1") { +// TODO If we there is a way to fetch the latest Android plugin version, test against the latest version +class KotlinAndroid32GradleIT : KotlinAndroid3GradleIT(GradleVersionRequired.AtLeast("4.5"), "3.2.0-alpha06") + +class KotlinAndroid30GradleIT : KotlinAndroid3GradleIT(GradleVersionRequired.AtLeast("4.1"), "3.0.0") + +abstract class KotlinAndroid3GradleIT( + gradleVersionRequired: GradleVersionRequired, + androidGradlePluginVersion: String +) : AbstractKotlinAndroidGradleTests(gradleVersionRequired, androidGradlePluginVersion) { @Test fun testApplyWithFeaturePlugin() { @@ -314,5 +322,4 @@ abstract class AbstractKotlinAndroidWithJackGradleTests( assertContains("Kotlin Gradle plugin does not support the deprecated Jack toolchain") } } -} - +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidProject/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidProject/build.gradle index 92702183782..83c04d30ff9 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidProject/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidProject/build.gradle @@ -13,7 +13,7 @@ buildscript { allprojects { repositories { mavenLocal() - mavenCentral() + jcenter() maven { url 'https://maven.google.com' } } } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/agp25/kotlin/org/jetbrains/kotlin/gradle/plugin/android/Android25ProjectHandler.kt b/libraries/tools/kotlin-gradle-plugin/src/agp25/kotlin/org/jetbrains/kotlin/gradle/plugin/android/Android25ProjectHandler.kt index 20a5e6689e4..afe2566b854 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/agp25/kotlin/org/jetbrains/kotlin/gradle/plugin/android/Android25ProjectHandler.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/agp25/kotlin/org/jetbrains/kotlin/gradle/plugin/android/Android25ProjectHandler.kt @@ -4,7 +4,6 @@ import com.android.build.gradle.* import com.android.build.gradle.api.* import com.android.build.gradle.tasks.MergeResources import com.android.builder.model.SourceProvider -import com.android.ide.common.res2.ResourceSet import org.gradle.api.Project import org.gradle.api.file.FileCollection import org.gradle.api.tasks.compile.AbstractCompile @@ -120,7 +119,7 @@ class Android25ProjectHandler(kotlinConfigurationTools: KotlinConfigurationTools } override fun getResDirectories(variantData: BaseVariant): List { - return variantData.mergeResources?.computeResourceSetList0()?.flatMap { it.sourceFiles } ?: emptyList() + return variantData.mergeResources?.computeResourceSetList0() ?: emptyList() } private inner class KaptVariant(variantData: BaseVariant) : KaptVariantData(variantData) { @@ -143,17 +142,26 @@ class Android25ProjectHandler(kotlinConfigurationTools: KotlinConfigurationTools } } - //TODO once the Android plugin reaches its 3.0.0 release, consider compiling against it (remove the reflective call) - //TODO this is a private API for now - private fun MergeResources.computeResourceSetList0(): List? { + //TODO A public API is expected for this purpose. Once it is available, use the public API + private fun MergeResources.computeResourceSetList0(): List? { val computeResourceSetListMethod = MergeResources::class.java.declaredMethods .firstOrNull { it.name == "computeResourceSetList" && it.parameterCount == 0 } ?: return null val oldIsAccessible = computeResourceSetListMethod.isAccessible try { computeResourceSetListMethod.isAccessible = true - @Suppress("UNCHECKED_CAST") - return computeResourceSetListMethod.invoke(this) as? List + + val resourceSets = computeResourceSetListMethod.invoke(this) as? Iterable<*> + + return resourceSets + ?.mapNotNull { resourceSet -> + val getSourceFiles = resourceSet?.javaClass?.methods?.find { it.name == "getSourceFiles" && it.parameterCount == 0 } + val files = getSourceFiles?.invoke(resourceSet) + @Suppress("UNCHECKED_CAST") + files as? Iterable + } + ?.flatten() + } finally { computeResourceSetListMethod.isAccessible = oldIsAccessible }