diff --git a/platform/platform-impl/src/com/intellij/jps/impl/JpsIdePluginManagerImpl.java b/platform/platform-impl/src/com/intellij/jps/impl/JpsIdePluginManagerImpl.java index 659fad9edb7a..c63869113911 100644 --- a/platform/platform-impl/src/com/intellij/jps/impl/JpsIdePluginManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/jps/impl/JpsIdePluginManagerImpl.java @@ -7,8 +7,10 @@ import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.roots.ContentEntry; +import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.ModuleRootModificationUtil; import com.intellij.openapi.roots.SourceFolder; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.util.containers.ContainerUtil; import org.jdom.Element; @@ -32,6 +34,7 @@ import java.nio.charset.StandardCharsets; import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Predicate; public final class JpsIdePluginManagerImpl extends JpsPluginManager { private final List myExternalBuildPlugins = new CopyOnWriteArrayList<>(); @@ -89,6 +92,8 @@ public final class JpsIdePluginManagerImpl extends JpsPluginManager { } private void handlePluginRemoved(@NotNull PluginDescriptor pluginDescriptor) { + if (!myExternalBuildPlugins.contains(pluginDescriptor)) return; + Map, JpsModuleSourceRootPropertiesSerializer> removed = new HashMap<>(); for (JpsModelSerializerExtension extension : loadExtensions(JpsModelSerializerExtension.class)) { for (JpsModuleSourceRootPropertiesSerializer serializer : extension.getModuleSourceRootPropertiesSerializers()) { @@ -96,14 +101,7 @@ public final class JpsIdePluginManagerImpl extends JpsPluginManager { } } - if (myExternalBuildPlugins.remove(pluginDescriptor)) { - myModificationStamp.incrementAndGet(); - } - else{ - return; - } - - for (JpsModelSerializerExtension extension : loadExtensions(JpsModelSerializerExtension.class)) { + for (JpsModelSerializerExtension extension : loadExtensions(JpsModelSerializerExtension.class, descriptor -> !descriptor.equals(pluginDescriptor))) { for (JpsModuleSourceRootPropertiesSerializer serializer : extension.getModuleSourceRootPropertiesSerializers()) { removed.remove(serializer.getType()); } @@ -114,6 +112,8 @@ public final class JpsIdePluginManagerImpl extends JpsPluginManager { replaceWithUnknownRootType(project, removed.values()); } } + myExternalBuildPlugins.remove(pluginDescriptor); + myModificationStamp.incrementAndGet(); } private void handlePluginAdded(@NotNull PluginDescriptor pluginDescriptor) { @@ -183,24 +183,32 @@ public final class JpsIdePluginManagerImpl extends JpsPluginManager { serializers.put(ser.getTypeId(), ser); } for (Module module : ModuleManager.getInstance(project).getModules()) { - ModuleRootModificationUtil.modifyModel(module, model -> { - boolean shouldCommit = false; - for (ContentEntry contentEntry : model.getContentEntries()) { - for (SourceFolder folder : contentEntry.getSourceFolders()) { - if (folder.getRootType() instanceof UnknownSourceRootType) { - UnknownSourceRootType type = (UnknownSourceRootType)folder.getRootType(); - JpsModuleSourceRootPropertiesSerializer serializer = serializers.get(type.getUnknownTypeId()); - if (serializer != null) { - UnknownSourceRootTypeProperties properties = folder.getJpsElement().getProperties(type); - Object data = properties != null? properties.getPropertiesData() : null; - changeType(folder, serializer, data instanceof Element ? (Element)data : null); - shouldCommit = true; - } + Map, Element>> foldersToUpdate = new HashMap<>(); + for (ContentEntry contentEntry : ModuleRootManager.getInstance(module).getContentEntries()) { + for (SourceFolder folder : contentEntry.getSourceFolders()) { + if (folder.getRootType() instanceof UnknownSourceRootType) { + UnknownSourceRootType type = (UnknownSourceRootType)folder.getRootType(); + JpsModuleSourceRootPropertiesSerializer serializer = serializers.get(type.getUnknownTypeId()); + if (serializer != null) { + UnknownSourceRootTypeProperties properties = folder.getJpsElement().getProperties(type); + Object data = properties != null ? properties.getPropertiesData() : null; + foldersToUpdate.put(folder, new Pair<>(serializer, data instanceof Element ? (Element)data : null)); } } } - return shouldCommit; - }); + } + if (!foldersToUpdate.isEmpty()) { + ModuleRootModificationUtil.updateModel(module, model -> { + for (ContentEntry contentEntry : model.getContentEntries()) { + for (SourceFolder folder : contentEntry.getSourceFolders()) { + Pair, Element> pair = foldersToUpdate.get(folder); + if (pair != null) { + changeType(folder, pair.first, pair.second); + } + } + } + }); + } } } @@ -230,9 +238,16 @@ public final class JpsIdePluginManagerImpl extends JpsPluginManager { @NotNull @Override public Collection loadExtensions(@NotNull Class extensionClass) { + return loadExtensions(extensionClass, null); + } + + @NotNull + private Collection loadExtensions(@NotNull Class extensionClass, @Nullable Predicate filter) { Set loaders = new LinkedHashSet<>(); for (PluginDescriptor plugin : myExternalBuildPlugins) { - ContainerUtil.addIfNotNull(loaders, plugin.getPluginClassLoader()); + if (filter == null || filter.test(plugin)) { + ContainerUtil.addIfNotNull(loaders, plugin.getPluginClassLoader()); + } } if (loaders.isEmpty()) { loaders.add(getClass().getClassLoader()); diff --git a/platform/projectModel-api/src/com/intellij/openapi/roots/SourceFolder.java b/platform/projectModel-api/src/com/intellij/openapi/roots/SourceFolder.java index 9d73f6d6b7dc..2985f50dc820 100644 --- a/platform/projectModel-api/src/com/intellij/openapi/roots/SourceFolder.java +++ b/platform/projectModel-api/src/com/intellij/openapi/roots/SourceFolder.java @@ -57,5 +57,10 @@ public interface SourceFolder extends ContentFolder { @NotNull JpsModuleSourceRoot getJpsElement(); + /** + * This method is used internally to change root type to 'unknown' and back when the plugin which provides the custom root type is + * unloaded or loader. It isn't intended to change root type to some other arbitrary type and must not be used in plugins. + */ + @ApiStatus.Internal

void changeType(JpsModuleSourceRootType

newType, P properties); } diff --git a/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/intellij/LegacyBridgeModuleRootComponent.kt b/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/intellij/LegacyBridgeModuleRootComponent.kt index fd99cf9a883e..dca76002cdf9 100644 --- a/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/intellij/LegacyBridgeModuleRootComponent.kt +++ b/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/intellij/LegacyBridgeModuleRootComponent.kt @@ -53,11 +53,11 @@ class LegacyBridgeModuleRootComponent( init { MODULE_EXTENSION_NAME.getPoint(legacyBridgeModule).addExtensionPointListener(object : ExtensionPointListener { override fun extensionAdded(extension: ModuleExtension, pluginDescriptor: PluginDescriptor) { - modelValue.dropCache() + dropRootModelCache() } override fun extensionRemoved(extension: ModuleExtension, pluginDescriptor: PluginDescriptor) { - modelValue.dropCache() + dropRootModelCache() } }, false, null) } @@ -75,6 +75,10 @@ class LegacyBridgeModuleRootComponent( override fun dropCaches() { orderRootsCache.clearCache() + dropRootModelCache() + } + + internal fun dropRootModelCache() { modelValue.dropCache() } diff --git a/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/typedModel/module/ContentFolderViaTypedEntity.kt b/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/typedModel/module/ContentFolderViaTypedEntity.kt index 44c76f8de948..83a68fc42e4c 100644 --- a/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/typedModel/module/ContentFolderViaTypedEntity.kt +++ b/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/typedModel/module/ContentFolderViaTypedEntity.kt @@ -3,12 +3,14 @@ package com.intellij.workspace.legacyBridge.typedModel.module import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.roots.ContentFolder import com.intellij.openapi.roots.ExcludeFolder +import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.roots.SourceFolder import com.intellij.openapi.util.JDOMUtil import com.intellij.openapi.vfs.VirtualFile import com.intellij.workspace.api.* import com.intellij.workspace.legacyBridge.intellij.LegacyBridgeFilePointerProvider import com.intellij.workspace.legacyBridge.intellij.LegacyBridgeFilePointerScope +import com.intellij.workspace.legacyBridge.intellij.LegacyBridgeModuleRootComponent import org.jetbrains.jps.model.JpsElement import org.jetbrains.jps.model.JpsElementFactory import org.jetbrains.jps.model.java.JpsJavaExtensionService @@ -100,7 +102,7 @@ internal class SourceFolderViaTypedEntity(private val entry: ContentEntryViaType } override fun

changeType(newType: JpsModuleSourceRootType

, properties: P) { - sourceRootType = newType + (ModuleRootManager.getInstance(contentEntry.rootModel.module) as LegacyBridgeModuleRootComponent).dropRootModelCache() } override fun hashCode() = entry.url.hashCode() @@ -140,7 +142,6 @@ internal class SourceFolderViaTypedEntity(private val entry: ContentEntryViaType if (javaResourceRoot != null) return updater { diff -> - // TODO Replace TempEntitySource with sourceRootEntity.source diff.addJavaSourceRootEntity(sourceRootEntity, false, packagePrefix, sourceRootEntity.entitySource) } } else {