From dff15a3d5997f92e5f2202071d5f204b0000ae4a Mon Sep 17 00:00:00 2001 From: Sergey Igushkin Date: Tue, 10 Oct 2017 21:49:05 +0300 Subject: [PATCH] Fix multiplatform projects communication broken if the plugin is loaded more than once in different class loaders. Issue #KT-20634 Fixed (cherry picked from commit c65f210) --- .../kotlin/gradle/MultiplatformGradleIT.kt | 37 +++++++++++++++++++ .../plugin/KotlinMultiplatformPlugin.kt | 12 ++++-- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MultiplatformGradleIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MultiplatformGradleIT.kt index a00f7d93f23..4230409e5c5 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MultiplatformGradleIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MultiplatformGradleIT.kt @@ -84,4 +84,41 @@ class MultiplatformGradleIT : BaseGradleIT() { } } } + + @Test + fun testSubprojectWithAnotherClassLoader() { + with(Project("multiplatformProject", GRADLE_VERSION)) { + setupWorkingDir() + + // Make sure there is a plugin applied with the plugins DSL, so that Gradle loads the + // plugins separately for the subproject, with a different class loader: + File(projectDir, "libJs/build.gradle").modify { + "plugins { id 'com.moowork.node' version '1.0.1' }" + "\n" + it + } + + // Remove the root project buildscript dependency, needed for the same purpose: + File(projectDir, "build.gradle").modify { + it.replace("classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:\$kotlin_version'", "") + .apply { assert(!equals(it)) } + } + + // Instead, add the dependencies directly to the subprojects buildscripts: + listOf("lib", "libJvm", "libJs").forEach { subDirectory -> + File(projectDir, "$subDirectory/build.gradle").modify { + """ + buildscript { + repositories { mavenLocal(); jcenter() } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${'$'}kotlin_version" + } + } + """.trimIndent() + "\n" + it + } + } + + build("build") { + assertSuccessful() + } + } + } } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinMultiplatformPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinMultiplatformPlugin.kt index f5eba3251b8..74e1ae6ea40 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinMultiplatformPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinMultiplatformPlugin.kt @@ -95,7 +95,7 @@ open class KotlinPlatformImplementationPluginBase(platformName: String) : Kotlin } commonProject.whenEvaluated { - if ((!commonProject.plugins.hasPlugin(KotlinPlatformCommonPlugin::class.java))) { + if (!commonProject.pluginManager.hasPlugin("kotlin-platform-common")) { throw GradleException( "Platform project $platformProject has an " + "'$EXPECTED_BY_CONFIG_NAME'${if (implementConfigurationIsUsed) "/'$IMPLEMENT_CONFIG_NAME'" else ""} " + @@ -115,7 +115,14 @@ open class KotlinPlatformImplementationPluginBase(platformName: String) : Kotlin } protected val SourceSet.kotlin: SourceDirectorySet? - get() = ((getConvention("kotlin") ?: getConvention("kotlin2js")) as? KotlinSourceSet)?.kotlin + get() { + // Access through reflection, because another project's KotlinSourceSet might be loaded + // by a different class loader: + val convention = (getConvention("kotlin") ?: getConvention("kotlin2js")) ?: return null + val kotlinSourceSetIface = convention.javaClass.interfaces.find { it.name == KotlinSourceSet::class.qualifiedName } + val getKotlin = kotlinSourceSetIface?.methods?.find { it.name == "getKotlin" } ?: return null + return getKotlin(convention) as? SourceDirectorySet + } companion object { @JvmStatic @@ -128,7 +135,6 @@ open class KotlinPlatformImplementationPluginBase(platformName: String) : Kotlin } } } - } open class KotlinPlatformJvmPlugin : KotlinPlatformImplementationPluginBase("jvm") {