diff --git a/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStoreImpl.java b/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStoreImpl.java index 5ef3ef2d6bda..f3bd4332d481 100644 --- a/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStoreImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStoreImpl.java @@ -16,7 +16,6 @@ package com.intellij.openapi.components.impl.stores; -import com.intellij.notification.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.PathMacroManager; import com.intellij.openapi.components.PathMacroSubstitutor; @@ -30,7 +29,6 @@ import com.intellij.openapi.module.impl.ModuleImpl; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ex.ProjectEx; import com.intellij.openapi.startup.StartupManager; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import org.jdom.Attribute; @@ -39,7 +37,6 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.swing.event.HyperlinkEvent; import java.io.File; import java.io.IOException; import java.util.*; @@ -85,18 +82,12 @@ public class ModuleStoreImpl extends BaseFileConfigurableStoreImpl implements IM final Collection macros = substitutor.getUnknownMacros(null); if (!macros.isEmpty()) { final Project project = myModule.getProject(); - StartupManager.getInstance(project).runWhenProjectIsInitialized(new Runnable() { - public void run() { - Notifications.Bus.notify(new UnknownMacroNotification("Load Error", String.format("Error loading module '%s':", myModule.getName()), - String.format( - "

Undefined Path Variable(s): %s. Fix it!

", - StringUtil.join(macros, ", ")), NotificationType.ERROR, new NotificationListener() { - public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) { - ((ProjectEx)myModule.getProject()).checkUnknownMacros(); - } - }, macros), NotificationDisplayType.STICKY_BALLOON, project); - } - }); + + StartupManager.getInstance(project).runWhenProjectIsInitialized(new Runnable() { + public void run() { + StorageUtil.notifyUnknownMacros(substitutor, project, null); + } + }); } } } diff --git a/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroConfigurable.java b/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroConfigurable.java index 1b382ccede8b..202488e849ab 100644 --- a/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroConfigurable.java +++ b/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroConfigurable.java @@ -18,6 +18,9 @@ package com.intellij.application.options.pathMacros; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.SearchableConfigurable; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.project.ex.ProjectEx; import com.intellij.openapi.util.IconLoader; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; @@ -40,6 +43,11 @@ public class PathMacroConfigurable implements SearchableConfigurable { public void apply() throws ConfigurationException { myEditor.commit(); + + final Project[] projects = ProjectManager.getInstance().getOpenProjects(); + for (Project project : projects) { + ((ProjectEx)project).checkUnknownMacros(false); + } } public void reset() { diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java index 8489cf581778..f40da2a5825b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java @@ -33,7 +33,9 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtil; import com.intellij.util.ReflectionCache; import com.intellij.util.ReflectionUtil; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.io.fs.IFile; +import net.sf.cglib.core.CollectionUtils; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -258,19 +260,7 @@ abstract class ComponentStoreImpl implements IComponentStore { if (service && componentName != null && project.isInitialized()) { final TrackingPathMacroSubstitutor substitutor = getStateStorageManager().getMacroSubstitutor(); if (substitutor != null) { - final Collection macros = substitutor.getUnknownMacros(componentName); - if (!macros.isEmpty()) { - Notifications.Bus.notify(new UnknownMacroNotification("Load Error", "Component load error: undefined path variables!", - String.format("

%s %s undefined. Fix it!

", - StringUtil.join(macros, ", "), macros.size() == 1 ? "is" : "are"), - NotificationType.ERROR, - new NotificationListener() { - public void hyperlinkUpdate(@NotNull Notification notification, - @NotNull HyperlinkEvent event) { - ((ProjectEx)project).checkUnknownMacros(); - } - }, macros), NotificationDisplayType.STICKY_BALLOON, project); - } + StorageUtil.notifyUnknownMacros(substitutor, project, componentName); } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java index 9c39e2b7bf12..e5b43e733122 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java @@ -16,15 +16,20 @@ package com.intellij.openapi.components.impl.stores; import com.intellij.application.options.PathMacrosCollector; +import com.intellij.notification.*; import com.intellij.openapi.application.ApplicationInfo; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.application.ex.ApplicationManagerEx; +import com.intellij.openapi.components.PathMacroSubstitutor; import com.intellij.openapi.components.RoamingType; import com.intellij.openapi.components.StateStorage; +import com.intellij.openapi.components.TrackingPathMacroSubstitutor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.options.StreamProvider; +import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectBundle; +import com.intellij.openapi.project.ex.ProjectEx; import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; @@ -36,14 +41,17 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.NotNullFunction; import com.intellij.util.SystemProperties; import com.intellij.util.UniqueFileNamesProvider; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.io.fs.FileSystem; import com.intellij.util.io.fs.IFile; import org.jdom.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.event.HyperlinkEvent; import java.io.*; import java.text.SimpleDateFormat; +import java.util.Collection; import java.util.Date; import java.util.Set; @@ -57,6 +65,30 @@ public class StorageUtil { private StorageUtil() { } + public static void notifyUnknownMacros(@NotNull final TrackingPathMacroSubstitutor substitutor, @NotNull final Project project, @Nullable final String componentName) { + Collection macros = substitutor.getUnknownMacros(componentName); + if (!macros.isEmpty()) { + final UnknownMacroNotification[] notifications = + NotificationsManager.getNotificationsManager().getNotificationsOfType(UnknownMacroNotification.class, project); + for (final UnknownMacroNotification notification : notifications) { + macros = ContainerUtil.subtract(macros, notification.getMacros()); + } + + if (!macros.isEmpty()) { + Notifications.Bus.notify(new UnknownMacroNotification("Load Error", "Loading error: undefined path variables!", + String.format("

%s %s undefined. Fix it!

", + StringUtil.join(macros, ", "), + macros.size() == 1 ? "is" : "are"), NotificationType.ERROR, + new NotificationListener() { + public void hyperlinkUpdate(@NotNull Notification notification, + @NotNull HyperlinkEvent event) { + ((ProjectEx)project).checkUnknownMacros(true); + } + }, macros), NotificationDisplayType.STICKY_BALLOON, project); + } + } + } + static void save(final IFile file, final byte[] text, final Object requestor) throws StateStorage.StateStorageException { final String filePath = file.getCanonicalPath(); try { diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java index 28b5783b2ff4..0419e7856058 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java @@ -710,6 +710,8 @@ public abstract class XmlElementStorage implements StateStorage, Disposable { } public void checkUnknownMacros(TrackingPathMacroSubstitutor pathMacroSubstitutor) { + if (pathMacroSubstitutor == null) return; + for (String componentName : myComponentStates.keySet()) { final Set unknownMacros = StorageUtil.getMacroNames(myComponentStates.get(componentName)); if (!unknownMacros.isEmpty()) { diff --git a/platform/platform-impl/src/com/intellij/openapi/project/ex/ProjectEx.java b/platform/platform-impl/src/com/intellij/openapi/project/ex/ProjectEx.java index 18697eab7dcd..21bc05e60437 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/ex/ProjectEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/ex/ProjectEx.java @@ -30,5 +30,5 @@ public interface ProjectEx extends Project { void setOptimiseTestLoadSpeed(boolean optimiseTestLoadSpeed); - void checkUnknownMacros(); + void checkUnknownMacros(final boolean showDialog); } diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java index 8418750b1737..23cea6f0382b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java @@ -359,7 +359,7 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx { return false; } - public void checkUnknownMacros() { + public void checkUnknownMacros(final boolean showDialog) { final IProjectStore stateStore = getStateStore(); final TrackingPathMacroSubstitutor[] substitutors = stateStore.getSubstitutors(); @@ -369,7 +369,7 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx { } if (!unknownMacros.isEmpty()) { - if (ProjectMacrosUtil.checkMacros(this, new HashSet(unknownMacros))) { + if (!showDialog || ProjectMacrosUtil.checkMacros(this, new HashSet(unknownMacros))) { final PathMacros pathMacros = PathMacros.getInstance(); final Set macros2invalidate = new HashSet(unknownMacros); for (Iterator it = macros2invalidate.iterator(); it.hasNext();) { diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java index f902ac473cd9..f956a0ff901a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java @@ -29,10 +29,7 @@ import com.intellij.openapi.application.impl.ApplicationImpl; import com.intellij.openapi.components.ExportableApplicationComponent; import com.intellij.openapi.components.StateStorage; import com.intellij.openapi.components.TrackingPathMacroSubstitutor; -import com.intellij.openapi.components.impl.stores.IComponentStore; -import com.intellij.openapi.components.impl.stores.IProjectStore; -import com.intellij.openapi.components.impl.stores.UnknownMacroNotification; -import com.intellij.openapi.components.impl.stores.XmlElementStorage; +import com.intellij.openapi.components.impl.stores.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.progress.ProcessCanceledException; @@ -399,19 +396,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt final TrackingPathMacroSubstitutor macroSubstitutor = ((ProjectEx)project).getStateStore().getStateStorageManager().getMacroSubstitutor(); if (macroSubstitutor != null) { - final Collection macros = macroSubstitutor.getUnknownMacros(null); - if (!macros.isEmpty()) { - Notifications.Bus.notify(new UnknownMacroNotification("Load Error", "Project loading error: undefined path variables!", - String.format("

%s %s undefined. Fix it!

", - StringUtil.join(macros, ", "), macros.size() == 1 ? "is" : "are"), - NotificationType.ERROR, - new NotificationListener() { - public void hyperlinkUpdate(@NotNull Notification notification, - @NotNull HyperlinkEvent event) { - ((ProjectEx)project).checkUnknownMacros(); - } - }, macros), NotificationDisplayType.STICKY_BALLOON, project); - } + StorageUtil.notifyUnknownMacros(macroSubstitutor, project, null); } } }); diff --git a/platform/testFramework/src/com/intellij/mock/MockProject.java b/platform/testFramework/src/com/intellij/mock/MockProject.java index 0c6013fd4912..f43767a88e51 100644 --- a/platform/testFramework/src/com/intellij/mock/MockProject.java +++ b/platform/testFramework/src/com/intellij/mock/MockProject.java @@ -36,7 +36,7 @@ public class MockProject extends MockComponentManager implements ProjectEx { return false; } - public void checkUnknownMacros() { + public void checkUnknownMacros(final boolean showDialog) { } @NotNull