[workspace model] support loading module groups (IDEA-250171)

GitOrigin-RevId: 443a1fed3d6c6185b6e3af1c3084434827bfa24a
This commit is contained in:
Nikolay Chashnikov
2020-09-04 22:51:44 +03:00
committed by intellij-monorepo-bot
parent 893a246ce0
commit 0819bde368
10 changed files with 61 additions and 21 deletions

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/foo/foo.iml" filepath="$PROJECT_DIR$/foo/foo.iml" group="group" />
</modules>
</component>
</project>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="EMPTY_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@@ -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 ->

View File

@@ -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")

View File

@@ -109,7 +109,7 @@ internal class ExternalModuleListSerializer(private val externalStorageRoot: Vir
return "${entity.name}.xml"
}
override fun createSerializer(internalSource: JpsFileEntitySource, fileUrl: VirtualFileUrl): JpsFileEntitiesSerializer<ModuleEntity> {
override fun createSerializer(internalSource: JpsFileEntitySource, fileUrl: VirtualFileUrl, moduleGroup: String?): JpsFileEntitiesSerializer<ModuleEntity> {
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)
}
}

View File

@@ -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)
}

View File

@@ -52,10 +52,10 @@ class JpsProjectSerializersImpl(directorySerializersFactories: List<JpsDirectory
}
val enabledModuleListSerializers = moduleListSerializers.filter { enableExternalStorage || !it.isExternalStorage }
val moduleFiles = enabledModuleListSerializers.flatMap { it.loadFileList(reader, virtualFileManager) }
for (moduleFile in moduleFiles) {
for ((moduleFile, moduleGroup) in moduleFiles) {
val internalSource = createFileInDirectorySource(moduleFile.parent!!, moduleFile.file!!.name)
for (moduleListSerializer in enabledModuleListSerializers) {
val moduleSerializer = moduleListSerializer.createSerializer(internalSource, moduleFile)
val moduleSerializer = moduleListSerializer.createSerializer(internalSource, moduleFile, moduleGroup)
moduleSerializers[moduleSerializer] = moduleListSerializer
}
}
@@ -114,11 +114,11 @@ class JpsProjectSerializersImpl(directorySerializersFactories: List<JpsDirectory
val newFileUrls = serializerFactory.loadFileList(reader, virtualFileManager)
val oldSerializers: List<JpsFileEntitiesSerializer<*>> = 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<JpsDirectory
&& (ModuleEntity::class.java in entities || FacetEntity::class.java in entities)) {
moduleListSerializersByUrl.values.forEach { moduleListSerializer ->
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)

View File

@@ -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<ModuleEntity> {
return createModuleEntitiesSerializer(fileUrl, internalSource, externalModuleListSerializer, externalStorageConfigurationManager)
override fun createSerializer(internalSource: JpsFileEntitySource, fileUrl: VirtualFileUrl, moduleGroup: String?): JpsFileEntitiesSerializer<ModuleEntity> {
return createModuleEntitiesSerializer(fileUrl, moduleGroup, internalSource, externalModuleListSerializer, externalStorageConfigurationManager)
}
override fun loadFileList(reader: JpsFileContentReader, virtualFileManager: VirtualFileUrlManager): List<VirtualFileUrl> {
override fun loadFileList(reader: JpsFileContentReader, virtualFileManager: VirtualFileUrlManager): List<Pair<VirtualFileUrl, String?>> {
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
}
}

View File

@@ -70,8 +70,8 @@ interface JpsModuleListSerializer {
val entitySourceFilter: (EntitySource) -> Boolean
get() = { true }
fun loadFileList(reader: JpsFileContentReader, virtualFileManager: VirtualFileUrlManager): List<VirtualFileUrl>
fun createSerializer(internalSource: JpsFileEntitySource, fileUrl: VirtualFileUrl): JpsFileEntitiesSerializer<ModuleEntity>
fun loadFileList(reader: JpsFileContentReader, virtualFileManager: VirtualFileUrlManager): List<Pair<VirtualFileUrl, String?>>
fun createSerializer(internalSource: JpsFileEntitySource, fileUrl: VirtualFileUrl, moduleGroup: String?): JpsFileEntitiesSerializer<ModuleEntity>
fun saveEntitiesList(entities: Sequence<ModuleEntity>, writer: JpsFileContentWriter)
fun getFileName(entity: ModuleEntity): String

View File

@@ -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) ->