From f10f69dd9b49c2c819b6fc5e7d05d9718f4cfb57 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Wed, 28 Dec 2016 17:48:59 +0100 Subject: [PATCH] =?UTF-8?q?ModuleRootManagerComponent=20=E2=80=94=20increm?= =?UTF-8?q?ent=20serialization=20modification=20count=20on=20project=20lib?= =?UTF-8?q?rary=20change=20(if=20used)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../intellij/roots/libraries/LibraryTest.java | 16 ++++++++++++- .../impl/ModuleRootManagerComponent.java | 23 +++++++++++++++---- .../impl/libraries/LibraryTableBase.java | 18 +++++++++++++-- 3 files changed, 50 insertions(+), 7 deletions(-) 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 db4059f329c2..6d58e29f7070 100644 --- a/java/java-tests/testSrc/com/intellij/roots/libraries/LibraryTest.java +++ b/java/java-tests/testSrc/com/intellij/roots/libraries/LibraryTest.java @@ -22,8 +22,10 @@ import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.NativeLibraryOrderRootType; import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.impl.ModuleRootManagerComponent; import com.intellij.openapi.roots.impl.libraries.LibraryEx; import com.intellij.openapi.roots.impl.libraries.LibraryTableBase; +import com.intellij.openapi.roots.impl.libraries.ProjectLibraryTable; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar; @@ -40,6 +42,8 @@ import org.jetbrains.annotations.NotNull; import java.util.Collection; import java.util.Collections; +import static com.intellij.testFramework.assertions.Assertions.assertThat; + /** * @author dsl */ @@ -71,8 +75,11 @@ public class LibraryTest extends ModuleRootManagerTestCase { } public void testLibrarySerialization() { + final long moduleModificationCount = ((ModuleRootManagerComponent)ModuleRootManager.getInstance(myModule)).getStateModificationCount(); Library library = PsiTestUtil.addProjectLibrary(myModule, "junit", Collections.singletonList(getJDomJar()), Collections.singletonList(getJDomSources())); + + assertThat(((ModuleRootManagerComponent)ModuleRootManager.getInstance(myModule)).getStateModificationCount()).isGreaterThan(moduleModificationCount); Element element = serialize(library); String classesUrl = getJDomJar().getUrl(); String sourcesUrl = getJDomSources().getUrl(); @@ -93,14 +100,21 @@ public class LibraryTest extends ModuleRootManagerTestCase { } public void testFindLibraryByNameAfterRename() { + final long moduleModificationCount = ((ModuleRootManagerComponent)ModuleRootManager.getInstance(myModule)).getStateModificationCount(); + ProjectLibraryTable table = (ProjectLibraryTable)getLibraryTable(); + final long projectLibraryModificationCount = table.getStateModificationCount(); Library a = createLibrary("a", null, null); - LibraryTable table = getLibraryTable(); LibraryTable.ModifiableModel model = table.getModifiableModel(); assertSame(a, table.getLibraryByName("a")); assertSame(a, model.getLibraryByName("a")); Library.ModifiableModel libraryModel = a.getModifiableModel(); libraryModel.setName("b"); commit(libraryModel); + + // module not marked as to save if project library modified, but module is not affected + assertThat(((ModuleRootManagerComponent)ModuleRootManager.getInstance(myModule)).getStateModificationCount()).isEqualTo(moduleModificationCount); + assertThat(table.getStateModificationCount()).isGreaterThan(projectLibraryModificationCount); + assertNull(table.getLibraryByName("a")); assertNull(model.getLibraryByName("a")); assertSame(a, table.getLibraryByName("b")); diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ModuleRootManagerComponent.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ModuleRootManagerComponent.java index 2f3ed88cd94e..042255e97504 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ModuleRootManagerComponent.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ModuleRootManagerComponent.java @@ -20,9 +20,13 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.module.impl.ModuleEx; import com.intellij.openapi.roots.impl.storage.ClassPathStorageUtil; import com.intellij.openapi.roots.impl.storage.ClasspathStorage; +import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager; +import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; +import java.util.List; + /** * @author yole */ @@ -58,11 +62,22 @@ public class ModuleRootManagerComponent extends ModuleRootManagerImpl implements @Override public long getStateModificationCount() { - long result = myModificationCount; Module module = getModule(); - if (module instanceof ModuleEx) { - result += ((ModuleEx)module).getOptionsModificationCount(); + if (!module.isLoaded() || !(module instanceof ModuleEx)) { + return myModificationCount; } - return result; + + final long[] result = {myModificationCount}; + result[0] += ((ModuleEx)module).getOptionsModificationCount(); + final List handledLibraryTables = new SmartList<>(); + getRootModel().orderEntries().forEachLibrary(library -> { + LibraryTable table = library.getTable(); + if (table instanceof PersistentStateComponentWithModificationTracker && !handledLibraryTables.contains(table.getTableLevel())) { + handledLibraryTables.add(table.getTableLevel()); + result[0] += ((PersistentStateComponentWithModificationTracker)table).getStateModificationCount(); + } + return true; + }); + return result[0]; } } diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryTableBase.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryTableBase.java index 6450d23b90d6..bc99590e17db 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryTableBase.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryTableBase.java @@ -19,7 +19,7 @@ package com.intellij.openapi.roots.impl.libraries; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.WriteAction; -import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.components.PersistentStateComponentWithModificationTracker; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.libraries.Library; @@ -40,12 +40,14 @@ import org.jetbrains.annotations.Nullable; import java.util.*; -public abstract class LibraryTableBase implements PersistentStateComponent, LibraryTable, Disposable { +public abstract class LibraryTableBase implements PersistentStateComponentWithModificationTracker, LibraryTable, Disposable { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.impl.libraries.LibraryTableBase"); private final EventDispatcher myDispatcher = EventDispatcher.create(Listener.class); private LibraryModel myModel = new LibraryModel(); private boolean myFirstLoad = true; + private volatile long myModificationCount; + @NotNull @Override public ModifiableModel getModifiableModel() { @@ -85,6 +87,11 @@ public abstract class LibraryTableBase implements PersistentStateComponent addedLibraries = ContainerUtil.newIdentityTroveSet(model.myLibraries); addedLibraries.removeAll(myModel.myLibraries); @@ -290,6 +302,8 @@ public abstract class LibraryTableBase implements PersistentStateComponent