diff --git a/java/java-tests/testData/configurationStore/module-in-group/.idea/modules.xml b/java/java-tests/testData/configurationStore/module-in-group/.idea/modules.xml
new file mode 100644
index 000000000000..29c93685eefd
--- /dev/null
+++ b/java/java-tests/testData/configurationStore/module-in-group/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/java/java-tests/testData/configurationStore/module-in-group/foo/foo.iml b/java/java-tests/testData/configurationStore/module-in-group/foo/foo.iml
new file mode 100644
index 000000000000..70ec6cce375a
--- /dev/null
+++ b/java/java-tests/testData/configurationStore/module-in-group/foo/foo.iml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/java/configurationStore/LoadProjectTest.kt b/java/java-tests/testSrc/com/intellij/java/configurationStore/LoadProjectTest.kt
index 4e7a87d3216e..88e97ed58f3d 100644
--- a/java/java-tests/testSrc/com/intellij/java/configurationStore/LoadProjectTest.kt
+++ b/java/java-tests/testSrc/com/intellij/java/configurationStore/LoadProjectTest.kt
@@ -57,6 +57,16 @@ class LoadProjectTest : LoadProjectBase() {
}
}
+ @Test
+ fun `load module with group`() {
+ loadProjectAndCheckResults("module-in-group") { project ->
+ val module = ModuleManager.getInstance(project).modules.single()
+ assertThat(module.name).isEqualTo("foo")
+ assertThat(module.moduleTypeName).isEqualTo("EMPTY_MODULE")
+ assertThat(ModuleManager.getInstance(project).getModuleGroupPath(module)).containsExactly("group")
+ }
+ }
+
@Test
fun `load detached module`() {
loadProjectAndCheckResults("detached-module") { project ->
diff --git a/java/java-tests/testSrc/com/intellij/java/configurationStore/SaveProjectTest.kt b/java/java-tests/testSrc/com/intellij/java/configurationStore/SaveProjectTest.kt
index e422538f1294..82410410d0d8 100644
--- a/java/java-tests/testSrc/com/intellij/java/configurationStore/SaveProjectTest.kt
+++ b/java/java-tests/testSrc/com/intellij/java/configurationStore/SaveProjectTest.kt
@@ -43,6 +43,19 @@ class SaveProjectTest {
projectModel.baseProjectDir.root.assertMatches(directoryContentOf(testDataRoot.resolve("single-module")))
}
+ @Test
+ fun `save module with group`() = runBlocking {
+ val module = projectModel.createModule("foo")
+ runWriteActionAndWait {
+ val model = projectModel.moduleManager.modifiableModel
+ model.setModuleGroupPath(module, arrayOf("group"))
+ model.commit()
+ }
+
+ saveProjectState()
+ projectModel.baseProjectDir.root.assertMatches(directoryContentOf(testDataRoot.resolve("module-in-group")))
+ }
+
@Test
fun `save detached module`() = runBlocking {
projectModel.createModule("foo")
diff --git a/platform/workspaceModel/ide/src/com/intellij/workspaceModel/ide/impl/jps/serialization/ExternalModuleImlFileEntitiesSerializer.kt b/platform/workspaceModel/ide/src/com/intellij/workspaceModel/ide/impl/jps/serialization/ExternalModuleImlFileEntitiesSerializer.kt
index d17f6bdf041c..0685f8b5475d 100644
--- a/platform/workspaceModel/ide/src/com/intellij/workspaceModel/ide/impl/jps/serialization/ExternalModuleImlFileEntitiesSerializer.kt
+++ b/platform/workspaceModel/ide/src/com/intellij/workspaceModel/ide/impl/jps/serialization/ExternalModuleImlFileEntitiesSerializer.kt
@@ -109,7 +109,7 @@ internal class ExternalModuleListSerializer(private val externalStorageRoot: Vir
return "${entity.name}.xml"
}
- override fun createSerializer(internalSource: JpsFileEntitySource, fileUrl: VirtualFileUrl): JpsFileEntitiesSerializer {
+ override fun createSerializer(internalSource: JpsFileEntitySource, fileUrl: VirtualFileUrl, moduleGroup: String?): JpsFileEntitiesSerializer {
val fileName = PathUtil.getFileName(fileUrl.url)
val actualFileUrl = if (PathUtil.getFileExtension(fileName) == "iml") {
externalStorageRoot.append("modules/${fileName.substringBeforeLast('.')}.xml")
@@ -118,6 +118,6 @@ internal class ExternalModuleListSerializer(private val externalStorageRoot: Vir
fileUrl
}
val filePath = JpsPathUtil.urlToPath(fileUrl.filePath)
- return ExternalModuleImlFileEntitiesSerializer(ModulePath(filePath, null), actualFileUrl, internalSource)
+ return ExternalModuleImlFileEntitiesSerializer(ModulePath(filePath, moduleGroup), actualFileUrl, internalSource)
}
}
\ No newline at end of file
diff --git a/platform/workspaceModel/ide/src/com/intellij/workspaceModel/ide/impl/jps/serialization/JpsProjectEntitiesLoader.kt b/platform/workspaceModel/ide/src/com/intellij/workspaceModel/ide/impl/jps/serialization/JpsProjectEntitiesLoader.kt
index 56f6b30fb82c..e06510536cfc 100644
--- a/platform/workspaceModel/ide/src/com/intellij/workspaceModel/ide/impl/jps/serialization/JpsProjectEntitiesLoader.kt
+++ b/platform/workspaceModel/ide/src/com/intellij/workspaceModel/ide/impl/jps/serialization/JpsProjectEntitiesLoader.kt
@@ -14,7 +14,6 @@ import com.intellij.workspaceModel.storage.*
import com.intellij.workspaceModel.storage.bridgeEntities.LibraryTableId
import org.jdom.Element
import org.jetbrains.annotations.TestOnly
-import java.io.File
import java.nio.file.Path
object JpsProjectEntitiesLoader {
@@ -52,7 +51,7 @@ object JpsProjectEntitiesLoader {
builder: WorkspaceEntityStorageBuilder,
virtualFileManager: VirtualFileUrlManager) {
val reader = CachingJpsFileContentReader(configLocation.baseDirectoryUrlString)
- val serializer = ModuleListSerializerImpl.createModuleEntitiesSerializer(moduleFile.toVirtualFileUrl(virtualFileManager), source)
+ val serializer = ModuleListSerializerImpl.createModuleEntitiesSerializer(moduleFile.toVirtualFileUrl(virtualFileManager), null, source)
serializer.loadEntities(builder, reader, virtualFileManager)
}
diff --git a/platform/workspaceModel/ide/src/com/intellij/workspaceModel/ide/impl/jps/serialization/JpsProjectSerializersImpl.kt b/platform/workspaceModel/ide/src/com/intellij/workspaceModel/ide/impl/jps/serialization/JpsProjectSerializersImpl.kt
index 2c772acbd0d1..f0d4957af1d5 100644
--- a/platform/workspaceModel/ide/src/com/intellij/workspaceModel/ide/impl/jps/serialization/JpsProjectSerializersImpl.kt
+++ b/platform/workspaceModel/ide/src/com/intellij/workspaceModel/ide/impl/jps/serialization/JpsProjectSerializersImpl.kt
@@ -52,10 +52,10 @@ class JpsProjectSerializersImpl(directorySerializersFactories: List> = moduleSerializers.getKeysByValue(serializerFactory) ?: emptyList()
val oldFileUrls = oldSerializers.mapTo(HashSet()) { it.fileUrl }
- val newFileUrlsSet = newFileUrls.toSet()
+ val newFileUrlsSet = newFileUrls.mapTo(HashSet()) { it.first }
val obsoleteSerializersForFactory = oldSerializers.filter { it.fileUrl !in newFileUrlsSet }
obsoleteSerializersForFactory.forEach { moduleSerializers.remove(it, serializerFactory) }
- val newFileSerializersForFactory = newFileUrls.filter { it !in oldFileUrls }.map {
- serializerFactory.createSerializer(createFileInDirectorySource(it.parent!!, it.file!!.name), it)
+ val newFileSerializersForFactory = newFileUrls.filter { it.first !in oldFileUrls }.map {
+ serializerFactory.createSerializer(createFileInDirectorySource(it.first.parent!!, it.first.file!!.name), it.first, it.second)
}
newFileSerializersForFactory.associateWithTo(moduleSerializers) { serializerFactory }
obsoleteSerializers.addAll(obsoleteSerializersForFactory)
@@ -309,7 +309,7 @@ class JpsProjectSerializersImpl(directorySerializersFactories: List
if (moduleListSerializer.entitySourceFilter(source)) {
- val newSerializer = moduleListSerializer.createSerializer(internalSource, virtualFileManager.fromUrl(url))
+ val newSerializer = moduleListSerializer.createSerializer(internalSource, virtualFileManager.fromUrl(url), null)
fileSerializersByUrl.put(url, newSerializer)
moduleSerializers[newSerializer] = moduleListSerializer
affectedFileFactories.add(moduleListSerializer)
diff --git a/platform/workspaceModel/ide/src/com/intellij/workspaceModel/ide/impl/jps/serialization/ModuleImlFileEntitiesSerializer.kt b/platform/workspaceModel/ide/src/com/intellij/workspaceModel/ide/impl/jps/serialization/ModuleImlFileEntitiesSerializer.kt
index d7aac72e1b6e..e4be1747257a 100644
--- a/platform/workspaceModel/ide/src/com/intellij/workspaceModel/ide/impl/jps/serialization/ModuleImlFileEntitiesSerializer.kt
+++ b/platform/workspaceModel/ide/src/com/intellij/workspaceModel/ide/impl/jps/serialization/ModuleImlFileEntitiesSerializer.kt
@@ -8,7 +8,6 @@ import com.intellij.openapi.module.impl.ModulePath
import com.intellij.openapi.project.ExternalStorageConfigurationManager
import com.intellij.openapi.roots.ExternalProjectSystemRegistry
import com.intellij.openapi.util.JDOMUtil
-import com.intellij.openapi.vfs.VfsUtil
import com.intellij.util.isEmpty
import com.intellij.workspaceModel.ide.JpsFileEntitySource
import com.intellij.workspaceModel.ide.JpsImportedEntitySource
@@ -61,7 +60,7 @@ internal open class ModuleImlFileEntitiesSerializer(internal val modulePath: Mod
val moduleEntity = loadModuleEntity(reader, builder, virtualFileManager)
if (moduleEntity != null) createFacetSerializer().loadFacetEntities(builder, moduleEntity, reader)
} else {
- val externalSerializer = externalModuleListSerializer?.createSerializer(internalEntitySource, fileUrl) as ModuleImlFileEntitiesSerializer?
+ val externalSerializer = externalModuleListSerializer?.createSerializer(internalEntitySource, fileUrl, modulePath.group) as ModuleImlFileEntitiesSerializer?
val moduleEntity = externalSerializer?.loadModuleEntity(reader, builder, virtualFileManager)
?: loadModuleEntity(reader, builder, virtualFileManager)
if (moduleEntity != null) {
@@ -83,6 +82,10 @@ internal open class ModuleImlFileEntitiesSerializer(internal val modulePath: Mod
val (externalSystemOptions, externalSystemId) = readExternalSystemOptions(reader, moduleOptions)
val entitySource = createEntitySource(externalSystemId)
val moduleEntity = builder.addModuleEntity(modulePath.moduleName, listOf(ModuleDependencyItem.ModuleSourceDependency), entitySource)
+ val moduleGroup = modulePath.group
+ if (moduleGroup != null) {
+ builder.addModuleGroupPathEntity(moduleGroup.split('/'), moduleEntity, entitySource)
+ }
val moduleType = moduleOptions["type"]
if (moduleType != null) {
@@ -560,10 +563,11 @@ internal open class ModuleListSerializerImpl(override val fileUrl: String,
: JpsModuleListSerializer {
companion object {
internal fun createModuleEntitiesSerializer(fileUrl: VirtualFileUrl,
+ moduleGroup: String?,
source: JpsFileEntitySource,
externalModuleListSerializer: JpsModuleListSerializer? = null,
externalStorageConfigurationManager: ExternalStorageConfigurationManager? = null) =
- ModuleImlFileEntitiesSerializer(ModulePath(JpsPathUtil.urlToPath(fileUrl.filePath), null), fileUrl, source,
+ ModuleImlFileEntitiesSerializer(ModulePath(JpsPathUtil.urlToPath(fileUrl.filePath), moduleGroup), fileUrl, source,
externalModuleListSerializer,
externalStorageConfigurationManager)
}
@@ -581,15 +585,14 @@ internal open class ModuleListSerializerImpl(override val fileUrl: String,
return "${entity.name}.iml"
}
- override fun createSerializer(internalSource: JpsFileEntitySource, fileUrl: VirtualFileUrl): JpsFileEntitiesSerializer {
- return createModuleEntitiesSerializer(fileUrl, internalSource, externalModuleListSerializer, externalStorageConfigurationManager)
+ override fun createSerializer(internalSource: JpsFileEntitySource, fileUrl: VirtualFileUrl, moduleGroup: String?): JpsFileEntitiesSerializer {
+ return createModuleEntitiesSerializer(fileUrl, moduleGroup, internalSource, externalModuleListSerializer, externalStorageConfigurationManager)
}
- override fun loadFileList(reader: JpsFileContentReader, virtualFileManager: VirtualFileUrlManager): List {
+ override fun loadFileList(reader: JpsFileContentReader, virtualFileManager: VirtualFileUrlManager): List> {
val moduleManagerTag = reader.loadComponent(fileUrl, componentName) ?: return emptyList()
return ModuleManagerImpl.getPathsToModuleFiles(moduleManagerTag).map {
- //todo load module groups
- Paths.get(it.path).toVirtualFileUrl(virtualFileManager)
+ Paths.get(it.path).toVirtualFileUrl(virtualFileManager) to it.group
}
}
diff --git a/platform/workspaceModel/ide/src/com/intellij/workspaceModel/ide/impl/jps/serialization/jpsFormatEntitiesSerialization.kt b/platform/workspaceModel/ide/src/com/intellij/workspaceModel/ide/impl/jps/serialization/jpsFormatEntitiesSerialization.kt
index 3c19bc93000f..cb171c21cdb6 100644
--- a/platform/workspaceModel/ide/src/com/intellij/workspaceModel/ide/impl/jps/serialization/jpsFormatEntitiesSerialization.kt
+++ b/platform/workspaceModel/ide/src/com/intellij/workspaceModel/ide/impl/jps/serialization/jpsFormatEntitiesSerialization.kt
@@ -70,8 +70,8 @@ interface JpsModuleListSerializer {
val entitySourceFilter: (EntitySource) -> Boolean
get() = { true }
- fun loadFileList(reader: JpsFileContentReader, virtualFileManager: VirtualFileUrlManager): List
- fun createSerializer(internalSource: JpsFileEntitySource, fileUrl: VirtualFileUrl): JpsFileEntitiesSerializer
+ fun loadFileList(reader: JpsFileContentReader, virtualFileManager: VirtualFileUrlManager): List>
+ fun createSerializer(internalSource: JpsFileEntitySource, fileUrl: VirtualFileUrl, moduleGroup: String?): JpsFileEntitiesSerializer
fun saveEntitiesList(entities: Sequence, writer: JpsFileContentWriter)
fun getFileName(entity: ModuleEntity): String
diff --git a/platform/workspaceModel/ide/tests/testSrc/com/intellij/workspaceModel/ide/impl/jps/serialization/jpsTestUtils.kt b/platform/workspaceModel/ide/tests/testSrc/com/intellij/workspaceModel/ide/impl/jps/serialization/jpsTestUtils.kt
index 7845ea2de890..ae9e0d4899fe 100644
--- a/platform/workspaceModel/ide/tests/testSrc/com/intellij/workspaceModel/ide/impl/jps/serialization/jpsTestUtils.kt
+++ b/platform/workspaceModel/ide/tests/testSrc/com/intellij/workspaceModel/ide/impl/jps/serialization/jpsTestUtils.kt
@@ -184,7 +184,7 @@ fun JpsProjectSerializersImpl.checkConsistency(projectBaseDirUrl: String, storag
assertEquals(url, fileSerializer.fileUrl)
val fileSerializers = moduleSerializers.getKeysByValue(fileSerializer) ?: emptyList()
val urlsFromFactory = fileSerializer.loadFileList(CachingJpsFileContentReader(projectBaseDirUrl), virtualFileManager)
- assertEquals(urlsFromFactory.map { it.url }.sorted(), fileSerializers.map { getNonNullActualFileUrl(it.internalEntitySource) }.sorted())
+ assertEquals(urlsFromFactory.map { it.first.url }.sorted(), fileSerializers.map { getNonNullActualFileUrl(it.internalEntitySource) }.sorted())
}
fileSerializersByUrl.keys.associateWith { fileSerializersByUrl.getValues(it) }.forEach { (url, serializers) ->