[workspace model] CPP-24452 Fix module serialization at external system folder

There were a couple of problems which were fixed within the ticket:
1. `CustomImlData` was not saved for modules stored at external system folder
2. `DummyParentEntitySource` was applied not only for module entity but for an other e.g `ModuleGroupPathEntity`,
`ModuleCustomImlDataEntity`... This entities without PersistentId which leads to incorrect behaviour at
replaceBySource and leaking DummyParentEntitySource` to the main store
3. There was a problem  that the system don't load `ExternalSystemOptions` if customRootsSerializer is exist
4. For Clion we should created `ExternalSystemModuleOptionsEntity` if we know the externalSystemId but project import
not started yet(for some reasons it may not start e.g due to the problems at Makefile)  and we should properly handle
serialization of such cases

GitOrigin-RevId: f045ceda298d61cf779091e2350827c7e0fb1ab2
This commit is contained in:
Mikhail Mazurkevich
2021-03-26 00:36:22 +03:00
committed by intellij-monorepo-bot
parent 878b959640
commit 68df252efd
4 changed files with 40 additions and 14 deletions

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="custom" version="4">
<module external.system.id="GRADLE" external.system.module.version="42.0" classpath="custom" version="4">
<component name="FacetManager">
<facet type="MockFacetId" name="MockFacet">
<configuration data="changed-data" />

View File

@@ -18,8 +18,15 @@ import com.intellij.packaging.artifacts.ArtifactManager
import com.intellij.packaging.impl.elements.FileCopyPackagingElement
import com.intellij.testFramework.*
import com.intellij.testFramework.configurationStore.copyFilesAndReloadProject
import com.intellij.workspaceModel.ide.JpsImportedEntitySource
import com.intellij.workspaceModel.ide.WorkspaceModel
import com.intellij.workspaceModel.ide.impl.jps.serialization.*
import com.intellij.workspaceModel.storage.DummyParentEntitySource
import com.intellij.workspaceModel.storage.bridgeEntities.ExternalSystemModuleOptionsEntity
import com.intellij.workspaceModel.storage.bridgeEntities.ModuleCustomImlDataEntity
import com.intellij.workspaceModel.storage.bridgeEntities.ModuleEntity
import org.assertj.core.api.Assertions.assertThat
import org.junit.Assume.assumeTrue
import org.junit.ClassRule
import org.junit.Rule
import org.junit.Test
@@ -120,7 +127,16 @@ class ReloadProjectTest {
copyFilesAndReload(project, "facet-in-module-with-custom-storage/update")
val changedFacet = FacetManager.getInstance(module).getFacetByType(MockFacetType.ID)!!
assertThat(changedFacet.configuration.data).isEqualTo("changed-data")
}
if (WorkspaceModel.isEnabled) {
val entityStorage = WorkspaceModel.getInstance(project).entityStorage.current
assumeTrue(entityStorage.entities(ModuleEntity::class.java).single().entitySource is DummyParentEntitySource)
assumeTrue(entityStorage.entities(ModuleCustomImlDataEntity::class.java).single().entitySource is JpsImportedEntitySource)
val moduleOptionsEntity = entityStorage.entities(ExternalSystemModuleOptionsEntity::class.java).single()
assertThat(moduleOptionsEntity.externalSystem).isEqualTo("GRADLE")
assertThat(moduleOptionsEntity.externalSystemModuleVersion).isEqualTo("42.0")
}
}
}
private suspend fun copyFilesAndReload(project: Project, relativePath: String) {

View File

@@ -85,9 +85,14 @@ internal class ExternalModuleImlFileEntitiesSerializer(modulePath: ModulePath,
saveOption("rootProjectPath", externalSystemOptions.rootProjectPath)
writer.saveComponent(fileUrlString, "ExternalSystem", componentTag)
}
if (moduleType != null) {
if (moduleType != null || customImlData?.customModuleOptions != null) {
val componentTag = JDomSerializationUtil.createComponentElement(DEPRECATED_MODULE_MANAGER_COMPONENT_NAME)
componentTag.addContent(Element("option").setAttribute("key", "type").setAttribute("value", moduleType))
if (moduleType != null) {
componentTag.addContent(Element("option").setAttribute("key", "type").setAttribute("value", moduleType))
}
customImlData?.customModuleOptions?.forEach{ (key, value) ->
componentTag.addContent(Element("option").setAttribute("key", key).setAttribute("value", value))
}
writer.saveComponent(fileUrlString, DEPRECATED_MODULE_MANAGER_COMPONENT_NAME, componentTag)
}
}

View File

@@ -15,10 +15,7 @@ import com.intellij.util.io.exists
import com.intellij.util.isEmpty
import com.intellij.workspaceModel.ide.*
import com.intellij.workspaceModel.ide.impl.virtualFile
import com.intellij.workspaceModel.storage.EntitySource
import com.intellij.workspaceModel.storage.WorkspaceEntity
import com.intellij.workspaceModel.storage.WorkspaceEntityStorage
import com.intellij.workspaceModel.storage.WorkspaceEntityStorageBuilder
import com.intellij.workspaceModel.storage.*
import com.intellij.workspaceModel.storage.bridgeEntities.*
import com.intellij.workspaceModel.storage.impl.url.toVirtualFileUrl
import com.intellij.workspaceModel.storage.url.VirtualFileUrl
@@ -99,7 +96,7 @@ internal open class ModuleImlFileEntitiesSerializer(internal val modulePath: Mod
val customDir: String?
val externalSystemOptions: Map<String?, String?>
val externalSystemId: String?
val entitySource = try {
val entitySourceForModuleAndOtherEntities = try {
moduleOptions = readModuleOptions(reader)
val pair = readExternalSystemOptions(reader, moduleOptions)
externalSystemOptions = pair.first
@@ -114,15 +111,23 @@ internal open class ModuleImlFileEntitiesSerializer(internal val modulePath: Mod
}
customDir = moduleOptions[JpsProjectLoader.CLASSPATH_DIR_ATTRIBUTE]
customRootsSerializer?.createEntitySource(fileUrl, internalEntitySource, customDir, virtualFileManager)
?: createEntitySource(externalSystemId)
val externalSystemEntitySource = createEntitySource(externalSystemId)
val moduleEntitySource = customRootsSerializer?.createEntitySource(fileUrl, internalEntitySource, customDir, virtualFileManager)
?: externalSystemEntitySource
if (moduleEntitySource is DummyParentEntitySource)
Pair(moduleEntitySource, externalSystemEntitySource)
else
Pair(moduleEntitySource, moduleEntitySource)
}
catch (e: JDOMException) {
builder.addModuleEntity(modulePath.moduleName, listOf(ModuleDependencyItem.ModuleSourceDependency), internalEntitySource)
throw e
}
val moduleEntity = builder.addModuleEntity(modulePath.moduleName, listOf(ModuleDependencyItem.ModuleSourceDependency), entitySource)
val moduleEntity = builder.addModuleEntity(modulePath.moduleName, listOf(ModuleDependencyItem.ModuleSourceDependency),
entitySourceForModuleAndOtherEntities.first)
val entitySource = entitySourceForModuleAndOtherEntities.second
val moduleGroup = modulePath.group
if (moduleGroup != null) {
builder.addModuleGroupPathEntity(moduleGroup.split('/'), moduleEntity, entitySource)
@@ -144,12 +149,12 @@ internal open class ModuleImlFileEntitiesSerializer(internal val modulePath: Mod
CUSTOM_MODULE_COMPONENT_SERIALIZER_EP.extensions().forEach {
it.loadComponent(builder, moduleEntity, reader, fileUrl, errorReporter, virtualFileManager)
}
// Don't forget to load external system options even if custome root serializer exist
loadExternalSystemOptions(builder, moduleEntity, reader, externalSystemOptions, externalSystemId, entitySource)
if (customRootsSerializer != null) {
customRootsSerializer.loadRoots(builder, moduleEntity, reader, customDir, fileUrl, internalModuleListSerializer, errorReporter, virtualFileManager)
}
else {
loadExternalSystemOptions(builder, moduleEntity, reader, externalSystemOptions, externalSystemId, entitySource)
val rootManagerElement = reader.loadComponent(fileUrl.url, MODULE_ROOT_MANAGER_COMPONENT_NAME, getBaseDirPath())?.clone()
if (rootManagerElement != null) {
loadRootManager(rootManagerElement, moduleEntity, builder, virtualFileManager)