From 3f182bfa57d1195194a321f5453d97d1f403e22c Mon Sep 17 00:00:00 2001 From: nik Date: Wed, 5 Feb 2020 09:45:05 +0300 Subject: [PATCH] [project model] keep custom library properties for libraries of unknown type (IDEA-219373) Such libraries now get special UnknownLibraryType and store the custom configuration as is. If a plugin supporting library type is dynamically loaded, UnknownLibraryType will be replaced by the real type. GitOrigin-RevId: 3529177996723e29d534e44925fc461f781b0f38 --- .../roots/libraries/LibraryPropertiesTest.kt | 61 +++++++++---- .../intellij/roots/libraries/LibraryTest.java | 13 +-- .../impl/libraries/LibraryKindLoader.java | 41 ++++++--- .../openapi/roots/libraries/LibraryType.java | 4 + .../roots/libraries/UnknownLibraryType.java | 41 +++++++++ .../roots/impl/libraries/LibraryEx.java | 4 +- .../openapi/roots/libraries/LibraryKind.java | 14 ++- .../roots/libraries/TemporaryLibraryKind.java | 11 +++ .../roots/impl/libraries/LibraryImpl.java | 45 ++++++++-- .../impl/libraries/UnknownLibraryKind.java | 89 +++++++++++++++++++ .../libraries/LegacyBridgeLibraryImpl.kt | 2 +- .../LegacyBridgeLibraryModifiableModelImpl.kt | 21 +++-- .../library/LibraryViaTypedEntity.kt | 3 +- 13 files changed, 294 insertions(+), 55 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/openapi/roots/libraries/UnknownLibraryType.java create mode 100644 platform/projectModel-api/src/com/intellij/openapi/roots/libraries/TemporaryLibraryKind.java create mode 100644 platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/UnknownLibraryKind.java diff --git a/java/java-tests/testSrc/com/intellij/roots/libraries/LibraryPropertiesTest.kt b/java/java-tests/testSrc/com/intellij/roots/libraries/LibraryPropertiesTest.kt index 8eab26fe1838..c7fe840d6bc2 100644 --- a/java/java-tests/testSrc/com/intellij/roots/libraries/LibraryPropertiesTest.kt +++ b/java/java-tests/testSrc/com/intellij/roots/libraries/LibraryPropertiesTest.kt @@ -5,6 +5,7 @@ import com.intellij.openapi.Disposable import com.intellij.openapi.application.runWriteAction import com.intellij.openapi.project.Project import com.intellij.openapi.roots.impl.libraries.LibraryEx +import com.intellij.openapi.roots.impl.libraries.UnknownLibraryKind import com.intellij.openapi.roots.libraries.* import com.intellij.openapi.roots.libraries.ui.LibraryEditorComponent import com.intellij.openapi.roots.libraries.ui.LibraryPropertiesEditor @@ -16,42 +17,64 @@ import javax.swing.JComponent class LibraryPropertiesTest : ModuleRootManagerTestCase() { fun `test set type and properties`() { - val table = LibraryTablesRegistrar.getInstance().getLibraryTable(myProject) registerLibraryType(testRootDisposable) + addLibrary("custom", "data") + val library = LibraryTablesRegistrar.getInstance().getLibraryTable(myProject).libraries.single() as LibraryEx + assertEquals(MockLibraryType.KIND, library.kind) + assertEquals("data", (library.properties as MockLibraryProperties).data) + assertEquals(""" + + + + + + + + """.trimIndent(), LibraryTest.serializeLibraries(myProject)) + } + + private fun addLibrary(name: String, data: String) { + val table = LibraryTablesRegistrar.getInstance().getLibraryTable(myProject) runWriteAction { val model = table.modifiableModel - val lib = model.createLibrary("custom", MockLibraryType.KIND) + val lib = model.createLibrary(name, MockLibraryType.KIND) val libModel = lib.modifiableModel as LibraryEx.ModifiableModelEx - libModel.properties = MockLibraryProperties("data") + libModel.properties = MockLibraryProperties(data) libModel.commit() model.commit() } - val library = table.libraries.single() as LibraryEx - assertEquals(MockLibraryType.KIND, library.kind) - assertEquals("data", (library.properties as MockLibraryProperties).data) } - fun `test clear kind when library type is unregistered`() { + fun `test convert to unknown library type is unregistered`() { val table = LibraryTablesRegistrar.getInstance().getLibraryTable(myProject) + runWithRegisteredType { + addLibrary("lib", "hello") + val library = table.libraries.single() as LibraryEx + assertEquals(MockLibraryType.KIND, library.kind) + assertEquals("hello", (library.properties as MockLibraryProperties).data) + } + + val unknown = table.libraries.single() as LibraryEx + assertInstanceOf(unknown.kind, UnknownLibraryKind::class.java) + assertNotNull(unknown.properties) + + runWithRegisteredType { + val library = table.libraries.single() as LibraryEx + assertEquals(MockLibraryType.KIND, library.kind) + assertEquals("hello", (library.properties as MockLibraryProperties).data) + } + } + + private fun runWithRegisteredType(action: () -> Unit) { val libraryTypeDisposable = Disposer.newDisposable() registerLibraryType(libraryTypeDisposable) try { - runWriteAction { - val model = table.modifiableModel - val lib = model.createLibrary("custom", MockLibraryType.KIND) - model.commit() - } - val library = table.libraries.single() as LibraryEx - assertEquals(MockLibraryType.KIND, library.kind) - assertEquals("default", (library.properties as MockLibraryProperties).data) + action() } finally { Disposer.dispose(libraryTypeDisposable) } - - val library = table.libraries.single() as LibraryEx - assertNull(library.kind) - assertNull(library.properties) } private fun registerLibraryType(disposable: Disposable) { diff --git a/java/java-tests/testSrc/com/intellij/roots/libraries/LibraryTest.java b/java/java-tests/testSrc/com/intellij/roots/libraries/LibraryTest.java index 48f546c7dd57..3d3366ff1628 100644 --- a/java/java-tests/testSrc/com/intellij/roots/libraries/LibraryTest.java +++ b/java/java-tests/testSrc/com/intellij/roots/libraries/LibraryTest.java @@ -7,6 +7,7 @@ import com.intellij.java.codeInsight.daemon.quickFix.OrderEntryTest; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.application.ex.PathManagerEx; +import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.*; import com.intellij.openapi.roots.impl.OrderEntryUtil; import com.intellij.openapi.roots.impl.libraries.LibraryEx; @@ -89,7 +90,7 @@ public class LibraryTest extends ModuleRootManagerTestCase { Collections.singletonList(LocalFileSystem.getInstance().refreshAndFindFileByIoFile(localJDomSources))); assertThat(ModuleRootManagerEx.getInstanceEx(myModule).getModificationCountForTests()).isGreaterThan(moduleModificationCount); - assertThat(serializeLibraries()).isEqualTo( + assertThat(serializeLibraries(myProject)).isEqualTo( "\n" + " \n" + " \n" + @@ -281,7 +282,7 @@ public class LibraryTest extends ModuleRootManagerTestCase { model.addRoot("file://native-lib-root", NativeLibraryOrderRootType.getInstance()); commit(model); - assertThat(serializeLibraries()).isEqualTo( + assertThat(serializeLibraries(myProject)).isEqualTo( "\n" + " \n" + " \n" + @@ -307,7 +308,7 @@ public class LibraryTest extends ModuleRootManagerTestCase { model.addJarDirectory("file://jar-dir-src", false, OrderRootType.SOURCES); commit(model); - assertThat(serializeLibraries()).isEqualTo( + assertThat(serializeLibraries(myProject)).isEqualTo( "\n" + " \n" + " \n" + @@ -324,12 +325,12 @@ public class LibraryTest extends ModuleRootManagerTestCase { ); } - private String serializeLibraries() { - StoreUtil.saveSettings(myProject); + static String serializeLibraries(Project project) { + StoreUtil.saveSettings(project); try { StringBuilder sb = new StringBuilder(); - Element root = JDOMUtil.load(new File(myProject.getProjectFilePath())); + Element root = JDOMUtil.load(new File(project.getProjectFilePath())); for (Element componentElement : root.getChildren("component")) { if ("libraryTable".equals(componentElement.getAttributeValue("name"))) { for (Element libraryElement : componentElement.getChildren("library")) { diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryKindLoader.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryKindLoader.java index a7614e51a42f..ce3253ea9e06 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryKindLoader.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryKindLoader.java @@ -2,6 +2,7 @@ package com.intellij.openapi.roots.impl.libraries; import com.intellij.ide.ApplicationInitializedListener; +import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.extensions.ExtensionPointListener; import com.intellij.openapi.extensions.PluginDescriptor; import com.intellij.openapi.module.Module; @@ -13,6 +14,8 @@ import com.intellij.openapi.roots.impl.OrderEntryUtil; import com.intellij.openapi.roots.libraries.*; import org.jetbrains.annotations.NotNull; +import java.util.function.Consumer; + public class LibraryKindLoader implements ApplicationInitializedListener { @Override public void componentsInitialized() { @@ -21,38 +24,56 @@ public class LibraryKindLoader implements ApplicationInitializedListener { LibraryType.EP_NAME.getExtensionList(); LibraryType.EP_NAME.addExtensionPointListener(new ExtensionPointListener>() { + @Override + public void extensionAdded(@NotNull LibraryType extension, @NotNull PluginDescriptor pluginDescriptor) { + WriteAction.run(() -> { + LibraryKind.registerKind(extension.getKind()); + processAllLibraries(library -> rememberKind(extension.getKind(), library)); + }); + } + @Override public void extensionRemoved(@NotNull LibraryType extension, @NotNull PluginDescriptor pluginDescriptor) { - clearKindInAllLibraries(extension.getKind()); + LibraryKind.unregisterKind(extension.getKind()); + processAllLibraries(library -> forgetKind(extension.getKind(), library)); } }, null); } - private static void clearKindInAllLibraries(@NotNull PersistentLibraryKind kind) { - clearKindInLibraries(kind, LibraryTablesRegistrar.getInstance().getLibraryTable()); + private static void processAllLibraries(@NotNull Consumer processor) { + processLibraries(LibraryTablesRegistrar.getInstance().getLibraryTable(), processor); for (LibraryTable table : LibraryTablesRegistrar.getInstance().getCustomLibraryTables()) { - clearKindInLibraries(kind, table); + processLibraries(table, processor); } for (Project project : ProjectManager.getInstance().getOpenProjects()) { - clearKindInLibraries(kind, LibraryTablesRegistrar.getInstance().getLibraryTable(project)); + processLibraries(LibraryTablesRegistrar.getInstance().getLibraryTable(project), processor); for (Module module : ModuleManager.getInstance(project).getModules()) { for (Library library : OrderEntryUtil.getModuleLibraries(ModuleRootManager.getInstance(module))) { - clearKind(kind, library); + processor.accept(library); } } } } - private static void clearKindInLibraries(@NotNull PersistentLibraryKind kind, @NotNull LibraryTable table) { + private static void processLibraries(@NotNull LibraryTable table, Consumer processor) { for (Library library : table.getLibraries()) { - clearKind(kind, library); + processor.accept(library); } } - private static void clearKind(@NotNull PersistentLibraryKind kind, @NotNull Library library) { + private static void forgetKind(@NotNull PersistentLibraryKind kind, @NotNull Library library) { if (kind.equals(((LibraryEx)library).getKind())) { LibraryEx.ModifiableModelEx model = (LibraryEx.ModifiableModelEx)library.getModifiableModel(); - model.clearKind(); + model.forgetKind(); + model.commit(); + } + } + + private static void rememberKind(@NotNull PersistentLibraryKind kind, @NotNull Library library) { + PersistentLibraryKind libraryKind = ((LibraryEx)library).getKind(); + if (libraryKind instanceof UnknownLibraryKind && libraryKind.getKindId().equals(kind.getKindId())) { + LibraryEx.ModifiableModelEx model = (LibraryEx.ModifiableModelEx)library.getModifiableModel(); + model.restoreKind(); model.commit(); } } diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/LibraryType.java b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/LibraryType.java index 9688fdb89447..22ac8f1676b9 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/LibraryType.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/LibraryType.java @@ -19,6 +19,7 @@ import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.impl.libraries.UnknownLibraryKind; import com.intellij.openapi.roots.libraries.ui.LibraryEditorComponent; import com.intellij.openapi.roots.libraries.ui.LibraryPropertiesEditor; import com.intellij.openapi.roots.libraries.ui.LibraryRootsComponentDescriptor; @@ -108,6 +109,9 @@ public abstract class LibraryType

extends LibraryPr return type; } } + if (kind instanceof UnknownLibraryKind) { + return new UnknownLibraryType((UnknownLibraryKind)kind); + } throw new IllegalArgumentException("Library with kind " + kind + " is not registered"); } } diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/UnknownLibraryType.java b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/UnknownLibraryType.java new file mode 100644 index 000000000000..d3c9a94a65a0 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/UnknownLibraryType.java @@ -0,0 +1,41 @@ +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.openapi.roots.libraries; + +import com.intellij.icons.AllIcons; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.impl.libraries.UnknownLibraryKind; +import com.intellij.openapi.roots.libraries.ui.LibraryEditorComponent; +import com.intellij.openapi.roots.libraries.ui.LibraryPropertiesEditor; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +public class UnknownLibraryType extends LibraryType { + public UnknownLibraryType(@NotNull UnknownLibraryKind kind) { + super(kind); + } + + @Override + public @Nullable String getCreateActionName() { + return null; + } + + @Override + public @Nullable NewLibraryConfiguration createNewLibrary(@NotNull JComponent parentComponent, + @Nullable VirtualFile contextDirectory, + @NotNull Project project) { + return null; + } + + @Override + public @Nullable LibraryPropertiesEditor createPropertiesEditor(@NotNull LibraryEditorComponent editorComponent) { + return null; + } + + @Override + public @Nullable Icon getIcon(UnknownLibraryKind.@Nullable UnknownLibraryProperties properties) { + return AllIcons.Nodes.Unknown; + } +} diff --git a/platform/projectModel-api/src/com/intellij/openapi/roots/impl/libraries/LibraryEx.java b/platform/projectModel-api/src/com/intellij/openapi/roots/impl/libraries/LibraryEx.java index 0c1afe5bddeb..268140229359 100644 --- a/platform/projectModel-api/src/com/intellij/openapi/roots/impl/libraries/LibraryEx.java +++ b/platform/projectModel-api/src/com/intellij/openapi/roots/impl/libraries/LibraryEx.java @@ -82,7 +82,9 @@ public interface LibraryEx extends Library { /** * Removes custom library kind and associated properties if any */ - void clearKind(); + void forgetKind(); + + void restoreKind(); /** * Add a URL to list of directories excluded from the library. The directory specified by {@code url} must be located under some diff --git a/platform/projectModel-api/src/com/intellij/openapi/roots/libraries/LibraryKind.java b/platform/projectModel-api/src/com/intellij/openapi/roots/libraries/LibraryKind.java index 8c2cac08d359..91fb93b46cf8 100644 --- a/platform/projectModel-api/src/com/intellij/openapi/roots/libraries/LibraryKind.java +++ b/platform/projectModel-api/src/com/intellij/openapi/roots/libraries/LibraryKind.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.roots.libraries; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -30,7 +31,8 @@ public class LibraryKind { */ public LibraryKind(@NotNull @NonNls String kindId) { myKindId = kindId; - if (ourAllKinds.containsKey(kindId)) { + LibraryKind kind = ourAllKinds.get(kindId); + if (kind != null && !(kind instanceof TemporaryLibraryKind)) { throw new IllegalArgumentException("Kind " + kindId + " is not unique"); } ourAllKinds.put(kindId, this); @@ -56,4 +58,14 @@ public class LibraryKind { public static LibraryKind findById(String kindId) { return ourAllKinds.get(kindId); } + + @ApiStatus.Internal + public static void unregisterKind(@NotNull LibraryKind kind) { + ourAllKinds.remove(kind.getKindId()); + } + + @ApiStatus.Internal + public static void registerKind(@NotNull LibraryKind kind) { + ourAllKinds.put(kind.getKindId(), kind); + } } diff --git a/platform/projectModel-api/src/com/intellij/openapi/roots/libraries/TemporaryLibraryKind.java b/platform/projectModel-api/src/com/intellij/openapi/roots/libraries/TemporaryLibraryKind.java new file mode 100644 index 000000000000..b374ee399ac0 --- /dev/null +++ b/platform/projectModel-api/src/com/intellij/openapi/roots/libraries/TemporaryLibraryKind.java @@ -0,0 +1,11 @@ +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.openapi.roots.libraries; + +import org.jetbrains.annotations.ApiStatus; + +/** + * Marker interface for implementations of {@link LibraryKind} which are used to replace the real implementations. For internal use only. + */ +@ApiStatus.Internal +public interface TemporaryLibraryKind { +} diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java index 7b8712b11f32..db4c2a050ec7 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java @@ -117,8 +117,12 @@ public class LibraryImpl extends TraceableDisposable implements LibraryEx.Modifi @Nullable private static PersistentLibraryKind findPersistentLibraryKind(@NotNull Element element) { String typeString = element.getAttributeValue(LIBRARY_TYPE_ATTR); + if (typeString == null) return null; LibraryKind kind = LibraryKind.findById(typeString); - if (kind != null && !(kind instanceof PersistentLibraryKind)) { + if (kind == null) { + return UnknownLibraryKind.getOrCreate(typeString); + } + if (!(kind instanceof PersistentLibraryKind)) { LOG.error("Cannot load non-persistable library kind: " + typeString); return null; } @@ -293,10 +297,16 @@ public class LibraryImpl extends TraceableDisposable implements LibraryEx.Modifi if (typeId == null) return; myKind = (PersistentLibraryKind) LibraryKind.findById(typeId); - if (myKind == null) return; + final Element propertiesElement = element.getChild(JpsLibraryTableSerializer.PROPERTIES_TAG); + if (myKind == null) { + myKind = UnknownLibraryKind.getOrCreate(typeId); + UnknownLibraryKind.UnknownLibraryProperties properties = new UnknownLibraryKind.UnknownLibraryProperties(); + properties.setConfiguration(propertiesElement); + myProperties = properties; + return; + } myProperties = myKind.createDefaultProperties(); - final Element propertiesElement = element.getChild(JpsLibraryTableSerializer.PROPERTIES_TAG); if (propertiesElement != null) { ComponentSerializationUtil.loadComponentState(myProperties, propertiesElement); } @@ -354,7 +364,7 @@ public class LibraryImpl extends TraceableDisposable implements LibraryEx.Modifi LOG.assertTrue(myProperties != null, "Properties is 'null' in library with kind " + myKind); final Object state = myProperties.getState(); if (state != null) { - final Element propertiesElement = XmlSerializer.serialize(state); + final Element propertiesElement = state instanceof Element ? ((Element)state).clone() : XmlSerializer.serialize(state); if (propertiesElement != null) { element.addContent(propertiesElement.setName(JpsLibraryTableSerializer.PROPERTIES_TAG)); } @@ -438,9 +448,30 @@ public class LibraryImpl extends TraceableDisposable implements LibraryEx.Modifi } @Override - public void clearKind() { - myKind = null; - myProperties = null; + public void forgetKind() { + if (myKind == null) return; + + myKind = UnknownLibraryKind.getOrCreate(myKind.getKindId()); + Object propertiesState = myProperties.getState(); + if (propertiesState != null) { + UnknownLibraryKind.UnknownLibraryProperties properties = new UnknownLibraryKind.UnknownLibraryProperties(); + properties.setConfiguration(XmlSerializer.serialize(propertiesState)); + myProperties = properties; + } + else { + myProperties = null; + } + } + + @Override + public void restoreKind() { + if (myKind == null || !(myKind instanceof UnknownLibraryKind)) return; + myKind = (PersistentLibraryKind)LibraryKind.findById(myKind.getKindId()); + Element configuration = ((UnknownLibraryKind.UnknownLibraryProperties)myProperties).getConfiguration(); + myProperties = myKind.createDefaultProperties(); + if (configuration != null) { + ComponentSerializationUtil.loadComponentState(myProperties, configuration); + } } @Override diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/UnknownLibraryKind.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/UnknownLibraryKind.java new file mode 100644 index 000000000000..225804ad63ad --- /dev/null +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/UnknownLibraryKind.java @@ -0,0 +1,89 @@ +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.openapi.roots.impl.libraries; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.roots.libraries.LibraryKind; +import com.intellij.openapi.roots.libraries.LibraryProperties; +import com.intellij.openapi.roots.libraries.PersistentLibraryKind; +import com.intellij.openapi.roots.libraries.TemporaryLibraryKind; +import com.intellij.openapi.util.JDOMUtil; +import org.jdom.Element; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class UnknownLibraryKind extends PersistentLibraryKind implements TemporaryLibraryKind { + private static final Logger LOG = Logger.getInstance(UnknownLibraryKind.class); + + private UnknownLibraryKind(@NotNull String kindId) { + super(kindId); + } + + @Override + public int hashCode() { + return getKindId().hashCode(); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof UnknownLibraryKind && ((UnknownLibraryKind)obj).getKindId().equals(getKindId()); + } + + @NotNull + @Override + public UnknownLibraryProperties createDefaultProperties() { + return new UnknownLibraryProperties(); + } + + public static UnknownLibraryKind getOrCreate(@NotNull String kindId) { + LibraryKind kind = LibraryKind.findById(kindId); + if (kind instanceof UnknownLibraryKind) { + return (UnknownLibraryKind)kind; + } + if (kind != null) { + LOG.error("Trying to create UnknownLibraryKind for known kind " + kind); + } + return new UnknownLibraryKind(kindId); + } + + @Override + public String toString() { + return "UnknownLibraryKind:" + getKindId(); + } + + public static class UnknownLibraryProperties extends LibraryProperties { + private Element myConfiguration; + + public Element getConfiguration() { + return myConfiguration; + } + + public void setConfiguration(Element configuration) { + myConfiguration = configuration; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof UnknownLibraryProperties)) return false; + Element configuration = ((UnknownLibraryProperties)obj).myConfiguration; + if (configuration == null && myConfiguration == null) return true; + if (configuration == null || myConfiguration == null) return false; + return JDOMUtil.areElementsEqual(myConfiguration, configuration); + } + + @Override + public int hashCode() { + return JDOMUtil.hashCode(myConfiguration, false); + } + + @Nullable + @Override + public Element getState() { + return myConfiguration; + } + + @Override + public void loadState(@NotNull Element state) { + myConfiguration = state; + } + } +} diff --git a/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/libraries/libraries/LegacyBridgeLibraryImpl.kt b/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/libraries/libraries/LegacyBridgeLibraryImpl.kt index ebbf8552f546..ca0b73a97f7f 100644 --- a/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/libraries/libraries/LegacyBridgeLibraryImpl.kt +++ b/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/libraries/libraries/LegacyBridgeLibraryImpl.kt @@ -117,7 +117,7 @@ internal class LegacyBridgeLibraryImpl( private val libraryEntity get() = entityStore.cachedValue(libraryEntityValue, entityId) - private val snapshotValue = CachedValueWithParameter { storage, id: LibraryId -> + internal val snapshotValue = CachedValueWithParameter { storage, id: LibraryId -> LibraryViaTypedEntity( libraryImpl = this, libraryEntity = storage.resolve(id) ?: object : LibraryEntity { diff --git a/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/libraries/libraries/LegacyBridgeLibraryModifiableModelImpl.kt b/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/libraries/libraries/LegacyBridgeLibraryModifiableModelImpl.kt index 82c46c06c4e3..1a6f502b217d 100644 --- a/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/libraries/libraries/LegacyBridgeLibraryModifiableModelImpl.kt +++ b/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/libraries/libraries/LegacyBridgeLibraryModifiableModelImpl.kt @@ -28,6 +28,7 @@ internal class LegacyBridgeLibraryModifiableModelImpl( ) : LegacyBridgeModifiableBase(diff), LibraryEx.ModifiableModelEx, LibraryEx, RootProvider { private var entityId = originalLibrarySnapshot.libraryEntity.persistentId() + private var reloadKind = false private val currentLibraryValue = CachedValue { storage -> val newLibrary = LibraryViaTypedEntity( @@ -79,9 +80,13 @@ internal class LegacyBridgeLibraryModifiableModelImpl( assertModelIsLive() modelIsCommittedOrDisposed = true - if (!isChanged) return - committer(this, diff) + if (reloadKind) { + originalLibrary.entityStore.clearCachedValue(originalLibrary.snapshotValue, originalLibrary.entityId) + } + if (isChanged) { + committer(this, diff) + } } private fun update(updater: ModifiableLibraryEntity.() -> Unit) { @@ -274,14 +279,12 @@ internal class LegacyBridgeLibraryModifiableModelImpl( } } - override fun clearKind() { - assertModelIsLive() - if (kind == null) return + override fun forgetKind() { + reloadKind = true + } - val properties = currentLibrary.libraryEntity.referrers(LibraryPropertiesEntity::library).toList() - for (propertiesEntity in properties) { - diff.removeEntity(propertiesEntity) - } + override fun restoreKind() { + reloadKind = true } private fun isUnderRoots(url: VirtualFileUrl, roots: Collection): Boolean { diff --git a/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/typedModel/library/LibraryViaTypedEntity.kt b/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/typedModel/library/LibraryViaTypedEntity.kt index 7ca2f188d9c3..386bac2928c6 100644 --- a/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/typedModel/library/LibraryViaTypedEntity.kt +++ b/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/typedModel/library/LibraryViaTypedEntity.kt @@ -7,6 +7,7 @@ import com.intellij.openapi.roots.OrderRootType import com.intellij.openapi.roots.ProjectModelExternalSource import com.intellij.openapi.roots.RootProvider import com.intellij.openapi.roots.impl.libraries.LibraryEx +import com.intellij.openapi.roots.impl.libraries.UnknownLibraryKind import com.intellij.openapi.roots.libraries.* import com.intellij.openapi.util.JDOMUtil import com.intellij.openapi.vfs.VirtualFile @@ -36,7 +37,7 @@ internal class LibraryViaTypedEntity(val libraryImpl: LegacyBridgeLibraryImpl, LegacyBridgeFileContainer(urls, jarDirs) } private val excludedRoots = if (libraryEntity.excludedRoots.isNotEmpty()) LegacyBridgeFileContainer(libraryEntity.excludedRoots, emptyList()) else null - private val libraryKind = libraryEntity.getCustomProperties()?.libraryType?.let { LibraryKind.findById(it) } as? PersistentLibraryKind<*> + private val libraryKind = libraryEntity.getCustomProperties()?.libraryType?.let { LibraryKind.findById(it) ?: UnknownLibraryKind.getOrCreate(it) } as? PersistentLibraryKind<*> private val properties = loadProperties() private fun loadProperties(): LibraryProperties<*>? {