From 91f1bfac48efa8f2b288d3a8f77ffcae15a90f0c Mon Sep 17 00:00:00 2001 From: Mikhail Mazurkevich Date: Wed, 7 Sep 2022 18:55:57 +0400 Subject: [PATCH] [workspace model] IDEA-298714 Initialize facets only if loaded from cache GitOrigin-RevId: 0aae96135290d9c0546fec0ce4190ea58f080e0a --- .../facet/FacetEntityChangeListener.kt | 10 +++++++--- .../facet/FacetEntityContributor.kt | 6 ++---- .../legacyBridge/facet/FacetManagerBridge.kt | 8 ++------ .../module/ModuleBridgeLoaderService.kt | 8 ++++---- .../legacyBridge/WorkspaceFacetContributor.kt | 4 ++-- .../ide/impl/WorkspaceModelImpl.kt | 5 ++++- .../impl/WorkspaceModelInitialTestContent.kt | 8 ++++++++ .../module/ModuleManagerBridgeImpl.kt | 17 ++++++++--------- 8 files changed, 37 insertions(+), 29 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/facet/FacetEntityChangeListener.kt b/platform/lang-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/facet/FacetEntityChangeListener.kt index c6895813ec2d..a25d29c3761d 100644 --- a/platform/lang-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/facet/FacetEntityChangeListener.kt +++ b/platform/lang-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/facet/FacetEntityChangeListener.kt @@ -31,7 +31,7 @@ class FacetEntityChangeListener(private val project: Project): Disposable { init { if (!project.isDefault) { val busConnection = project.messageBus.connect(this) - WorkspaceModelTopics.getInstance(project).subscribeModuleBridgeInitializer(busConnection, object : WorkspaceModelChangeListener { + WorkspaceModelTopics.getInstance(project).subscribeAfterModuleLoading(busConnection, object : WorkspaceModelChangeListener { override fun beforeChanged(event: VersionedStorageChange) { WorkspaceFacetContributor.EP_NAME.extensions.forEach { facetBridgeContributor -> processBeforeChangeEvents(event, facetBridgeContributor) @@ -54,7 +54,9 @@ class FacetEntityChangeListener(private val project: Project): Disposable { val existingFacetBridge = event.storageAfter.facetMapping().getDataByEntity(change.entity) val facetBridge = if (existingFacetBridge == null) { val workspaceModel = WorkspaceModel.getInstance(project) - val newFacetBridge = workspaceFacetContributor.createFacetFromEntity(change.newEntity, project) + val moduleEntity = workspaceFacetContributor.getRelatedModuleEntity(change.newEntity) + val module = ModuleManager.getInstance(project).findModuleByName(moduleEntity.name) ?: error("Module bridge should be available") + val newFacetBridge = workspaceFacetContributor.createFacetFromEntity(change.newEntity, module) workspaceModel.updateProjectModelSilent { it.mutableFacetMapping().addMapping(change.newEntity, newFacetBridge) } @@ -85,7 +87,9 @@ class FacetEntityChangeListener(private val project: Project): Disposable { val existingFacetBridge = event.storageAfter.facetMapping().getDataByEntity(change.entity) val facet = if (existingFacetBridge == null) { val workspaceModel = WorkspaceModel.getInstance(project) - val newFacetBridge = workspaceFacetContributor.createFacetFromEntity(change.newEntity, project) + val moduleEntity = workspaceFacetContributor.getRelatedModuleEntity(change.newEntity) + val module = ModuleManager.getInstance(project).findModuleByName(moduleEntity.name) ?: error("Module bridge should be available") + val newFacetBridge = workspaceFacetContributor.createFacetFromEntity(change.newEntity, module) workspaceModel.updateProjectModelSilent { it.mutableFacetMapping().addMapping(change.newEntity, newFacetBridge) } diff --git a/platform/lang-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/facet/FacetEntityContributor.kt b/platform/lang-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/facet/FacetEntityContributor.kt index 60877822724f..89a16c521631 100644 --- a/platform/lang-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/facet/FacetEntityContributor.kt +++ b/platform/lang-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/facet/FacetEntityContributor.kt @@ -3,8 +3,7 @@ package com.intellij.workspaceModel.ide.impl.legacyBridge.facet import com.intellij.facet.Facet import com.intellij.facet.FacetManager -import com.intellij.openapi.module.ModuleManager -import com.intellij.openapi.project.Project +import com.intellij.openapi.module.Module import com.intellij.workspaceModel.ide.legacyBridge.WorkspaceFacetContributor import com.intellij.workspaceModel.storage.bridgeEntities.api.FacetEntity import com.intellij.workspaceModel.storage.bridgeEntities.api.ModuleEntity @@ -15,8 +14,7 @@ class FacetEntityContributor: WorkspaceFacetContributor { override fun getRootEntityByModuleEntity(moduleEntity: ModuleEntity): FacetEntity = error("Unsupported operation") - override fun createFacetFromEntity(entity: FacetEntity, project: Project): Facet<*> { - val module = ModuleManager.getInstance(project).findModuleByName(entity.module.name) ?: error("Module bridge should be available") + override fun createFacetFromEntity(entity: FacetEntity, module: Module): Facet<*> { val facetManagerBridge = FacetManager.getInstance(module) as FacetManagerBridge return facetManagerBridge.model.createFacet(entity) } diff --git a/platform/lang-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/facet/FacetManagerBridge.kt b/platform/lang-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/facet/FacetManagerBridge.kt index 013a2d150554..96925c5762cf 100644 --- a/platform/lang-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/facet/FacetManagerBridge.kt +++ b/platform/lang-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/facet/FacetManagerBridge.kt @@ -129,19 +129,15 @@ open class FacetModelBridge(private val moduleBridge: ModuleBridge) : FacetModel init { // Initialize facet bridges after loading from cache - fun createFacetBridgeIfNeeded(entity: WorkspaceEntity, facetContributor: WorkspaceFacetContributor, project: Project) { - updateDiffOrStorage{ this.getOrPutDataByEntity(entity) { facetContributor.createFacetFromEntity(entity, project) } } - } - moduleBridge.project val moduleEntity = moduleBridge.entityStorage.current.resolve(moduleBridge.moduleEntityId) ?: error("Module entity should be available") WorkspaceFacetContributor.EP_NAME.extensions.forEach { facetContributor -> if (facetContributor.rootEntityType != FacetEntity::class.java) { facetContributor.getRootEntityByModuleEntity(moduleEntity)?.let { - createFacetBridgeIfNeeded(it, facetContributor, moduleBridge.project) + updateDiffOrStorage{ this.getOrPutDataByEntity(it) { facetContributor.createFacetFromEntity(it, moduleBridge) }} } } else { - moduleEntity.facets.forEach { createFacetBridgeIfNeeded(it, facetContributor, moduleBridge.project) } + moduleEntity.facets.forEach { getOrCreateFacet(it) } } } } diff --git a/platform/lang-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/module/ModuleBridgeLoaderService.kt b/platform/lang-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/module/ModuleBridgeLoaderService.kt index 0170d75b95ad..b0c3d7fecb83 100644 --- a/platform/lang-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/module/ModuleBridgeLoaderService.kt +++ b/platform/lang-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/module/ModuleBridgeLoaderService.kt @@ -31,7 +31,7 @@ private class ModuleBridgeLoaderService : ProjectServiceContainerInitializedList private val LOG = logger() } - private suspend fun loadModules(project: Project, activity: Activity?) { + private suspend fun loadModules(project: Project, activity: Activity?, loadedFromCache: Boolean) { val componentManager = project as ComponentManagerEx val childActivity = activity?.startChild("modules instantiation") @@ -40,7 +40,7 @@ private class ModuleBridgeLoaderService : ProjectServiceContainerInitializedList val moduleManager = componentManager.getServiceAsync(ModuleManager::class.java).await() as ModuleManagerComponentBridge val entities = moduleManager.entityStore.current.entities(ModuleEntity::class.java) - moduleManager.loadModules(entities) + moduleManager.loadModules(entities, loadedFromCache) childActivity?.setDescription("modules count: ${moduleManager.modules.size}") childActivity?.end() @@ -62,7 +62,7 @@ private class ModuleBridgeLoaderService : ProjectServiceContainerInitializedList workspaceModel.ignoreCache() // sets `WorkspaceModelImpl#loadedFromCache` to `false` project.putUserData(PROJECT_LOADED_FROM_CACHE_BUT_HAS_NO_MODULES, true) } - loadModules(project, activity) + loadModules(project, activity, workspaceModel.loadedFromCache) } else { LOG.info("Workspace model loaded without cache. Loading real project state into workspace model. ${Thread.currentThread()}") @@ -71,7 +71,7 @@ private class ModuleBridgeLoaderService : ProjectServiceContainerInitializedList projectModelSynchronizer.applyLoadedStorage(storeToEntitySources) project.messageBus.syncPublisher(JpsProjectLoadedListener.LOADED).loaded() - loadModules(project, activity) + loadModules(project, activity, workspaceModel.loadedFromCache) } runActivity("tracked libraries setup") { diff --git a/platform/lang-impl/src/com/intellij/workspaceModel/ide/legacyBridge/WorkspaceFacetContributor.kt b/platform/lang-impl/src/com/intellij/workspaceModel/ide/legacyBridge/WorkspaceFacetContributor.kt index 793624662f07..f2745fdc0872 100644 --- a/platform/lang-impl/src/com/intellij/workspaceModel/ide/legacyBridge/WorkspaceFacetContributor.kt +++ b/platform/lang-impl/src/com/intellij/workspaceModel/ide/legacyBridge/WorkspaceFacetContributor.kt @@ -2,7 +2,7 @@ package com.intellij.workspaceModel.ide.legacyBridge import com.intellij.facet.Facet import com.intellij.openapi.extensions.ExtensionPointName -import com.intellij.openapi.project.Project +import com.intellij.openapi.module.Module import com.intellij.workspaceModel.storage.WorkspaceEntity import com.intellij.workspaceModel.storage.bridgeEntities.api.ModuleEntity import org.jetbrains.annotations.ApiStatus @@ -51,7 +51,7 @@ interface WorkspaceFacetContributor { /** * Method for creating [com.intellij.facet.Facet] from the given entity of root type */ - fun createFacetFromEntity(entity: T, project: Project): Facet<*> + fun createFacetFromEntity(entity: T, module: Module): Facet<*> /** * This field should be overridden if root entity can have children which changes can affect e.g. facet configuration diff --git a/platform/projectModel-impl/src/com/intellij/workspaceModel/ide/impl/WorkspaceModelImpl.kt b/platform/projectModel-impl/src/com/intellij/workspaceModel/ide/impl/WorkspaceModelImpl.kt index d2ad302afe82..3346bc4e2d5a 100644 --- a/platform/projectModel-impl/src/com/intellij/workspaceModel/ide/impl/WorkspaceModelImpl.kt +++ b/platform/projectModel-impl/src/com/intellij/workspaceModel/ide/impl/WorkspaceModelImpl.kt @@ -38,7 +38,10 @@ open class WorkspaceModelImpl(private val project: Project) : WorkspaceModel, Di val initialContent = WorkspaceModelInitialTestContent.pop() val cache = WorkspaceModelCache.getInstance(project) val projectEntities: MutableEntityStorage = when { - initialContent != null -> initialContent.toBuilder() + initialContent != null -> { + loadedFromCache = initialContent !== EntityStorageSnapshot.empty() + initialContent.toBuilder() + } cache != null -> { val activity = startActivity("cache loading") val previousStorage: MutableEntityStorage? diff --git a/platform/projectModel-impl/src/com/intellij/workspaceModel/ide/impl/WorkspaceModelInitialTestContent.kt b/platform/projectModel-impl/src/com/intellij/workspaceModel/ide/impl/WorkspaceModelInitialTestContent.kt index 8b4036611000..3ec0607ad98a 100644 --- a/platform/projectModel-impl/src/com/intellij/workspaceModel/ide/impl/WorkspaceModelInitialTestContent.kt +++ b/platform/projectModel-impl/src/com/intellij/workspaceModel/ide/impl/WorkspaceModelInitialTestContent.kt @@ -2,6 +2,7 @@ package com.intellij.workspaceModel.ide.impl import com.intellij.openapi.application.ApplicationManager +import com.intellij.util.PlatformUtils import com.intellij.workspaceModel.storage.EntityStorageSnapshot import org.jetbrains.annotations.TestOnly import java.util.concurrent.atomic.AtomicReference @@ -26,12 +27,19 @@ object WorkspaceModelInitialTestContent { error("Initial content was already registered") } + val previousPropertyValue = System.getProperty(PlatformUtils.PLATFORM_PREFIX_KEY) + if (storage !== EntityStorageSnapshot.empty()) { + System.setProperty(PlatformUtils.PLATFORM_PREFIX_KEY, PlatformUtils.IDEA_CE_PREFIX) + } hasInitialContent = true try { return block() } finally { hasInitialContent = false + if (storage !== EntityStorageSnapshot.empty()) { + System.setProperty(PlatformUtils.PLATFORM_PREFIX_KEY, previousPropertyValue) + } if (initialContent.getAndSet(null) != null) { error("Initial content was not used") } diff --git a/platform/projectModel-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/module/ModuleManagerBridgeImpl.kt b/platform/projectModel-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/module/ModuleManagerBridgeImpl.kt index c592287b8d40..9a7ae8f3fb07 100644 --- a/platform/projectModel-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/module/ModuleManagerBridgeImpl.kt +++ b/platform/projectModel-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/module/ModuleManagerBridgeImpl.kt @@ -78,7 +78,7 @@ abstract class ModuleManagerBridgeImpl(private val project: Project) : ModuleMan val entityStore = WorkspaceModel.getInstance(project).entityStorage - suspend fun loadModules(entities: Sequence) { + suspend fun loadModules(entities: Sequence, initializeFacets: Boolean) { val plugins = PluginManagerCore.getPluginSet().getEnabledModules() val corePlugin = plugins.firstOrNull { it.pluginId == PluginManagerCore.CORE_ID } val result = coroutineScope { @@ -130,13 +130,12 @@ abstract class ModuleManagerBridgeImpl(private val project: Project) : ModuleMan // Facets that are loaded from the cache do not generate "EntityAdded" event and aren't initialized // We initialize the facets manually here (after modules loading). - // - // Possible issue - if we'll initialize facets here and after that we'll get "EntityAdded" event, the facet will be initialized twice - // But 1. That seems impossible as we don't create facets before the modules are loaded 2. I hope that facets initialization is idempotent - blockingContext { - invokeLater { - for (module in modules) { - module.initFacets() + if (initializeFacets) { + blockingContext { + invokeLater { + for (module in modules) { + module.initFacets() + } } } } @@ -301,7 +300,7 @@ abstract class ModuleManagerBridgeImpl(private val project: Project) : ModuleMan } // todo why we load modules in a write action runBlocking { - loadModules(moduleEntitiesToLoad.asSequence()) + loadModules(moduleEntitiesToLoad.asSequence(), true) } } }