Skip to content

Commit bdad58c

Browse files
committed
Kotlin Facet: Support "implements" relation between modules
#KT-17593 Fixed
1 parent 8ebc766 commit bdad58c

File tree

6 files changed

+288
-4
lines changed

6 files changed

+288
-4
lines changed

idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleProjectResolverExtension.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ var DataNode<ModuleData>.coroutines
4545
by UserDataProperty(Key.create<String>("KOTLIN_COROUTINES"))
4646
var DataNode<ModuleData>.platformPluginId
4747
by UserDataProperty(Key.create<String>("PLATFORM_PLUGIN_ID"))
48+
var DataNode<ModuleData>.implementedModule
49+
by UserDataProperty(Key.create<DataNode<ModuleData>>("IMPLEMENTS"))
4850

4951
class KotlinGradleProjectResolverExtension : AbstractProjectResolverExtension() {
5052
override fun getToolingExtensionsClasses(): Set<Class<out Any>> {
@@ -68,6 +70,7 @@ class KotlinGradleProjectResolverExtension : AbstractProjectResolverExtension()
6870
ideModule.compilerArgumentsBySourceSet = gradleModel.compilerArgumentsBySourceSet
6971
ideModule.coroutines = gradleModel.coroutines
7072
ideModule.platformPluginId = gradleModel.platformPluginId
73+
ideModule.implementedModule = gradleModel.implements?.let { findModule(ideProject, it) }
7174

7275
super.populateModuleDependencies(gradleModule, ideModule, ideProject)
7376
}

idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleSourceSetDataService.kt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ import com.intellij.openapi.diagnostic.Logger
2020
import com.intellij.openapi.externalSystem.model.DataNode
2121
import com.intellij.openapi.externalSystem.model.ProjectKeys
2222
import com.intellij.openapi.externalSystem.model.project.LibraryData
23-
import com.intellij.openapi.externalSystem.model.project.LibraryDependencyData
2423
import com.intellij.openapi.externalSystem.model.project.ModuleData
2524
import com.intellij.openapi.externalSystem.model.project.ProjectData
2625
import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider
2726
import com.intellij.openapi.externalSystem.service.project.manage.AbstractProjectDataService
2827
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
2928
import com.intellij.openapi.module.Module
29+
import com.intellij.openapi.module.isQualifiedModuleNamesEnabled
3030
import com.intellij.openapi.project.Project
3131
import com.intellij.openapi.roots.OrderRootType
3232
import com.intellij.openapi.roots.impl.libraries.LibraryEx
@@ -192,9 +192,9 @@ private fun configureFacetByGradleModule(
192192
val kotlinFacet = ideModule.getOrCreateFacet(modelsProvider, false)
193193
kotlinFacet.configureFacet(compilerVersion, coroutinesProperty, platformKind, modelsProvider)
194194

195-
val sourceSetName = sourceSetNode?.data?.id?.let { it.substring(it.lastIndexOf(':') + 1) } ?: "main"
195+
val sourceSetName = sourceSetNode?.data?.id?.let { it.substring(it.lastIndexOf(':') + 1) }
196196

197-
val argsInfo = moduleNode.compilerArgumentsBySourceSet?.get(sourceSetName)
197+
val argsInfo = moduleNode.compilerArgumentsBySourceSet?.get(sourceSetName ?: "main")
198198
if (argsInfo != null) {
199199
val currentCompilerArguments = argsInfo.currentArguments
200200
val defaultCompilerArguments = argsInfo.defaultArguments
@@ -205,9 +205,18 @@ private fun configureFacetByGradleModule(
205205
adjustClasspath(kotlinFacet, dependencyClasspath)
206206
}
207207

208+
kotlinFacet.configuration.settings.implementedModuleName = getImplementedModuleName(moduleNode, sourceSetName)
209+
208210
return kotlinFacet
209211
}
210212

213+
private fun getImplementedModuleName(moduleNode: DataNode<ModuleData>, sourceSetName: String?): String? {
214+
val baseModuleName = moduleNode.implementedModule?.data?.internalName
215+
if (baseModuleName == null || sourceSetName == null) return baseModuleName
216+
val delimiter = if(isQualifiedModuleNamesEnabled()) "." else "_"
217+
return "$baseModuleName$delimiter$sourceSetName"
218+
}
219+
211220
private fun adjustClasspath(kotlinFacet: KotlinFacet, dependencyClasspath: List<String>) {
212221
if (dependencyClasspath.isEmpty()) return
213222
val arguments = kotlinFacet.configuration.settings.compilerArguments as? K2JVMCompilerArguments ?: return

idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleFacetImportTest.kt

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,6 +1319,265 @@ compileTestKotlin {
13191319
}
13201320
}
13211321

1322+
@Test
1323+
fun testImplementsDependency() {
1324+
createProjectSubFile(
1325+
"build.gradle",
1326+
"""
1327+
buildscript {
1328+
repositories {
1329+
mavenCentral()
1330+
maven {
1331+
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
1332+
}
1333+
}
1334+
dependencies {
1335+
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.0")
1336+
}
1337+
}
1338+
1339+
apply plugin: 'kotlin-platform-common'
1340+
1341+
repositories {
1342+
mavenCentral()
1343+
maven {
1344+
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
1345+
}
1346+
}
1347+
1348+
dependencies {
1349+
compile "org.jetbrains.kotlin:kotlin-stdlib-common:1.1.0"
1350+
}
1351+
1352+
""".trimIndent()
1353+
)
1354+
createProjectSubFile(
1355+
"settings.gradle",
1356+
"""
1357+
rootProject.name = 'MultiTest'
1358+
include 'MultiTest-jvm', 'MultiTest-js'
1359+
""".trimIndent()
1360+
)
1361+
createProjectSubFile(
1362+
"MultiTest-js/build.gradle",
1363+
"""
1364+
buildscript {
1365+
repositories {
1366+
mavenCentral()
1367+
maven {
1368+
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
1369+
}
1370+
}
1371+
dependencies {
1372+
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.0")
1373+
}
1374+
}
1375+
1376+
apply plugin: 'kotlin-platform-js'
1377+
1378+
repositories {
1379+
mavenCentral()
1380+
maven {
1381+
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
1382+
}
1383+
}
1384+
1385+
dependencies {
1386+
compile "org.jetbrains.kotlin:kotlin-stdlib-js:1.1.0"
1387+
implement project(":")
1388+
}
1389+
1390+
""".trimIndent()
1391+
)
1392+
createProjectSubFile(
1393+
"MultiTest-jvm/build.gradle",
1394+
"""
1395+
buildscript {
1396+
repositories {
1397+
mavenCentral()
1398+
maven {
1399+
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
1400+
}
1401+
}
1402+
dependencies {
1403+
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.0")
1404+
}
1405+
}
1406+
1407+
apply plugin: 'kotlin-platform-jvm'
1408+
1409+
repositories {
1410+
mavenCentral()
1411+
maven {
1412+
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
1413+
}
1414+
}
1415+
1416+
dependencies {
1417+
compile "org.jetbrains.kotlin:kotlin-stdlib:1.1.0"
1418+
implement project(":")
1419+
}
1420+
1421+
""".trimIndent()
1422+
)
1423+
1424+
importProject()
1425+
1426+
Assert.assertEquals("MultiTest_main", facetSettings("MultiTest-jvm_main").implementedModuleName)
1427+
Assert.assertEquals("MultiTest_test", facetSettings("MultiTest-jvm_test").implementedModuleName)
1428+
Assert.assertEquals("MultiTest_main", facetSettings("MultiTest-js_main").implementedModuleName)
1429+
Assert.assertEquals("MultiTest_test", facetSettings("MultiTest-js_test").implementedModuleName)
1430+
}
1431+
1432+
@Test
1433+
fun testImplementsDependencyWithCustomSourceSets() {
1434+
createProjectSubFile(
1435+
"build.gradle",
1436+
"""
1437+
buildscript {
1438+
repositories {
1439+
mavenCentral()
1440+
maven {
1441+
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
1442+
}
1443+
}
1444+
dependencies {
1445+
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.0")
1446+
}
1447+
}
1448+
1449+
apply plugin: 'kotlin-platform-common'
1450+
1451+
sourceSets {
1452+
myMain {
1453+
kotlin {
1454+
srcDir 'src'
1455+
}
1456+
}
1457+
myTest {
1458+
kotlin {
1459+
srcDir 'test'
1460+
}
1461+
}
1462+
}
1463+
1464+
repositories {
1465+
mavenCentral()
1466+
maven {
1467+
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
1468+
}
1469+
}
1470+
1471+
dependencies {
1472+
compile "org.jetbrains.kotlin:kotlin-stdlib-common:1.1.0"
1473+
}
1474+
1475+
""".trimIndent()
1476+
)
1477+
createProjectSubFile(
1478+
"settings.gradle",
1479+
"""
1480+
rootProject.name = 'MultiTest'
1481+
include 'MultiTest-jvm', 'MultiTest-js'
1482+
""".trimIndent()
1483+
)
1484+
createProjectSubFile(
1485+
"MultiTest-js/build.gradle",
1486+
"""
1487+
buildscript {
1488+
repositories {
1489+
mavenCentral()
1490+
maven {
1491+
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
1492+
}
1493+
}
1494+
dependencies {
1495+
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.0")
1496+
}
1497+
}
1498+
1499+
apply plugin: 'kotlin-platform-js'
1500+
1501+
sourceSets {
1502+
myMain {
1503+
kotlin {
1504+
srcDir 'src'
1505+
}
1506+
}
1507+
myTest {
1508+
kotlin {
1509+
srcDir 'test'
1510+
}
1511+
}
1512+
}
1513+
1514+
repositories {
1515+
mavenCentral()
1516+
maven {
1517+
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
1518+
}
1519+
}
1520+
1521+
dependencies {
1522+
compile "org.jetbrains.kotlin:kotlin-stdlib-js:1.1.0"
1523+
implement project(":")
1524+
}
1525+
1526+
""".trimIndent()
1527+
)
1528+
createProjectSubFile(
1529+
"MultiTest-jvm/build.gradle",
1530+
"""
1531+
buildscript {
1532+
repositories {
1533+
mavenCentral()
1534+
maven {
1535+
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
1536+
}
1537+
}
1538+
dependencies {
1539+
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.0")
1540+
}
1541+
}
1542+
1543+
apply plugin: 'kotlin-platform-jvm'
1544+
1545+
sourceSets {
1546+
myMain {
1547+
kotlin {
1548+
srcDir 'src'
1549+
}
1550+
}
1551+
myTest {
1552+
kotlin {
1553+
srcDir 'test'
1554+
}
1555+
}
1556+
}
1557+
1558+
repositories {
1559+
mavenCentral()
1560+
maven {
1561+
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
1562+
}
1563+
}
1564+
1565+
dependencies {
1566+
compile "org.jetbrains.kotlin:kotlin-stdlib:1.1.0"
1567+
implement project(":")
1568+
}
1569+
1570+
""".trimIndent()
1571+
)
1572+
1573+
importProject()
1574+
1575+
Assert.assertEquals("MultiTest_myMain", facetSettings("MultiTest-jvm_myMain").implementedModuleName)
1576+
Assert.assertEquals("MultiTest_myTest", facetSettings("MultiTest-jvm_myTest").implementedModuleName)
1577+
Assert.assertEquals("MultiTest_myMain", facetSettings("MultiTest-js_myMain").implementedModuleName)
1578+
Assert.assertEquals("MultiTest_myTest", facetSettings("MultiTest-js_myTest").implementedModuleName)
1579+
}
1580+
13221581
private fun assertAllModulesConfigured() {
13231582
runReadAction {
13241583
for (moduleGroup in ModuleSourceRootMap(myProject).groupByBaseModules(myProject.allModules())) {

idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinFacetSettings.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ class KotlinFacetSettings {
149149
LanguageFeature.State.ENABLED_WITH_ERROR, LanguageFeature.State.DISABLED -> CommonCompilerArguments.ERROR
150150
}
151151
}
152+
153+
var implementedModuleName: String? = null
152154
}
153155

154156
fun TargetPlatformKind<*>.createCompilerArguments(init: CommonCompilerArguments.() -> Unit = {}): CommonCompilerArguments {

idea/idea-jps-common/src/org/jetbrains/kotlin/config/facetSerialization.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import com.intellij.util.xmlb.SkipDefaultsSerializationFilter
2222
import com.intellij.util.xmlb.XmlSerializer
2323
import org.jdom.DataConversionException
2424
import org.jdom.Element
25+
import org.jdom.Text
2526
import org.jetbrains.kotlin.cli.common.arguments.*
2627
import org.jetbrains.kotlin.load.java.JvmAbi
2728
import java.lang.reflect.Modifier
@@ -95,6 +96,9 @@ private fun readV2AndLaterConfig(element: Element): KotlinFacetSettings {
9596
element.getAttributeValue("useProjectSettings")?.let { useProjectSettings = it.toBoolean() }
9697
val platformName = element.getAttributeValue("platform")
9798
val platformKind = TargetPlatformKind.ALL_PLATFORMS.firstOrNull { it.description == platformName } ?: TargetPlatformKind.DEFAULT_PLATFORM
99+
element.getChild("implements")?.let {
100+
implementedModuleName = (element.content.firstOrNull() as? Text)?.textTrim
101+
}
98102
element.getChild("compilerSettings")?.let {
99103
compilerSettings = CompilerSettings()
100104
XmlSerializer.deserializeInto(compilerSettings!!, it)
@@ -224,6 +228,9 @@ private fun KotlinFacetSettings.writeLatestConfig(element: Element) {
224228
if (!useProjectSettings) {
225229
element.setAttribute("useProjectSettings", useProjectSettings.toString())
226230
}
231+
implementedModuleName?.let {
232+
element.addContent(Element("implements").apply { addContent(it) })
233+
}
227234
compilerSettings?.let { copyBean(it) }?.let {
228235
it.convertPathsToSystemIndependent()
229236
buildChildElement(element, "compilerSettings", it, filter)

idea/kotlin-gradle-tooling/src/KotlinGradleModelBuilder.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ interface KotlinGradleModel : Serializable {
4747
val compilerArgumentsBySourceSet: CompilerArgumentsBySourceSet
4848
val coroutines: String?
4949
val platformPluginId: String?
50+
val implements: String?
5051
val transitiveCommonDependencies: Set<String>
5152
}
5253

@@ -55,6 +56,7 @@ class KotlinGradleModelImpl(
5556
override val compilerArgumentsBySourceSet: CompilerArgumentsBySourceSet,
5657
override val coroutines: String?,
5758
override val platformPluginId: String?,
59+
override val implements: String?,
5860
override val transitiveCommonDependencies: Set<String>
5961
) : KotlinGradleModel
6062

@@ -191,13 +193,15 @@ class KotlinGradleModelBuilder : ModelBuilderService {
191193
}
192194

193195
val platform = platformPluginId ?: pluginToPlatform.entries.singleOrNull { project.plugins.findPlugin(it.key) != null }?.value
194-
val transitiveCommon = getImplements(project)?.let { transitiveCommonDependencies(it) } ?: emptySet()
196+
val implementedProject = getImplements(project)
197+
val transitiveCommon = implementedProject?.let { transitiveCommonDependencies(it) } ?: emptySet()
195198

196199
return KotlinGradleModelImpl(
197200
kotlinPluginId != null || platformPluginId != null,
198201
compilerArgumentsBySourceSet,
199202
getCoroutines(project),
200203
platform,
204+
implementedProject?.pathOrName(),
201205
transitiveCommon
202206
)
203207
}

0 commit comments

Comments
 (0)