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)
This commit is contained in:
Sergey Igushkin
2017-10-10 21:49:05 +03:00
parent f211985332
commit dff15a3d59
2 changed files with 46 additions and 3 deletions
@@ -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()
}
}
}
}
@@ -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") {