mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[workspace model] support loading and unloading plugins defining custom module root types
Since properties of custom source roots are stored in xml format in the workspace model entities it's enough to just drop caches if type is changed. However it's also required to unregister plugin which provides root type after root types are changed to 'unknown' (otherwise when ModifiableRootModel is created it'll already use UnknownSourceRootType for these roots), and collect affected roots before creating ModifiableRootModel when a new root type is registered. GitOrigin-RevId: b39e769a1a42b5119d3b7fff61156f7e9bf19882
This commit is contained in:
committed by
intellij-monorepo-bot
parent
82ee0cc693
commit
c570e228df
@@ -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<PluginDescriptor> 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<JpsModuleSourceRootType<?>, 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<SourceFolder, Pair<JpsModuleSourceRootPropertiesSerializer<?>, 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<JpsModuleSourceRootPropertiesSerializer<?>, 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 <T> Collection<T> loadExtensions(@NotNull Class<T> extensionClass) {
|
||||
return loadExtensions(extensionClass, null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private <T> Collection<T> loadExtensions(@NotNull Class<T> extensionClass, @Nullable Predicate<PluginDescriptor> filter) {
|
||||
Set<ClassLoader> 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());
|
||||
|
||||
@@ -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
|
||||
<P extends JpsElement> void changeType(JpsModuleSourceRootType<P> newType, P properties);
|
||||
}
|
||||
|
||||
+6
-2
@@ -53,11 +53,11 @@ class LegacyBridgeModuleRootComponent(
|
||||
init {
|
||||
MODULE_EXTENSION_NAME.getPoint(legacyBridgeModule).addExtensionPointListener(object : ExtensionPointListener<ModuleExtension?> {
|
||||
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()
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -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 <P : JpsElement> changeType(newType: JpsModuleSourceRootType<P>, 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 {
|
||||
|
||||
Reference in New Issue
Block a user