avoid duplicate notification for same path variables (which are defined in project & module) + validate path variables on apply in path variables in setting dialog + [ex] 17789 NPE: XmlElementStorage$StorageData.checkUnknownMacros [r=nik]

This commit is contained in:
Alexey Pegov
2009-12-03 18:32:50 +03:00
parent 3112144d8a
commit 3ba2b4e136
9 changed files with 57 additions and 49 deletions
@@ -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<String> 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(
"<p>Undefined Path Variable(s): <i>%s</i>. <a href=\"\">Fix it!</a></p>",
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);
}
});
}
}
}
@@ -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() {
@@ -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<String> macros = substitutor.getUnknownMacros(componentName);
if (!macros.isEmpty()) {
Notifications.Bus.notify(new UnknownMacroNotification("Load Error", "Component load error: undefined path variables!",
String.format("<p><i>%s</i> %s undefined. <a href=\"\">Fix it!</a></p>",
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);
}
}
}
@@ -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<String> 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("<p><i>%s</i> %s undefined. <a href=\"\">Fix it!</a></p>",
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 {
@@ -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<String> unknownMacros = StorageUtil.getMacroNames(myComponentStates.get(componentName));
if (!unknownMacros.isEmpty()) {
@@ -30,5 +30,5 @@ public interface ProjectEx extends Project {
void setOptimiseTestLoadSpeed(boolean optimiseTestLoadSpeed);
void checkUnknownMacros();
void checkUnknownMacros(final boolean showDialog);
}
@@ -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<String>(unknownMacros))) {
if (!showDialog || ProjectMacrosUtil.checkMacros(this, new HashSet<String>(unknownMacros))) {
final PathMacros pathMacros = PathMacros.getInstance();
final Set<String> macros2invalidate = new HashSet<String>(unknownMacros);
for (Iterator it = macros2invalidate.iterator(); it.hasNext();) {
@@ -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<String> macros = macroSubstitutor.getUnknownMacros(null);
if (!macros.isEmpty()) {
Notifications.Bus.notify(new UnknownMacroNotification("Load Error", "Project loading error: undefined path variables!",
String.format("<p><i>%s</i> %s undefined. <a href=\"\">Fix it!</a></p>",
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);
}
}
});
@@ -36,7 +36,7 @@ public class MockProject extends MockComponentManager implements ProjectEx {
return false;
}
public void checkUnknownMacros() {
public void checkUnknownMacros(final boolean showDialog) {
}
@NotNull