GitOrigin-RevId: c1b463c720414d421a507729c9d8e33ce961b7da
This commit is contained in:
Vladimir Krivosheev
2025-05-20 20:56:36 +00:00
committed by intellij-monorepo-bot
parent 7354a4e504
commit 5b7e72ee8a
12 changed files with 117 additions and 108 deletions
@@ -1,7 +1,6 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.platform.backend.workspace
import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.openapi.project.Project
import com.intellij.platform.workspace.storage.EntityChange
import com.intellij.platform.workspace.storage.MutableEntityStorage
@@ -14,10 +13,6 @@ import org.jetbrains.annotations.ApiStatus
@ApiStatus.Internal
public interface BridgeInitializer {
public fun isEnabled(): Boolean
public fun initializeBridges(project: Project, changes: Map<Class<*>, List<EntityChange<*>>>, builder: MutableEntityStorage)
public companion object {
@JvmField
public val EP_NAME: ExtensionPointName<BridgeInitializer> = ExtensionPointName("com.intellij.workspace.bridgeInitializer")
}
public fun initializeBridges(project: Project, changes: Map<Class<*>, List<EntityChange<*>>>, builder: MutableEntityStorage)
}
@@ -201,4 +201,9 @@ public interface Module extends ComponentManager, AreaInstance, Disposable {
default boolean canStoreSettings() {
return true;
}
// not called for module on loading, only if module created after project opening
@ApiStatus.Internal
default void initNewlyAddedModule() {
}
}
@@ -28,7 +28,6 @@ import com.intellij.openapi.vfs.VirtualFile
import com.intellij.platform.project.registerNewProjectId
import com.intellij.platform.project.unregisterProjectId
import com.intellij.serviceContainer.*
import com.intellij.util.application
import com.intellij.util.messages.MessageBus
import kotlinx.coroutines.CoroutineScope
import org.jetbrains.annotations.NonNls
@@ -47,9 +46,11 @@ internal class DefaultProject : UserDataHolderBase(), Project, ComponentManagerE
LOG.assertTrue(!app.isDisposed(), "Application is being disposed!")
val project = DefaultProjectImpl(actualContainerInstance = this@DefaultProject)
val componentStoreFactory = app.service<ProjectStoreFactory>()
project.registerServiceInstance(serviceInterface = IComponentStore::class.java,
instance = componentStoreFactory.createDefaultProjectStore(project),
pluginDescriptor = ComponentManagerImpl.fakeCorePluginDescriptor)
project.registerServiceInstance(
serviceInterface = IComponentStore::class.java,
instance = componentStoreFactory.createDefaultProjectStore(project),
pluginDescriptor = ComponentManagerImpl.fakeCorePluginDescriptor,
)
// mark myDelegate as not disposed if someone cluelessly did Disposer.dispose(getDefaultProject())
Disposer.register(this@DefaultProject, this)
@@ -58,7 +59,7 @@ internal class DefaultProject : UserDataHolderBase(), Project, ComponentManagerE
public override fun init(project: Project) {
(project as DefaultProjectImpl).init()
application.messageBus.syncPublisher(DefaultProjectListener.TOPIC).defaultProjectImplCreated(project)
ApplicationManager.getApplication().messageBus.syncPublisher(DefaultProjectListener.TOPIC).defaultProjectImplCreated(project)
}
}
@@ -114,12 +115,11 @@ internal class DefaultProject : UserDataHolderBase(), Project, ComponentManagerE
unregisterProjectId(this)
}
override fun getMutableComponentContainer(): ComponentManager =
delegate.getComponentManagerImpl()
override fun getMutableComponentContainer(): ComponentManager = delegate.getComponentManagerImpl()
@TestOnly
fun disposeDefaultProjectAndCleanupComponentsForDynamicPluginTests() {
ApplicationManager.getApplication().runWriteAction(Runnable { Disposer.dispose(timedProject) })
ApplicationManager.getApplication().runWriteAction { Disposer.dispose(timedProject) }
}
private val delegate: Project
@@ -157,53 +157,65 @@ internal class DefaultProject : UserDataHolderBase(), Project, ComponentManagerE
override fun getCoroutineScope(): CoroutineScope = (ApplicationManager.getApplication() as ComponentManagerEx).getCoroutineScope()
override fun instanceCoroutineScope(pluginClass: Class<*>): CoroutineScope =
(delegate as ComponentManagerEx).getCoroutineScope()
override fun instanceCoroutineScope(pluginClass: Class<*>): CoroutineScope {
return (delegate as ComponentManagerEx).getCoroutineScope()
}
override fun unregisterComponent(componentKey: Class<*>): ComponentAdapter? =
(delegate as ComponentManagerEx).unregisterComponent(componentKey)
override fun unregisterComponent(componentKey: Class<*>): ComponentAdapter? {
return (delegate as ComponentManagerEx).unregisterComponent(componentKey)
}
override fun <T : Any> replaceServiceInstance(serviceInterface: Class<T>, instance: T, parentDisposable: Disposable) =
override fun <T : Any> replaceServiceInstance(serviceInterface: Class<T>, instance: T, parentDisposable: Disposable) {
(delegate as ComponentManagerEx).replaceServiceInstance(serviceInterface, instance, parentDisposable)
}
override fun instances(createIfNeeded: Boolean, filter: ((Class<*>) -> Boolean)?): Sequence<Any> =
(delegate as ComponentManagerEx).instances(createIfNeeded, filter)
override fun instances(createIfNeeded: Boolean, filter: ((Class<*>) -> Boolean)?): Sequence<Any> {
return (delegate as ComponentManagerEx).instances(createIfNeeded, filter)
}
override fun processAllImplementationClasses(processor: (Class<*>, PluginDescriptor?) -> Unit) =
override fun processAllImplementationClasses(processor: (Class<*>, PluginDescriptor?) -> Unit) {
(delegate as ComponentManagerEx).processAllImplementationClasses(processor)
}
override fun registerService(serviceInterface: Class<*>, implementation: Class<*>, pluginDescriptor: PluginDescriptor, override: Boolean, clientKind: ClientKind?) =
override fun registerService(serviceInterface: Class<*>, implementation: Class<*>, pluginDescriptor: PluginDescriptor, override: Boolean, clientKind: ClientKind?) {
(delegate as ComponentManagerEx).registerService(serviceInterface, implementation, pluginDescriptor, override, clientKind)
}
override fun <T : Any> getServiceByClassName(serviceClassName: String): T? =
(delegate as ComponentManagerEx).getServiceByClassName(serviceClassName)
override fun <T : Any> getServiceByClassName(serviceClassName: String): T? {
return (delegate as ComponentManagerEx).getServiceByClassName(serviceClassName)
}
override fun unloadServices(module: IdeaPluginDescriptor, services: List<ServiceDescriptor>) =
override fun unloadServices(module: IdeaPluginDescriptor, services: List<ServiceDescriptor>) {
(delegate as ComponentManagerEx).unloadServices(module, services)
}
override fun processAllHolders(processor: (String, Class<*>, PluginDescriptor?) -> Unit) =
override fun processAllHolders(processor: (String, Class<*>, PluginDescriptor?) -> Unit) {
(delegate as ComponentManagerEx).processAllHolders(processor)
}
override fun pluginCoroutineScope(pluginClassloader: ClassLoader): CoroutineScope =
(delegate as ComponentManagerEx).pluginCoroutineScope(pluginClassloader)
override fun pluginCoroutineScope(pluginClassloader: ClassLoader): CoroutineScope {
return (delegate as ComponentManagerEx).pluginCoroutineScope(pluginClassloader)
}
override fun stopServicePreloading() =
(delegate as ComponentManagerEx).stopServicePreloading()
override fun stopServicePreloading() = (delegate as ComponentManagerEx).stopServicePreloading()
override fun <T : Any> collectInitializedComponents(aClass: Class<T>): List<T> =
(delegate as ComponentManagerEx).collectInitializedComponents(aClass)
override fun <T : Any> collectInitializedComponents(aClass: Class<T>): List<T> {
return (delegate as ComponentManagerEx).collectInitializedComponents(aClass)
}
override fun debugString(): String =
(delegate as ComponentManagerEx).debugString()
override fun debugString(): String = (delegate as ComponentManagerEx).debugString()
override fun isServiceSuitable(descriptor: ServiceDescriptor): Boolean =
(delegate as ComponentManagerEx).isServiceSuitable(descriptor)
override fun isServiceSuitable(descriptor: ServiceDescriptor): Boolean {
return (delegate as ComponentManagerEx).isServiceSuitable(descriptor)
}
override fun <T : Any> registerServiceInstance(serviceInterface: Class<T>, instance: T, pluginDescriptor: PluginDescriptor) =
override fun <T : Any> registerServiceInstance(serviceInterface: Class<T>, instance: T, pluginDescriptor: PluginDescriptor) {
(delegate as ComponentManagerEx).registerServiceInstance(serviceInterface, instance, pluginDescriptor)
}
override fun getServiceImplementation(key: Class<*>): Class<*>? =
(delegate as ComponentManagerEx).getServiceImplementation(key)
override fun getServiceImplementation(key: Class<*>): Class<*>? {
return (delegate as ComponentManagerEx).getServiceImplementation(key)
}
override fun <T : Any> replaceComponentInstance(componentKey: Class<T>, componentImplementation: T, parentDisposable: Disposable?) {
(delegate as ComponentManagerEx).replaceComponentInstance(componentKey, componentImplementation, parentDisposable)
@@ -223,7 +235,7 @@ internal class DefaultProject : UserDataHolderBase(), Project, ComponentManagerE
@Suppress("DEPRECATION")
@Deprecated("")
override fun getComponent(name: String): com.intellij.openapi.components.BaseComponent? = delegate.getComponent(name)
override fun getComponent(name: String): BaseComponent? = delegate.getComponent(name)
override fun getActivityCategory(isExtension: Boolean): ActivityCategory {
return if (isExtension) ActivityCategory.PROJECT_EXTENSION else ActivityCategory.PROJECT_SERVICE
@@ -285,7 +297,7 @@ private class DefaultProjectImpl(
override fun dispose() {
super.dispose()
// possibly re-enable "the only project" optimization since we have closed the extra project.
(ProjectManager.getInstance() as ProjectManagerImpl).updateTheOnlyProjectField();
(ProjectManager.getInstance() as ProjectManagerImpl).updateTheOnlyProjectField()
unregisterProjectId(this)
}
@@ -1,50 +1,45 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.openapi.project.impl;
package com.intellij.openapi.project.impl
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.util.ModalityUiUtil;
import com.intellij.util.TimedReference;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectManager
import com.intellij.util.ModalityUiUtil
import com.intellij.util.TimedReference
import org.jetbrains.annotations.ApiStatus
@ApiStatus.Internal
public abstract class DefaultProjectTimed extends TimedReference<Project> {
private final @NotNull DefaultProject myParentDisposable;
abstract class DefaultProjectTimed internal constructor(
private val parentDisposable: DefaultProject,
) : TimedReference<Project>(parentDisposable) {
abstract fun compute(): Project
DefaultProjectTimed(@NotNull DefaultProject disposable) {
super(disposable);
myParentDisposable = disposable;
}
abstract fun init(project: Project)
abstract @NotNull Project compute();
abstract void init(@NotNull Project project);
@Override
public synchronized @NotNull Project get() {
Project value = super.get();
if (value == null) {
value = compute();
set(value);
init(value);
// disable "the only project" optimization since we have now more than one project.
// (even though the default project is not a real project, it can be used indirectly in e.g. "Settings|Code Style" code fragments PSI)
((ProjectManagerImpl)ProjectManager.getInstance()).updateTheOnlyProjectField();
@Synchronized
override fun get(): Project {
super.get()?.let {
return it
}
return value;
val value = compute()
set(value)
init(value)
// disable "the only project" optimization since we have now more than one project.
// (even though the default project is not a real project, it can be used indirectly in e.g. "Settings|Code Style" code fragments PSI)
(ProjectManager.getInstance() as ProjectManagerImpl).updateTheOnlyProjectField()
return value
}
@Override
public void dispose() {
override fun dispose() {
// project must be disposed in EDT in write action
Runnable doDispose = () -> {
if (isCached()) {
WriteAction.run(() -> super.dispose());
ModalityUiUtil.invokeLaterIfNeeded(ModalityState.nonModal(), parentDisposable.getDisposed()) {
if (isCached) {
ApplicationManager.getApplication().runWriteAction {
super.dispose()
}
}
};
ModalityUiUtil.invokeLaterIfNeeded(ModalityState.nonModal(), myParentDisposable.getDisposed(), doDispose);
}
}
}
@@ -1,4 +1,6 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
@file:Suppress("ReplacePutWithAssignment")
package com.intellij.openapi.project.impl
import com.intellij.configurationStore.StoreReloadManager
@@ -227,7 +229,7 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
override fun getDefaultProject(): Project {
LOG.assertTrue(!ApplicationManager.getApplication().isDisposed, "Application has already been disposed!")
// call instance method to reset timeout
// call an instance method to reset timeout
// re-instantiate if needed
val bus = defaultProject.messageBus
LOG.assertTrue(!bus.isDisposed)
@@ -7,10 +7,6 @@ import org.jetbrains.annotations.NotNull;
@ApiStatus.Internal
public interface ModuleEx extends Module {
// not called for module on loading, only if module created after project opening
default void initNewlyAddedModule() {
}
default void markAsLoaded() {
}
@@ -43,10 +43,12 @@ import org.jetbrains.annotations.TestOnly
import java.util.concurrent.atomic.AtomicLong
import kotlin.system.measureTimeMillis
private val EP_NAME: ExtensionPointName<BridgeInitializer> = ExtensionPointName("com.intellij.workspace.bridgeInitializer")
@ApiStatus.Internal
open class WorkspaceModelImpl : WorkspaceModelInternal {
val project: Project
val cs: CoroutineScope
private val project: Project
private val coroutineScope: CoroutineScope
@Volatile
var loadedFromCache: Boolean = false
@@ -85,7 +87,7 @@ open class WorkspaceModelImpl : WorkspaceModelInternal {
constructor(project: Project, cs: CoroutineScope, storage: ImmutableEntityStorage, virtualFileUrlManager: VirtualFileUrlManager) {
this.project = project
this.cs = cs
this.coroutineScope = cs
this.virtualFileManager = virtualFileUrlManager
entityStorage = VersionedEntityStorageImpl(storage)
unloadedEntitiesStorage = VersionedEntityStorageImpl(ImmutableEntityStorage.empty())
@@ -94,7 +96,7 @@ open class WorkspaceModelImpl : WorkspaceModelInternal {
constructor(project: Project, cs: CoroutineScope) {
this.project = project
this.cs = cs
this.coroutineScope = cs
this.virtualFileManager = IdeVirtualFileUrlManagerImpl(project.isCaseSensitive)
log.debug { "Loading workspace model" }
val start = Milliseconds.now()
@@ -412,7 +414,7 @@ open class WorkspaceModelImpl : WorkspaceModelInternal {
}
initializeBridgesTimeMs.addMeasuredTime {
for (bridgeInitializer in BridgeInitializer.EP_NAME.extensionList) {
for (bridgeInitializer in EP_NAME.extensionList) {
logErrorOnEventHandling {
if (bridgeInitializer.isEnabled()) {
bridgeInitializer.initializeBridges(project, change, builder)
@@ -446,7 +448,7 @@ open class WorkspaceModelImpl : WorkspaceModelInternal {
}
// We emit async changes before running other listeners under write action
cs.launch { updatesFlow.emit(change) }
coroutineScope.launch { updatesFlow.emit(change) }
onChangedTimeMs.addMeasuredTime { // Measure only the time of WorkspaceModelChangeListener
logErrorOnEventHandling {
@@ -1,5 +1,5 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
@file:Suppress("ReplacePutWithAssignment")
@file:Suppress("ReplacePutWithAssignment", "OVERRIDE_DEPRECATION")
package com.intellij.workspaceModel.ide.impl.legacyBridge.module
@@ -294,8 +294,9 @@ internal class ModifiableModuleModelBridgeImpl(
override fun getNewName(module: Module): String? = newNameToModule.getKeysByValue(module as ModuleBridge)?.single()
override fun getActualName(module: Module): String = getNewName(module) ?: module.name
override fun getModuleGroupPath(module: Module): Array<String>? =
ModuleManagerBridgeImpl.getModuleGroupPath(module, entityStorageOnDiff)
override fun getModuleGroupPath(module: Module): Array<String>? {
return ModuleManagerBridgeImpl.getModuleGroupPath(module as ModuleBridge, entityStorageOnDiff)
}
override fun hasModuleGroups(): Boolean = ModuleManagerBridgeImpl.hasModuleGroups(entityStorageOnDiff)
@@ -401,13 +401,14 @@ abstract class ModuleManagerBridgeImpl(
}
}
val workspaceModel = project.serviceAsync<WorkspaceModel>()
withContext(Dispatchers.EDT) {
edtWriteAction {
ProjectRootManagerEx.getInstanceEx(project).withRootsChange(RootsChangeRescanningInfo.NO_RESCAN_NEEDED).use {
WorkspaceModel.getInstance(project).updateProjectModel("Update unloaded modules") { builder ->
workspaceModel.updateProjectModel("Update unloaded modules") { builder ->
addAndRemoveModules(builder, moduleEntitiesToLoad, moduleEntitiesToUnload, unloadedEntityStorage)
}
(WorkspaceModel.getInstance(project) as WorkspaceModelInternal).updateUnloadedEntities("Update unloaded modules") { builder ->
(workspaceModel as WorkspaceModelInternal).updateUnloadedEntities("Update unloaded modules") { builder ->
addAndRemoveModules(builder, moduleEntitiesToUnload, moduleEntitiesToLoad, mainStorage)
}
}
@@ -528,11 +529,9 @@ abstract class ModuleManagerBridgeImpl(
return ModuleManager.getInstance(project) as ModuleManagerBridgeImpl
}
@JvmStatic
val EntityStorage.moduleMap: ExternalEntityMapping<ModuleBridge>
get() = getExternalMapping(MODULE_BRIDGE_MAPPING_ID)
@JvmStatic
val MutableEntityStorage.mutableModuleMap: MutableExternalEntityMapping<ModuleBridge>
get() = getMutableExternalMapping(MODULE_BRIDGE_MAPPING_ID)
@@ -635,11 +634,11 @@ abstract class ModuleManagerBridgeImpl(
private fun checkOldServices(plugins: List<IdeaPluginDescriptorImpl>) {
for (plugin in plugins) {
for (content in plugin.contentModules) {
checkModuleLevel(plugin, content.descriptor, forbid = false)
checkModuleLevel(plugin = plugin, child = content.descriptor, forbid = false)
}
executeRegisterTaskForOldContent(plugin) {
checkModuleLevel(plugin, it, forbid = true)
checkModuleLevel(plugin = plugin, child = it, forbid = true)
}
}
}
@@ -5,8 +5,10 @@ import com.intellij.java.workspace.entities.JavaSourceRootPropertiesEntity
import com.intellij.openapi.application.*
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.module.*
import com.intellij.openapi.module.impl.ModuleEx
import com.intellij.openapi.module.EmptyModuleType
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.module.ModuleType
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.rootManager
import com.intellij.openapi.roots.*
@@ -22,6 +24,7 @@ import com.intellij.platform.workspace.jps.JpsEntitySourceFactory
import com.intellij.platform.workspace.jps.JpsProjectFileEntitySource
import com.intellij.platform.workspace.jps.entities.*
import com.intellij.platform.workspace.jps.entities.DependencyScope
import com.intellij.platform.workspace.jps.serialization.impl.toConfigLocation
import com.intellij.platform.workspace.storage.ImmutableEntityStorage
import com.intellij.platform.workspace.storage.MutableEntityStorage
import com.intellij.platform.workspace.storage.VersionedStorageChange
@@ -38,7 +41,6 @@ import com.intellij.testFramework.workspaceModel.updateProjectModel
import com.intellij.util.io.write
import com.intellij.util.ui.UIUtil
import com.intellij.workspaceModel.ide.impl.WorkspaceModelInitialTestContent
import com.intellij.platform.workspace.jps.serialization.impl.toConfigLocation
import com.intellij.workspaceModel.ide.impl.legacyBridge.module.ModuleManagerBridgeImpl
import com.intellij.workspaceModel.ide.impl.legacyBridge.module.WEB_MODULE_ENTITY_TYPE_ID
import com.intellij.workspaceModel.ide.impl.legacyBridge.module.findModule
@@ -830,7 +832,7 @@ class ModuleBridgesTest {
val virtualFileUrlManager = workspaceModel.getVirtualFileUrlManager()
val newNonPersistentModule = moduleManager.newNonPersistentModule(moduleName, JAVA_MODULE_ENTITY_TYPE_ID_NAME)
assertFalse((newNonPersistentModule as ModuleEx).canStoreSettings())
assertFalse(newNonPersistentModule.canStoreSettings())
val moduleEntity = workspaceModel.currentSnapshot.entities(ModuleEntity::class.java).single()
assertEquals(NonPersistentEntitySource, moduleEntity.entitySource)
@@ -849,7 +851,7 @@ class ModuleBridgesTest {
}
val persistentModule = moduleManager.modules.single()
assertTrue((persistentModule as ModuleEx).canStoreSettings())
assertTrue(persistentModule.canStoreSettings())
assertSame(newNonPersistentModule, persistentModule)
}
@@ -71,7 +71,7 @@ public class GradleProjectResolverUtilTest {
}));
return Unit.INSTANCE;
}));
ModuleManagerBridgeImpl.getMutableModuleMap(builder).addMapping(moduleEntity, module);
ModuleManagerBridgeImpl.Companion.getMutableModuleMap(builder).addMapping(moduleEntity, module);
when(module.getEntityStorage()).thenReturn(new VersionedEntityStorageOnSnapshot(builder.toSnapshot()));
ExternalSystemModulePropertyManager modulePropertyManager = new ExternalSystemModulePropertyManagerBridge(module);
@@ -3,7 +3,6 @@ package com.jetbrains.python.defaultProjectAwareService;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.impl.ModuleEx;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -29,8 +28,9 @@ public final class PyDefaultProjectAwareServiceClasses<
* Use it for "getInstance" function. Returns module-level if module is set, app level otherwise
*/
public SERVICE getService(@Nullable Module module) {
if (module == null) return getAppService();
if (module instanceof ModuleEx && !((ModuleEx)module).canStoreSettings()) return getAppService();
if (module == null || !module.canStoreSettings()) {
return getAppService();
}
return getModuleService(module);
}