Kotlin Facet: Support "implements" relation between modules
#KT-17593 Fixed
This commit is contained in:
+3
@@ -45,6 +45,8 @@ var DataNode<ModuleData>.coroutines
|
||||
by UserDataProperty(Key.create<String>("KOTLIN_COROUTINES"))
|
||||
var DataNode<ModuleData>.platformPluginId
|
||||
by UserDataProperty(Key.create<String>("PLATFORM_PLUGIN_ID"))
|
||||
var DataNode<ModuleData>.implementedModule
|
||||
by UserDataProperty(Key.create<DataNode<ModuleData>>("IMPLEMENTS"))
|
||||
|
||||
class KotlinGradleProjectResolverExtension : AbstractProjectResolverExtension() {
|
||||
override fun getToolingExtensionsClasses(): Set<Class<out Any>> {
|
||||
@@ -68,6 +70,7 @@ class KotlinGradleProjectResolverExtension : AbstractProjectResolverExtension()
|
||||
ideModule.compilerArgumentsBySourceSet = gradleModel.compilerArgumentsBySourceSet
|
||||
ideModule.coroutines = gradleModel.coroutines
|
||||
ideModule.platformPluginId = gradleModel.platformPluginId
|
||||
ideModule.implementedModule = gradleModel.implements?.let { findModule(ideProject, it) }
|
||||
|
||||
super.populateModuleDependencies(gradleModule, ideModule, ideProject)
|
||||
}
|
||||
|
||||
+12
-3
@@ -20,13 +20,13 @@ import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.externalSystem.model.DataNode
|
||||
import com.intellij.openapi.externalSystem.model.ProjectKeys
|
||||
import com.intellij.openapi.externalSystem.model.project.LibraryData
|
||||
import com.intellij.openapi.externalSystem.model.project.LibraryDependencyData
|
||||
import com.intellij.openapi.externalSystem.model.project.ModuleData
|
||||
import com.intellij.openapi.externalSystem.model.project.ProjectData
|
||||
import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.AbstractProjectDataService
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.isQualifiedModuleNamesEnabled
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.OrderRootType
|
||||
import com.intellij.openapi.roots.impl.libraries.LibraryEx
|
||||
@@ -192,9 +192,9 @@ private fun configureFacetByGradleModule(
|
||||
val kotlinFacet = ideModule.getOrCreateFacet(modelsProvider, false)
|
||||
kotlinFacet.configureFacet(compilerVersion, coroutinesProperty, platformKind, modelsProvider)
|
||||
|
||||
val sourceSetName = sourceSetNode?.data?.id?.let { it.substring(it.lastIndexOf(':') + 1) } ?: "main"
|
||||
val sourceSetName = sourceSetNode?.data?.id?.let { it.substring(it.lastIndexOf(':') + 1) }
|
||||
|
||||
val argsInfo = moduleNode.compilerArgumentsBySourceSet?.get(sourceSetName)
|
||||
val argsInfo = moduleNode.compilerArgumentsBySourceSet?.get(sourceSetName ?: "main")
|
||||
if (argsInfo != null) {
|
||||
val currentCompilerArguments = argsInfo.currentArguments
|
||||
val defaultCompilerArguments = argsInfo.defaultArguments
|
||||
@@ -205,9 +205,18 @@ private fun configureFacetByGradleModule(
|
||||
adjustClasspath(kotlinFacet, dependencyClasspath)
|
||||
}
|
||||
|
||||
kotlinFacet.configuration.settings.implementedModuleName = getImplementedModuleName(moduleNode, sourceSetName)
|
||||
|
||||
return kotlinFacet
|
||||
}
|
||||
|
||||
private fun getImplementedModuleName(moduleNode: DataNode<ModuleData>, sourceSetName: String?): String? {
|
||||
val baseModuleName = moduleNode.implementedModule?.data?.internalName
|
||||
if (baseModuleName == null || sourceSetName == null) return baseModuleName
|
||||
val delimiter = if(isQualifiedModuleNamesEnabled()) "." else "_"
|
||||
return "$baseModuleName$delimiter$sourceSetName"
|
||||
}
|
||||
|
||||
private fun adjustClasspath(kotlinFacet: KotlinFacet, dependencyClasspath: List<String>) {
|
||||
if (dependencyClasspath.isEmpty()) return
|
||||
val arguments = kotlinFacet.configuration.settings.compilerArguments as? K2JVMCompilerArguments ?: return
|
||||
|
||||
+259
@@ -1319,6 +1319,265 @@ compileTestKotlin {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testImplementsDependency() {
|
||||
createProjectSubFile(
|
||||
"build.gradle",
|
||||
"""
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.0")
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'kotlin-platform-common'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib-common:1.1.0"
|
||||
}
|
||||
|
||||
""".trimIndent()
|
||||
)
|
||||
createProjectSubFile(
|
||||
"settings.gradle",
|
||||
"""
|
||||
rootProject.name = 'MultiTest'
|
||||
include 'MultiTest-jvm', 'MultiTest-js'
|
||||
""".trimIndent()
|
||||
)
|
||||
createProjectSubFile(
|
||||
"MultiTest-js/build.gradle",
|
||||
"""
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.0")
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'kotlin-platform-js'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib-js:1.1.0"
|
||||
implement project(":")
|
||||
}
|
||||
|
||||
""".trimIndent()
|
||||
)
|
||||
createProjectSubFile(
|
||||
"MultiTest-jvm/build.gradle",
|
||||
"""
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.0")
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'kotlin-platform-jvm'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:1.1.0"
|
||||
implement project(":")
|
||||
}
|
||||
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
importProject()
|
||||
|
||||
Assert.assertEquals("MultiTest_main", facetSettings("MultiTest-jvm_main").implementedModuleName)
|
||||
Assert.assertEquals("MultiTest_test", facetSettings("MultiTest-jvm_test").implementedModuleName)
|
||||
Assert.assertEquals("MultiTest_main", facetSettings("MultiTest-js_main").implementedModuleName)
|
||||
Assert.assertEquals("MultiTest_test", facetSettings("MultiTest-js_test").implementedModuleName)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testImplementsDependencyWithCustomSourceSets() {
|
||||
createProjectSubFile(
|
||||
"build.gradle",
|
||||
"""
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.0")
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'kotlin-platform-common'
|
||||
|
||||
sourceSets {
|
||||
myMain {
|
||||
kotlin {
|
||||
srcDir 'src'
|
||||
}
|
||||
}
|
||||
myTest {
|
||||
kotlin {
|
||||
srcDir 'test'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib-common:1.1.0"
|
||||
}
|
||||
|
||||
""".trimIndent()
|
||||
)
|
||||
createProjectSubFile(
|
||||
"settings.gradle",
|
||||
"""
|
||||
rootProject.name = 'MultiTest'
|
||||
include 'MultiTest-jvm', 'MultiTest-js'
|
||||
""".trimIndent()
|
||||
)
|
||||
createProjectSubFile(
|
||||
"MultiTest-js/build.gradle",
|
||||
"""
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.0")
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'kotlin-platform-js'
|
||||
|
||||
sourceSets {
|
||||
myMain {
|
||||
kotlin {
|
||||
srcDir 'src'
|
||||
}
|
||||
}
|
||||
myTest {
|
||||
kotlin {
|
||||
srcDir 'test'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib-js:1.1.0"
|
||||
implement project(":")
|
||||
}
|
||||
|
||||
""".trimIndent()
|
||||
)
|
||||
createProjectSubFile(
|
||||
"MultiTest-jvm/build.gradle",
|
||||
"""
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.0")
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'kotlin-platform-jvm'
|
||||
|
||||
sourceSets {
|
||||
myMain {
|
||||
kotlin {
|
||||
srcDir 'src'
|
||||
}
|
||||
}
|
||||
myTest {
|
||||
kotlin {
|
||||
srcDir 'test'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:1.1.0"
|
||||
implement project(":")
|
||||
}
|
||||
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
importProject()
|
||||
|
||||
Assert.assertEquals("MultiTest_myMain", facetSettings("MultiTest-jvm_myMain").implementedModuleName)
|
||||
Assert.assertEquals("MultiTest_myTest", facetSettings("MultiTest-jvm_myTest").implementedModuleName)
|
||||
Assert.assertEquals("MultiTest_myMain", facetSettings("MultiTest-js_myMain").implementedModuleName)
|
||||
Assert.assertEquals("MultiTest_myTest", facetSettings("MultiTest-js_myTest").implementedModuleName)
|
||||
}
|
||||
|
||||
private fun assertAllModulesConfigured() {
|
||||
runReadAction {
|
||||
for (moduleGroup in ModuleSourceRootMap(myProject).groupByBaseModules(myProject.allModules())) {
|
||||
|
||||
@@ -149,6 +149,8 @@ class KotlinFacetSettings {
|
||||
LanguageFeature.State.ENABLED_WITH_ERROR, LanguageFeature.State.DISABLED -> CommonCompilerArguments.ERROR
|
||||
}
|
||||
}
|
||||
|
||||
var implementedModuleName: String? = null
|
||||
}
|
||||
|
||||
fun TargetPlatformKind<*>.createCompilerArguments(init: CommonCompilerArguments.() -> Unit = {}): CommonCompilerArguments {
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.util.xmlb.SkipDefaultsSerializationFilter
|
||||
import com.intellij.util.xmlb.XmlSerializer
|
||||
import org.jdom.DataConversionException
|
||||
import org.jdom.Element
|
||||
import org.jdom.Text
|
||||
import org.jetbrains.kotlin.cli.common.arguments.*
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import java.lang.reflect.Modifier
|
||||
@@ -95,6 +96,9 @@ private fun readV2AndLaterConfig(element: Element): KotlinFacetSettings {
|
||||
element.getAttributeValue("useProjectSettings")?.let { useProjectSettings = it.toBoolean() }
|
||||
val platformName = element.getAttributeValue("platform")
|
||||
val platformKind = TargetPlatformKind.ALL_PLATFORMS.firstOrNull { it.description == platformName } ?: TargetPlatformKind.DEFAULT_PLATFORM
|
||||
element.getChild("implements")?.let {
|
||||
implementedModuleName = (element.content.firstOrNull() as? Text)?.textTrim
|
||||
}
|
||||
element.getChild("compilerSettings")?.let {
|
||||
compilerSettings = CompilerSettings()
|
||||
XmlSerializer.deserializeInto(compilerSettings!!, it)
|
||||
@@ -224,6 +228,9 @@ private fun KotlinFacetSettings.writeLatestConfig(element: Element) {
|
||||
if (!useProjectSettings) {
|
||||
element.setAttribute("useProjectSettings", useProjectSettings.toString())
|
||||
}
|
||||
implementedModuleName?.let {
|
||||
element.addContent(Element("implements").apply { addContent(it) })
|
||||
}
|
||||
compilerSettings?.let { copyBean(it) }?.let {
|
||||
it.convertPathsToSystemIndependent()
|
||||
buildChildElement(element, "compilerSettings", it, filter)
|
||||
|
||||
@@ -47,6 +47,7 @@ interface KotlinGradleModel : Serializable {
|
||||
val compilerArgumentsBySourceSet: CompilerArgumentsBySourceSet
|
||||
val coroutines: String?
|
||||
val platformPluginId: String?
|
||||
val implements: String?
|
||||
val transitiveCommonDependencies: Set<String>
|
||||
}
|
||||
|
||||
@@ -55,6 +56,7 @@ class KotlinGradleModelImpl(
|
||||
override val compilerArgumentsBySourceSet: CompilerArgumentsBySourceSet,
|
||||
override val coroutines: String?,
|
||||
override val platformPluginId: String?,
|
||||
override val implements: String?,
|
||||
override val transitiveCommonDependencies: Set<String>
|
||||
) : KotlinGradleModel
|
||||
|
||||
@@ -191,13 +193,15 @@ class KotlinGradleModelBuilder : ModelBuilderService {
|
||||
}
|
||||
|
||||
val platform = platformPluginId ?: pluginToPlatform.entries.singleOrNull { project.plugins.findPlugin(it.key) != null }?.value
|
||||
val transitiveCommon = getImplements(project)?.let { transitiveCommonDependencies(it) } ?: emptySet()
|
||||
val implementedProject = getImplements(project)
|
||||
val transitiveCommon = implementedProject?.let { transitiveCommonDependencies(it) } ?: emptySet()
|
||||
|
||||
return KotlinGradleModelImpl(
|
||||
kotlinPluginId != null || platformPluginId != null,
|
||||
compilerArgumentsBySourceSet,
|
||||
getCoroutines(project),
|
||||
platform,
|
||||
implementedProject?.pathOrName(),
|
||||
transitiveCommon
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user