From 6d5e2bcf49a4a49568cc839d5aa4d5bd9df69d2a Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 23 Jan 2017 15:58:15 +0100 Subject: [PATCH] IDEA-CR-17317 digest if module ext doesn't implement state tracker --- .../roots/impl/ModifiableModelCommitter.java | 3 ++ .../roots/impl/ModuleRootManagerImpl.java | 2 +- .../openapi/roots/impl/RootModelImpl.java | 49 +++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModifiableModelCommitter.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModifiableModelCommitter.java index d68016ec0c9b..7cdcdaee3cd6 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModifiableModelCommitter.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModifiableModelCommitter.java @@ -52,6 +52,9 @@ public class ModifiableModelCommitter { ModuleRootManagerImpl.doCommit(model); } for (ModifiableRootModel model : modelsToDispose) { + if (model instanceof RootModelImpl) { + ((RootModelImpl)model).checkModuleExtensionModification(); + } model.dispose(); } }); diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleRootManagerImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleRootManagerImpl.java index 6c45fa5a210a..5072f414d2a2 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleRootManagerImpl.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleRootManagerImpl.java @@ -364,7 +364,7 @@ public class ModuleRootManagerImpl extends ModuleRootManager implements Disposab } } - private void stateChanged() { + void stateChanged() { if (Registry.is("store.track.module.root.manager.changes", false)) { LOG.error("ModelRootManager state changed"); } diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java index 90b15121e6e6..355524868b3f 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.roots.impl; +import com.intellij.configurationStore.Scheme_implKt; import com.intellij.configurationStore.SerializationUtilKt; import com.intellij.openapi.CompositeDisposable; import com.intellij.openapi.Disposable; @@ -38,6 +39,7 @@ import com.intellij.util.ArrayUtil; import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.xmlb.XmlSerializer; +import gnu.trove.THashMap; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -63,6 +65,8 @@ public class RootModelImpl extends RootModelBase implements ModifiableRootModel private boolean myDisposed = false; private final Set myExtensions = new TreeSet<>((o1, o2) -> Comparing.compare(o1.getClass().getName(), o2.getClass().getName())); + @Nullable + private final Map myExtensionToStateDigest; private final RootConfigurationAccessor myConfigurationAccessor; @@ -88,6 +92,7 @@ public class RootModelImpl extends RootModelBase implements ModifiableRootModel myExtensions.add(model); } myConfigurationAccessor = new RootConfigurationAccessor(); + myExtensionToStateDigest = null; } private void addSourceOrderEntries() { @@ -140,6 +145,7 @@ public class RootModelImpl extends RootModelBase implements ModifiableRootModel myExtensions.add(model); } myConfigurationAccessor = new RootConfigurationAccessor(); + myExtensionToStateDigest = null; } @Override @@ -176,10 +182,24 @@ public class RootModelImpl extends RootModelBase implements ModifiableRootModel setOrderEntriesFrom(rootModel); + myExtensionToStateDigest = writable ? new THashMap<>() : null; + for (ModuleExtension extension : rootModel.myExtensions) { ModuleExtension model = extension.getModifiableModel(writable); registerOnDispose(model); myExtensions.add(model); + + if (myExtensionToStateDigest != null && !(extension instanceof PersistentStateComponentWithModificationTracker)) { + Element state = new Element("state"); + try { + //noinspection deprecation + extension.writeExternal(state); + myExtensionToStateDigest.put(extension, Scheme_implKt.digest(state)); + } + catch (Exception e) { + LOG.warn(e); + } + } } } @@ -654,6 +674,12 @@ public class RootModelImpl extends RootModelBase implements ModifiableRootModel assert !myDisposed; Disposer.dispose(myDisposable); myExtensions.clear(); + + if (myExtensionToStateDigest != null) { + myExtensionToStateDigest.clear(); + + } + myWritable = false; myDisposed = true; } @@ -786,4 +812,27 @@ public class RootModelImpl extends RootModelBase implements ModifiableRootModel void registerOnDispose(@NotNull Disposable disposable) { myDisposable.add(disposable); } + + void checkModuleExtensionModification() { + if (myExtensionToStateDigest == null || myExtensionToStateDigest.isEmpty()) { + return; + } + + for (Map.Entry entry : myExtensionToStateDigest.entrySet()) { + Element state = new Element("state"); + try { + ModuleExtension extension = entry.getKey(); + //noinspection deprecation + extension.writeExternal(state); + byte[] newDigest = Scheme_implKt.digest(state); + if (!Arrays.equals(newDigest, entry.getValue())) { + myModuleRootManager.stateChanged(); + return; + } + } + catch (Exception e) { + LOG.warn(e); + } + } + } }