allow to ignore invalid facets from error notification

This commit is contained in:
nik
2011-10-10 13:11:11 +04:00
parent 94788bfc64
commit 6998b3f6c9
8 changed files with 122 additions and 84 deletions
@@ -18,6 +18,7 @@ package com.intellij.packaging.impl.artifacts;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.module.ConfigurationErrorDescription;
import com.intellij.openapi.module.ConfigurationErrorType;
import com.intellij.openapi.project.Project;
import com.intellij.packaging.artifacts.ArtifactManager;
import com.intellij.packaging.artifacts.ModifiableArtifactModel;
@@ -26,17 +27,18 @@ import com.intellij.packaging.artifacts.ModifiableArtifactModel;
* @author nik
*/
public class ArtifactLoadingErrorDescription extends ConfigurationErrorDescription {
private static final ConfigurationErrorType INVALID_ARTIFACT = new ConfigurationErrorType("artifact", false);
private final Project myProject;
private final InvalidArtifact myArtifact;
public ArtifactLoadingErrorDescription(Project project, InvalidArtifact artifact) {
super(artifact.getName(), "artifact", artifact.getErrorMessage());
super(artifact.getName(), artifact.getErrorMessage(), INVALID_ARTIFACT);
myProject = project;
myArtifact = artifact;
}
@Override
public void removeInvalidElement() {
public void ignoreInvalidElement() {
final ModifiableArtifactModel model = ArtifactManager.getInstance(myProject).createModifiableModel();
model.removeArtifact(myArtifact);
new WriteAction() {
@@ -47,7 +49,7 @@ public class ArtifactLoadingErrorDescription extends ConfigurationErrorDescripti
}
@Override
public String getRemoveConfirmationMessage() {
public String getIgnoreConfirmationMessage() {
return "Would you like to remove artifact '" + myArtifact.getName() + "?";
}
@@ -17,28 +17,31 @@
package com.intellij.facet.impl;
import com.intellij.facet.impl.invalid.InvalidFacet;
import com.intellij.facet.impl.invalid.InvalidFacetManager;
import com.intellij.openapi.module.ConfigurationErrorDescription;
import com.intellij.openapi.module.ConfigurationErrorType;
import com.intellij.openapi.project.ProjectBundle;
/**
* @author nik
*/
public class FacetLoadingErrorDescription extends ConfigurationErrorDescription {
private static final ConfigurationErrorType INVALID_FACET = new ConfigurationErrorType(ProjectBundle.message("element.kind.name.facet"), true);
private final InvalidFacet myFacet;
public FacetLoadingErrorDescription(final InvalidFacet facet) {
super(facet.getName() + " (" + facet.getModule().getName() + ")", ProjectBundle.message("element.kind.name.facet"), facet.getErrorMessage());
super(facet.getName() + " (" + facet.getModule().getName() + ")", facet.getErrorMessage(), INVALID_FACET);
myFacet = facet;
}
@Override
public String getRemoveConfirmationMessage() {
return ProjectBundle.message("confirmation.message.would.you.like.to.remove.facet", myFacet.getName(), myFacet.getModule().getName());
public String getIgnoreConfirmationMessage() {
return ProjectBundle.message("confirmation.message.would.you.like.to.ignore.facet", myFacet.getName(), myFacet.getModule().getName());
}
@Override
public void removeInvalidElement() {
FacetUtil.deleteFacet(myFacet);
public void ignoreInvalidElement() {
InvalidFacetManager.getInstance(myFacet.getModule().getProject()).setIgnored(myFacet, true);
}
@Override
@@ -21,12 +21,12 @@ package com.intellij.openapi.module;
*/
public abstract class ConfigurationErrorDescription {
private final String myElementName;
private final String myElementKind;
private final String myDescription;
private ConfigurationErrorType myErrorType;
protected ConfigurationErrorDescription(String elementName, String elementKind, String description) {
protected ConfigurationErrorDescription(String elementName, String description, ConfigurationErrorType errorType) {
myElementName = elementName;
myElementKind = elementKind;
myErrorType = errorType;
myDescription = description;
}
@@ -34,17 +34,17 @@ public abstract class ConfigurationErrorDescription {
return myElementName;
}
public String getElementKind() {
return myElementKind;
public ConfigurationErrorType getErrorType() {
return myErrorType;
}
public String getDescription() {
return myDescription;
}
public abstract void removeInvalidElement();
public abstract void ignoreInvalidElement();
public abstract String getRemoveConfirmationMessage();
public abstract String getIgnoreConfirmationMessage();
public boolean isValid() {
return true;
@@ -0,0 +1,37 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.module;
/**
* @author nik
*/
public class ConfigurationErrorType {
private String myElementKind;
private boolean myCanIgnore;
public ConfigurationErrorType(String elementKind, boolean canIgnore) {
myElementKind = elementKind;
myCanIgnore = canIgnore;
}
public String getElementKind() {
return myElementKind;
}
public boolean canIgnore() {
return myCanIgnore;
}
}
@@ -17,6 +17,7 @@
package com.intellij.openapi.module.impl;
import com.intellij.openapi.module.ConfigurationErrorDescription;
import com.intellij.openapi.module.ConfigurationErrorType;
import com.intellij.openapi.project.ProjectBundle;
import java.io.File;
@@ -25,12 +26,13 @@ import java.io.File;
* @author nik
*/
public class ModuleLoadingErrorDescription extends ConfigurationErrorDescription {
private static final ConfigurationErrorType INVALID_MODULE = new ConfigurationErrorType(ProjectBundle.message("element.kind.name.module"), false);
private final ModuleManagerImpl.ModulePath myModulePath;
private final ModuleManagerImpl myModuleManager;
private ModuleLoadingErrorDescription(final String description, final ModuleManagerImpl.ModulePath modulePath, ModuleManagerImpl moduleManager,
final String elementName) {
super(elementName, ProjectBundle.message("element.kind.name.module"), description);
super(elementName, description, INVALID_MODULE);
myModulePath = modulePath;
myModuleManager = moduleManager;
}
@@ -40,12 +42,12 @@ public class ModuleLoadingErrorDescription extends ConfigurationErrorDescription
}
@Override
public void removeInvalidElement() {
public void ignoreInvalidElement() {
myModuleManager.removeFailedModulePath(myModulePath);
}
@Override
public String getRemoveConfirmationMessage() {
public String getIgnoreConfirmationMessage() {
return ProjectBundle.message("module.remove.from.project.confirmation", getElementName());
}
@@ -22,6 +22,7 @@ import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
import com.intellij.openapi.module.ConfigurationErrorDescription;
import com.intellij.openapi.module.ConfigurationErrorType;
import com.intellij.openapi.module.ProjectLoadingErrorsNotifier;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectBundle;
@@ -29,12 +30,10 @@ import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.TObjectIntHashMap;
import gnu.trove.TObjectIntProcedure;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import javax.swing.event.HyperlinkEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -43,7 +42,7 @@ import java.util.List;
* @author nik
*/
public class ProjectLoadingErrorsNotifierImpl extends ProjectLoadingErrorsNotifier {
private final List<ConfigurationErrorDescription> myErrors = new ArrayList<ConfigurationErrorDescription>();
private final MultiMap<ConfigurationErrorType, ConfigurationErrorDescription> myErrors = new MultiMap<ConfigurationErrorType, ConfigurationErrorDescription>();
private final Object myLock = new Object();
private final Project myProject;
@@ -63,7 +62,9 @@ public class ProjectLoadingErrorsNotifierImpl extends ProjectLoadingErrorsNotifi
boolean first;
synchronized (myLock) {
first = myErrors.isEmpty();
myErrors.addAll(errorDescriptions);
for (ConfigurationErrorDescription description : errorDescriptions) {
myErrors.putValue(description.getErrorType(), description);
}
}
if (myProject.isInitialized()) {
fireNotifications();
@@ -78,63 +79,47 @@ public class ProjectLoadingErrorsNotifierImpl extends ProjectLoadingErrorsNotifi
}
private void fireNotifications() {
final ConfigurationErrorDescription[] descriptions;
final MultiMap<ConfigurationErrorType, ConfigurationErrorDescription> descriptionsMap = new MultiMap<ConfigurationErrorType, ConfigurationErrorDescription>();
synchronized (myLock) {
if (myErrors.isEmpty()) return;
descriptions = myErrors.toArray(new ConfigurationErrorDescription[myErrors.size()]);
descriptionsMap.putAllValues(myErrors);
myErrors.clear();
}
final String invalidElements = getInvalidElementsString(descriptions);
final String errorText = ProjectBundle.message("error.message.configuration.cannot.load") + " " + invalidElements + " <a href=\"\">Details...</a>";
for (final ConfigurationErrorType type : descriptionsMap.keySet()) {
final Collection<ConfigurationErrorDescription> descriptions = descriptionsMap.get(type);
if (descriptions.isEmpty()) continue;
Notifications.Bus.notify(new Notification("Project Loading Error", "Error Loading Project", errorText, NotificationType.ERROR,
new NotificationListener() {
public void hyperlinkUpdate(@NotNull Notification notification,
@NotNull HyperlinkEvent event) {
final List<ConfigurationErrorDescription> validDescriptions =
ContainerUtil.findAll(descriptions, new Condition<ConfigurationErrorDescription>() {
public boolean value(ConfigurationErrorDescription errorDescription) {
return errorDescription.isValid();
}
});
RemoveInvalidElementsDialog
.showDialog(myProject, CommonBundle.getErrorTitle(), invalidElements,
validDescriptions);
final String invalidElements = getInvalidElementsString(type, descriptions);
final String errorText = ProjectBundle.message("error.message.configuration.cannot.load") + " " + invalidElements + " <a href=\"\">Details...</a>";
notification.expire();
}
}), myProject);
Notifications.Bus.notify(new Notification("Project Loading Error", "Error Loading Project", errorText, NotificationType.ERROR,
new NotificationListener() {
public void hyperlinkUpdate(@NotNull Notification notification,
@NotNull HyperlinkEvent event) {
final List<ConfigurationErrorDescription> validDescriptions =
ContainerUtil.findAll(descriptions, new Condition<ConfigurationErrorDescription>() {
public boolean value(ConfigurationErrorDescription errorDescription) {
return errorDescription.isValid();
}
});
RemoveInvalidElementsDialog
.showDialog(myProject, CommonBundle.getErrorTitle(), type, invalidElements,
validDescriptions);
notification.expire();
}
}), myProject);
}
}
private static String getInvalidElementsString(ConfigurationErrorDescription[] descriptions) {
if (descriptions.length == 1) {
final ConfigurationErrorDescription description = descriptions[0];
return description.getElementKind() + " " + description.getElementName();
private static String getInvalidElementsString(ConfigurationErrorType type, Collection<ConfigurationErrorDescription> descriptions) {
if (descriptions.size() == 1) {
final ConfigurationErrorDescription description = ContainerUtil.getFirstItem(descriptions);
return type.getElementKind() + " " + description.getElementName();
}
TObjectIntHashMap<String> kind2count = new TObjectIntHashMap<String>();
for (ConfigurationErrorDescription description : descriptions) {
final String kind = description.getElementKind();
if (!kind2count.contains(kind)) {
kind2count.put(kind, 1);
}
else {
kind2count.increment(kind);
}
}
final StringBuilder message = new StringBuilder();
kind2count.forEachEntry(new TObjectIntProcedure<String>() {
public boolean execute(String a, int b) {
if (message.length() > 0) {
message.append(' ').append(ProjectBundle.message("text.and")).append(' ');
}
message.append(b).append(' ').append(b > 1 ? StringUtil.pluralize(a) : a);
return true;
}
});
return message.toString();
return descriptions.size() + " " + StringUtil.pluralize(type.getElementKind());
}
}
@@ -16,8 +16,8 @@
package com.intellij.openapi.module.impl;
import com.intellij.CommonBundle;
import com.intellij.openapi.module.ConfigurationErrorDescription;
import com.intellij.openapi.module.ConfigurationErrorType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.ui.DialogWrapper;
@@ -28,8 +28,10 @@ import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author nik
@@ -40,10 +42,14 @@ public class RemoveInvalidElementsDialog extends DialogWrapper {
private JLabel myDescriptionLabel;
private final Map<JCheckBox, ConfigurationErrorDescription> myCheckboxes = new HashMap<JCheckBox, ConfigurationErrorDescription>();
private RemoveInvalidElementsDialog(final String title, String invalidElements, final Project project, List<ConfigurationErrorDescription> errors) {
private RemoveInvalidElementsDialog(final String title,
ConfigurationErrorType type,
String invalidElements,
final Project project,
List<ConfigurationErrorDescription> errors) {
super(project, true);
setTitle(title);
myDescriptionLabel.setText(ProjectBundle.message("label.text.0.cannot.be.loaded", invalidElements));
myDescriptionLabel.setText(ProjectBundle.message(type.canIgnore() ? "label.text.0.cannot.be.loaded.ignore" : "label.text.0.cannot.be.loaded.remove", invalidElements));
myContentPanel.setLayout(new VerticalFlowLayout());
for (ConfigurationErrorDescription error : errors) {
JCheckBox checkBox = new JCheckBox(error.getElementName() + ".");
@@ -62,32 +68,34 @@ public class RemoveInvalidElementsDialog extends DialogWrapper {
myContentPanel.add(panel);
}
init();
setOKButtonText(ProjectBundle.message("button.text.remove.selected"));
setOKButtonText(ProjectBundle.message(type.canIgnore() ? "button.text.ignore.selected" : "button.text.remove.selected"));
setCancelButtonText(ProjectBundle.message("button.text.keep.all"));
}
public static void showDialog(@NotNull Project project, @NotNull String title, @NotNull String invalidElements,
public static void showDialog(@NotNull Project project,
@NotNull String title,
ConfigurationErrorType type,
@NotNull String invalidElements,
@NotNull List<ConfigurationErrorDescription> errors) {
if (errors.isEmpty()) {
return;
}
if (errors.size() == 1) {
ConfigurationErrorDescription error = errors.get(0);
String message = error.getDescription() + "\n" + error.getRemoveConfirmationMessage();
final int answer = Messages.showOkCancelDialog(project, message, title, CommonBundle.getNoButtonText(),
CommonBundle.getYesButtonText(), Messages.getErrorIcon());
String message = error.getDescription() + "\n" + error.getIgnoreConfirmationMessage();
final int answer = Messages.showYesNoDialog(project, message, title, Messages.getErrorIcon());
if (answer == 1) {
error.removeInvalidElement();
error.ignoreInvalidElement();
}
return;
}
RemoveInvalidElementsDialog dialog = new RemoveInvalidElementsDialog(title, invalidElements, project, errors);
RemoveInvalidElementsDialog dialog = new RemoveInvalidElementsDialog(title, type, invalidElements, project, errors);
dialog.show();
if (dialog.isOK()) {
for (ConfigurationErrorDescription errorDescription : dialog.getSelectedItems()) {
errorDescription.removeInvalidElement();
errorDescription.ignoreInvalidElement();
}
}
}
@@ -359,13 +359,14 @@ error.message.0.facet.must.be.placed.under.1.facet={0} facet must be placed unde
error.message.0.cannot.be.placed.under.1={0} cannot be placed under {1}
error.message.0.facets.are.not.allowed.in.1={0} facets are not allowed in {1}
button.text.remove.selected=Remove Selected
button.text.ignore.selected=Ignore Selected
button.text.keep.all=Keep All
confirmation.message.would.you.like.to.remove.facet=Would you like to remove facet ''{0}'' from module ''{1}''?
confirmation.message.would.you.like.to.ignore.facet=Would you like to ignore facet ''{0}'' from module ''{1}''?
element.kind.name.facet=facet
error.message.configuration.cannot.load=Cannot load
label.text.0.cannot.be.loaded={0} cannot be loaded. You can remove them from the project (no files will be deleted).
text.and=and
label.text.0.cannot.be.loaded.remove={0} cannot be loaded. You can remove them from the project (no files will be deleted).
label.text.0.cannot.be.loaded.ignore={0} cannot be loaded. You can mark them as ignored to suppress this error notification.
#artifacts
display.name.artifacts=Artifacts