project structure dialog: persisting ignored errors

This commit is contained in:
nik
2011-09-30 13:43:08 +04:00
parent c55a67ef7c
commit 4bbbde4a04
30 changed files with 439 additions and 117 deletions
@@ -23,8 +23,8 @@ import javax.swing.*;
* User: spLeaner
*/
public abstract class ConfigurationError implements Comparable<ConfigurationError> {
protected String myPlainTextTitle;
protected String myDescription;
private final String myPlainTextTitle;
private final String myDescription;
private boolean myIgnored;
protected ConfigurationError(final String plainTextTitle, final String description) {
@@ -39,6 +39,11 @@ public class GeneralProjectSettingsElement extends ProjectStructureElement {
super(context);
}
@Override
public String getPresentableName() {
return "Project";
}
@Override
public void check(ProjectStructureProblemsHolder problemsHolder) {
final Graph<Chunk<ModifiableRootModel>> graph = ModuleCompilerUtil.toChunkGraph(myContext.getModulesConfigurator().createGraphGenerator());
@@ -59,10 +64,20 @@ public class GeneralProjectSettingsElement extends ProjectStructureElement {
if (count > 0) {
@NonNls final String leftBrace = "<html>";
@NonNls final String rightBrace = "</html>";
final String warningMessage = leftBrace + ProjectBundle.message("module.circular.dependency.warning", cycles, count) + rightBrace;
final String fullDescription = leftBrace + ProjectBundle.message("module.circular.dependency.warning", cycles, count) + rightBrace;
final Project project = myContext.getProject();
final PlaceInProjectStructureBase place = new PlaceInProjectStructureBase(project, ProjectStructureConfigurable.getInstance(project).createModulesPlace());
problemsHolder.registerWarning("Circular dependencies", warningMessage, place, null);
for (Chunk<ModifiableRootModel> chunk : chunks) {
final Set<ModifiableRootModel> nodes = chunk.getNodes();
if (nodes.size() > 1) {
final PlaceInProjectStructureBase place = new PlaceInProjectStructureBase(project, ProjectStructureConfigurable.getInstance(project).createModulesPlace(), this);
StringBuilder names = new StringBuilder();
for (ModifiableRootModel model : nodes) {
if (names.length() > 0) names.append(", ");
names.append(model.getModule().getName());
}
problemsHolder.registerProblem(new CircularDependencyProblemDescription("Circular dependency between modules " + names, fullDescription, place));
}
}
}
}
@@ -76,6 +91,11 @@ public class GeneralProjectSettingsElement extends ProjectStructureElement {
return false;
}
@Override
public String getId() {
return "project:general";
}
@Override
public boolean equals(Object obj) {
return obj instanceof GeneralProjectSettingsElement;
@@ -85,4 +105,20 @@ public class GeneralProjectSettingsElement extends ProjectStructureElement {
public int hashCode() {
return 0;
}
public static class CircularDependencyProblemDescription extends ProjectStructureProblemDescription {
@NotNull private final String myFullDescription;
public CircularDependencyProblemDescription(@NotNull String message,
@NotNull String fullDescription,
@NotNull PlaceInProjectStructure place) {
super(message, null, place, Collections.<ConfigurationErrorQuickFix>emptyList(), ProjectStructureProblemType.warning("module-circular-dependency"));
myFullDescription = fullDescription;
}
@NotNull
public String getFullDescription() {
return myFullDescription;
}
}
}
@@ -120,9 +120,9 @@ public class ProjectConfigurable extends ProjectStructureElementConfigurable<Pro
private void updateCircularDependencyWarning() {
ProjectStructureProblemsHolderImpl holder = myContext.getDaemonAnalyzer().getProblemsHolder(mySettingsElement);
final ProjectStructureProblemDescription item = holder != null ? ContainerUtil.getFirstItem(holder.getProblemDescriptions()) : null;
if (item != null) {
if (item instanceof GeneralProjectSettingsElement.CircularDependencyProblemDescription) {
myWarningLabel.setIcon(Messages.getWarningIcon());
myWarningLabel.setText(item.getDescription());
myWarningLabel.setText(((GeneralProjectSettingsElement.CircularDependencyProblemDescription)item).getFullDescription());
}
else {
myWarningLabel.setIcon(null);
@@ -17,6 +17,7 @@ package com.intellij.openapi.roots.ui.configuration.artifacts;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ConfigurationErrorQuickFix;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemDescription;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemType;
import com.intellij.packaging.elements.PackagingElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -29,9 +30,10 @@ import java.util.List;
public class ArtifactProblemDescription extends ProjectStructureProblemDescription {
private final List<PackagingElement<?>> myPathToPlace;
public ArtifactProblemDescription(@NotNull String message, @NotNull Severity severity, @Nullable List<PackagingElement<?>> pathToPlace,
@NotNull PlaceInArtifact place, final List<ConfigurationErrorQuickFix> quickFixList) {
super(message, null, severity, place, quickFixList);
public ArtifactProblemDescription(@NotNull String message, @NotNull ProjectStructureProblemType problemType,
@Nullable List<PackagingElement<?>> pathToPlace, @NotNull PlaceInArtifact place,
final List<ConfigurationErrorQuickFix> quickFixList) {
super(message, null, place, quickFixList, problemType);
myPathToPlace = pathToPlace;
}
@@ -16,7 +16,7 @@
package com.intellij.openapi.roots.ui.configuration.artifacts;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ConfigurationErrorQuickFix;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemDescription;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemType;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemsHolder;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.packaging.elements.PackagingElement;
@@ -47,12 +47,21 @@ public class ArtifactProblemsHolderImpl extends ArtifactProblemsHolderBase {
myProblemsHolder = problemsHolder;
}
public void registerError(@NotNull String message, @Nullable List<PackagingElement<?>> pathToPlace, @NotNull ArtifactProblemQuickFix... quickFixes) {
registerProblem(message, pathToPlace, ProjectStructureProblemDescription.Severity.ERROR, quickFixes);
public void registerError(@NotNull String message,
@NotNull String problemTypeId,
@Nullable List<PackagingElement<?>> pathToPlace,
@NotNull ArtifactProblemQuickFix... quickFixes) {
registerProblem(message, pathToPlace, ProjectStructureProblemType.error(problemTypeId), quickFixes);
}
public void registerWarning(@NotNull String message,
@NotNull String problemTypeId, @Nullable List<PackagingElement<?>> pathToPlace,
@NotNull ArtifactProblemQuickFix... quickFixes) {
registerProblem(message, pathToPlace, ProjectStructureProblemType.warning(problemTypeId), quickFixes);
}
private void registerProblem(@NotNull String message, @Nullable List<PackagingElement<?>> pathToPlace,
final ProjectStructureProblemDescription.Severity severity, @NotNull ArtifactProblemQuickFix... quickFixes) {
final ProjectStructureProblemType problemType, @NotNull ArtifactProblemQuickFix... quickFixes) {
String parentPath;
PackagingElement<?> element;
if (pathToPlace != null && !pathToPlace.isEmpty()) {
@@ -65,13 +74,7 @@ public class ArtifactProblemsHolderImpl extends ArtifactProblemsHolderBase {
}
final Artifact artifact = myContext.getArtifactModel().getArtifactByOriginal(myOriginalArtifact);
final PlaceInArtifact place = new PlaceInArtifact(artifact, myContext, parentPath, element);
myProblemsHolder.registerProblem(new ArtifactProblemDescription(message, severity, pathToPlace, place, convertQuickFixes(quickFixes)));
}
public void registerWarning(@NotNull String message,
@Nullable List<PackagingElement<?>> pathToPlace,
@NotNull ArtifactProblemQuickFix... quickFixes) {
registerProblem(message, pathToPlace, ProjectStructureProblemDescription.Severity.WARNING, quickFixes);
myProblemsHolder.registerProblem(new ArtifactProblemDescription(message, problemType, pathToPlace, place, convertQuickFixes(quickFixes)));
}
private List<ConfigurationErrorQuickFix> convertQuickFixes(ArtifactProblemQuickFix[] quickFixes) {
@@ -114,11 +114,6 @@ public class ArtifactProjectStructureElement extends ProjectStructureElement {
return new UsageInArtifact(myOriginalArtifact, myArtifactsStructureContext, element, this, path.getPathString(), packagingElement);
}
@Override
public String toString() {
return "artifact:" + myOriginalArtifact.getName();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -138,4 +133,17 @@ public class ArtifactProjectStructureElement extends ProjectStructureElement {
return false;
}
@Override
public String getPresentableName() {
return "Artifact '" + getActualArtifactName() + "'";
}
@Override
public String getId() {
return "artifact:" + getActualArtifactName();
}
private String getActualArtifactName() {
return myArtifactsStructureContext.getArtifactModel().getArtifactByOriginal(myOriginalArtifact).getName();
}
}
@@ -17,6 +17,7 @@ package com.intellij.openapi.roots.ui.configuration.artifacts;
import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.PlaceInProjectStructure;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.packaging.elements.PackagingElement;
@@ -40,6 +41,21 @@ public class PlaceInArtifact extends PlaceInProjectStructure {
myPackagingElement = packagingElement;
}
@NotNull
@Override
public ProjectStructureElement getContainingElement() {
return myContext.getOrCreateArtifactElement(myArtifact);
}
@Override
public String getPlacePath() {
if (myParentPath != null && myPackagingElement != null) {
//todo[nik] use id of element?
return myParentPath + "/" + myPackagingElement.getType().getId();
}
return null;
}
@NotNull
@Override
public ActionCallback navigate() {
@@ -20,7 +20,7 @@ import com.intellij.openapi.editor.markup.EffectType;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.roots.ui.configuration.artifacts.ArtifactEditorImpl;
import com.intellij.openapi.roots.ui.configuration.artifacts.ArtifactProblemDescription;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemDescription;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemType;
import com.intellij.openapi.util.MultiValuesMap;
import com.intellij.packaging.elements.CompositePackagingElement;
import com.intellij.packaging.elements.PackagingElement;
@@ -107,7 +107,7 @@ public class PackagingElementNode<E extends PackagingElement<?>> extends Artifac
try {
buffer.append("<html>");
for (ArtifactProblemDescription problem : problems) {
isError |= problem.getSeverity() == ProjectStructureProblemDescription.Severity.ERROR;
isError |= problem.getSeverity() == ProjectStructureProblemType.Severity.ERROR;
buffer.append(problem.getMessage()).append("<br>");
}
buffer.append("</html>");
@@ -196,14 +196,14 @@ public abstract class BaseStructureConfigurable extends MasterDetailsComponent i
if (problemsHolder == null) {
daemonAnalyzer.queueUpdate(projectStructureElement, true, false);
}
final ProjectStructureProblemDescription.Severity level = problemsHolder != null ? problemsHolder.getSeverity() : null;
final ProjectStructureProblemType.Severity level = problemsHolder != null ? problemsHolder.getSeverity() : null;
final boolean invalid = level != null;
if (unused || invalid) {
Color fg = unused
? UIUtil.getInactiveTextColor()
: selected && hasFocus ? UIUtil.getTreeSelectionForeground() : UIUtil.getTreeForeground();
textAttributes = new SimpleTextAttributes(invalid ? SimpleTextAttributes.STYLE_WAVED : SimpleTextAttributes.STYLE_PLAIN, fg,
level == ProjectStructureProblemDescription.Severity.ERROR ? Color.RED : Color.GRAY);
level == ProjectStructureProblemType.Severity.ERROR ? Color.RED : Color.GRAY);
String text = problemsHolder != null ? problemsHolder.composeTooltipMessage() : "";
if (unused) {
text += ProjectBundle.message("project.roots.tooltip.unused", displayName);
@@ -16,6 +16,7 @@
package com.intellij.openapi.roots.ui.configuration.projectRoot.daemon;
import com.intellij.facet.Facet;
import com.intellij.facet.pointers.FacetPointersManager;
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
import org.jetbrains.annotations.NotNull;
@@ -47,6 +48,16 @@ public class FacetProjectStructureElement extends ProjectStructureElement {
return false;
}
@Override
public String getPresentableName() {
return "Facet '" + myFacet.getName() + "' in module '" + myFacet.getModule().getName() + "'";
}
@Override
public String getId() {
return "facet:" + FacetPointersManager.constructId(myFacet);
}
@Override
public boolean equals(Object obj) {
return obj instanceof FacetProjectStructureElement && myFacet.equals(((FacetProjectStructureElement)obj).myFacet);
@@ -56,9 +67,4 @@ public class FacetProjectStructureElement extends ProjectStructureElement {
public int hashCode() {
return myFacet.hashCode();
}
@Override
public String toString() {
return "facet:" + myFacet.getName() + " in " + myFacet.getModule().getName();
}
}
@@ -1,7 +1,6 @@
package com.intellij.openapi.roots.ui.configuration.projectRoot.daemon;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.roots.JavadocOrderRootType;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.impl.libraries.LibraryEx;
@@ -17,14 +16,11 @@ import com.intellij.openapi.roots.ui.configuration.projectRoot.LibraryConfigurab
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
import com.intellij.openapi.ui.NamedConfigurable;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -49,22 +45,38 @@ public class LibraryProjectStructureElement extends ProjectStructureElement {
final LibraryEx library = (LibraryEx)myContext.getLibraryModel(myLibrary);
if (library == null || library.isDisposed()) return;
final String libraryName = library.getName();
final List<String> invalidClasses = library.getInvalidRootUrls(OrderRootType.CLASSES);
if (!invalidClasses.isEmpty()) {
final String description = createInvalidRootsDescription(invalidClasses, libraryName);
problemsHolder.registerError(ProjectBundle.message("project.roots.tooltip.library.misconfigured", libraryName), description, createPlace(),
new RemoveInvalidRootsQuickFix(Collections.singletonMap(OrderRootType.CLASSES, invalidClasses), library));
}
final List<String> invalidJavadocs = library.getInvalidRootUrls(JavadocOrderRootType.getInstance());
final List<String> invalidSources = library.getInvalidRootUrls(OrderRootType.SOURCES);
if (!invalidJavadocs.isEmpty() || !invalidSources.isEmpty()) {
final Map<OrderRootType, List<String>> invalidRoots = new HashMap<OrderRootType, List<String>>();
invalidRoots.put(OrderRootType.SOURCES, invalidSources);
invalidRoots.put(JavadocOrderRootType.getInstance(), invalidJavadocs);
final String description = createInvalidRootsDescription(ContainerUtil.concat(invalidJavadocs, invalidSources), libraryName);
problemsHolder.registerWarning(ProjectBundle.message("project.roots.tooltip.library.misconfigured", libraryName), description, createPlace(),
new RemoveInvalidRootsQuickFix(invalidRoots, library));
//final String libraryName = library.getName();
reportInvalidRoots(problemsHolder, library, OrderRootType.CLASSES, ProjectStructureProblemType.error("library-invalid-classes-path"));
reportInvalidRoots(problemsHolder, library, OrderRootType.SOURCES, ProjectStructureProblemType.warning("library-invalid-source-javadoc-path"));
reportInvalidRoots(problemsHolder, library, JavadocOrderRootType.getInstance(), ProjectStructureProblemType.warning("library-invalid-source-javadoc-path"));
//if (!invalidClasses.isEmpty()) {
// final String description = createInvalidRootsDescription(invalidClasses, libraryName);
// problemsHolder.registerProblem(ProjectBundle.message("project.roots.error.message.invalid.classes.roots", invalidClasses.size()), description, ProjectStructureProblemType.error("library-invalid-classes-path"),
// createPlace(),
// new RemoveInvalidRootsQuickFix(Collections.singletonMap(OrderRootType.CLASSES, invalidClasses),
// library));
//}
//final List<String> invalidJavadocs = library.getInvalidRootUrls(JavadocOrderRootType.getInstance());
//final List<String> invalidSources = library.getInvalidRootUrls(OrderRootType.SOURCES);
//if (!invalidJavadocs.isEmpty() || !invalidSources.isEmpty()) {
// final Map<OrderRootType, List<String>> invalidRoots = new HashMap<OrderRootType, List<String>>();
// invalidRoots.put(OrderRootType.SOURCES, invalidSources);
// invalidRoots.put(JavadocOrderRootType.getInstance(), invalidJavadocs);
// final String description = createInvalidRootsDescription(ContainerUtil.concat(invalidJavadocs, invalidSources), libraryName);
// problemsHolder.registerProblem(ProjectBundle.message("project.roots.error.message.invalid.source.javadoc.roots", invalidJavadocs.size()+invalidSources.size()), description,
// ProjectStructureProblemType.warning("library-invalid-source-javadoc-path"),
// createPlace(),
// new RemoveInvalidRootsQuickFix(invalidRoots, library));
//}
}
private void reportInvalidRoots(ProjectStructureProblemsHolder problemsHolder,
LibraryEx library,
final OrderRootType type, final ProjectStructureProblemType problemType) {
final List<String> invalidClasses = library.getInvalidRootUrls(type);
for (String url : invalidClasses) {
problemsHolder.registerProblem("invalid path '" + url + "'", null, problemType,
createPlace(), new RemoveInvalidRootsQuickFix(Collections.singletonMap(type, Collections.singletonList(url)), library));
}
}
@@ -83,7 +95,7 @@ public class LibraryProjectStructureElement extends ProjectStructureElement {
@NotNull
private PlaceInProjectStructure createPlace() {
final Project project = myContext.getProject();
return new PlaceInProjectStructureBase(project, ProjectStructureConfigurable.getInstance(project).createProjectOrGlobalLibraryPlace(myLibrary));
return new PlaceInProjectStructureBase(project, ProjectStructureConfigurable.getInstance(project).createProjectOrGlobalLibraryPlace(myLibrary), this);
}
@Override
@@ -113,17 +125,22 @@ public class LibraryProjectStructureElement extends ProjectStructureElement {
return getSourceOrThis().hashCode();
}
@Override
public String toString() {
return "library:" + myLibrary.getName();
}
@Override
public boolean highlightIfUnused() {
final LibraryTable libraryTable = myLibrary.getTable();
return libraryTable != null && LibraryTablesRegistrar.PROJECT_LEVEL.equals(libraryTable.getTableLevel());
}
@Override
public String getPresentableName() {
return "Library '" + myLibrary.getName() + "'";
}
@Override
public String getId() {
return "library:" + myLibrary.getTable().getTableLevel() + ":" + myLibrary.getName();
}
private class RemoveInvalidRootsQuickFix extends ConfigurationErrorQuickFix {
private final Map<OrderRootType, List<String>> myInvalidRoots;
private final Library myLibrary;
@@ -41,7 +41,8 @@ public class ModuleProjectStructureElement extends ProjectStructureElement {
for (Module each : all) {
if (each != myModule && myContext.getRealName(each).equals(myContext.getRealName(myModule))) {
problemsHolder.registerError(ProjectBundle.message("project.roots.module.duplicate.name.message"), null, createPlace(), null);
problemsHolder.registerProblem(ProjectBundle.message("project.roots.module.duplicate.name.message"), null, ProjectStructureProblemType.error("duplicate-module-name"), createPlace(),
null);
break;
}
}
@@ -52,12 +53,13 @@ public class ModuleProjectStructureElement extends ProjectStructureElement {
for (OrderEntry entry : entries) {
if (!entry.isValid()){
if (entry instanceof JdkOrderEntry && ((JdkOrderEntry)entry).getJdkName() == null) {
problemsHolder.registerError(ProjectBundle.message("project.roots.module.jdk.problem.message"), null, createPlace(entry), null);
problemsHolder.registerProblem(ProjectBundle.message("project.roots.module.jdk.problem.message"), null, ProjectStructureProblemType.error("module-sdk-not-defined"), createPlace(entry),
null);
}
else {
problemsHolder.registerError(ProjectBundle.message("project.roots.library.problem.message", entry.getPresentableName()), null,
createPlace(entry),
null);
problemsHolder.registerProblem(ProjectBundle.message("project.roots.library.problem.message", entry.getPresentableName()), null,
ProjectStructureProblemType.error("invalid-module-dependency"), createPlace(entry),
null);
}
}
//todo[nik] highlight libraries with invalid paths in ClasspathEditor
@@ -77,11 +79,11 @@ public class ModuleProjectStructureElement extends ProjectStructureElement {
private PlaceInProjectStructure createPlace() {
final Project project = myContext.getProject();
return new PlaceInProjectStructureBase(project, ProjectStructureConfigurable.getInstance(project).createModulePlace(myModule));
return new PlaceInProjectStructureBase(project, ProjectStructureConfigurable.getInstance(project).createModulePlace(myModule), this);
}
private PlaceInProjectStructure createPlace(OrderEntry entry) {
return new PlaceInModuleClasspath(myContext, myModule, entry);
return new PlaceInModuleClasspath(myContext, myModule, this, entry);
}
@Override
@@ -127,13 +129,18 @@ public class ModuleProjectStructureElement extends ProjectStructureElement {
return myModule.hashCode();
}
@Override
public String toString() {
return "module:" + myModule.getName();
}
@Override
public boolean highlightIfUnused() {
return false;
}
@Override
public String getPresentableName() {
return "Module '" + myModule.getName() + "'";
}
@Override
public String getId() {
return "module:" + myModule.getName();
}
}
@@ -28,19 +28,22 @@ import org.jetbrains.annotations.NotNull;
* @author nik
*/
public class PlaceInModuleClasspath extends PlaceInProjectStructure {
private StructureConfigurableContext myContext;
private Module myModule;
private OrderEntry myOrderEntry;
private final StructureConfigurableContext myContext;
private final Module myModule;
private final ProjectStructureElement myElement;
private final OrderEntry myOrderEntry;
public PlaceInModuleClasspath(StructureConfigurableContext context, Module module, OrderEntry orderEntry) {
public PlaceInModuleClasspath(StructureConfigurableContext context, Module module, ProjectStructureElement element, OrderEntry orderEntry) {
myContext = context;
myModule = module;
myElement = element;
myOrderEntry = orderEntry;
}
public PlaceInModuleClasspath(@NotNull StructureConfigurableContext context, @NotNull Module module, @NotNull ProjectStructureElement elementInClasspath) {
public PlaceInModuleClasspath(@NotNull StructureConfigurableContext context, @NotNull Module module, ProjectStructureElement element, @NotNull ProjectStructureElement elementInClasspath) {
myContext = context;
myModule = module;
myElement = element;
ModuleRootModel rootModel = myContext.getModulesConfigurator().getRootModel(myModule);
if (elementInClasspath instanceof LibraryProjectStructureElement) {
myOrderEntry = OrderEntryUtil.findLibraryOrderEntry(rootModel, ((LibraryProjectStructureElement)elementInClasspath).getLibrary());
@@ -56,6 +59,17 @@ public class PlaceInModuleClasspath extends PlaceInProjectStructure {
}
}
@NotNull
@Override
public ProjectStructureElement getContainingElement() {
return myElement;
}
@Override
public String getPlacePath() {
return myOrderEntry != null ? myOrderEntry.getPresentableName() : null;
}
@NotNull
@Override
public ActionCallback navigate() {
@@ -17,11 +17,18 @@ package com.intellij.openapi.roots.ui.configuration.projectRoot.daemon;
import com.intellij.openapi.util.ActionCallback;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author nik
*/
public abstract class PlaceInProjectStructure {
@NotNull
public abstract ProjectStructureElement getContainingElement();
@Nullable
public abstract String getPlacePath();
@NotNull
public abstract ActionCallback navigate();
}
@@ -27,10 +27,23 @@ import org.jetbrains.annotations.NotNull;
public class PlaceInProjectStructureBase extends PlaceInProjectStructure {
private final Project myProject;
private final Place myPlace;
private final ProjectStructureElement myElement;
public PlaceInProjectStructureBase(Project project, Place place) {
public PlaceInProjectStructureBase(Project project, Place place, ProjectStructureElement element) {
myProject = project;
myPlace = place;
myElement = element;
}
@Override
public String getPlacePath() {
return null;
}
@NotNull
@Override
public ProjectStructureElement getContainingElement() {
return myElement;
}
@NotNull
@@ -12,10 +12,12 @@
*/
package com.intellij.openapi.roots.ui.configuration.projectRoot.daemon;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ui.configuration.ConfigurationError;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.PopupStep;
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -26,10 +28,28 @@ import java.util.List;
*/
class ProjectConfigurationProblem extends ConfigurationError {
private final ProjectStructureProblemDescription myDescription;
private final Project myProject;
public ProjectConfigurationProblem(ProjectStructureProblemDescription description) {
super(description.getMessage(), description.getDescription() != null ? description.getDescription() : description.getMessage());
public ProjectConfigurationProblem(ProjectStructureProblemDescription description, Project project) {
super(computeMessage(description), computeDescription(description),
ProjectStructureProblemsSettings.getInstance(project).isIgnored(description));
myDescription = description;
myProject = project;
}
private static String computeDescription(ProjectStructureProblemDescription description) {
final String descriptionString = description.getDescription();
return descriptionString != null ? descriptionString : computeMessage(description);
}
private static String computeMessage(ProjectStructureProblemDescription description) {
return description.getPlace().getContainingElement().getPresentableName() + ": " + StringUtil.decapitalize(description.getMessage());
}
@Override
public void ignore(boolean b) {
super.ignore(b);
ProjectStructureProblemsSettings.getInstance(myProject).setIgnored(myDescription, b);
}
@Override
@@ -67,7 +67,7 @@ public class ProjectConfigurationProblems {
final List<ProjectStructureProblemDescription> descriptions = problemsHolder.getProblemDescriptions();
if (descriptions != null) {
for (ProjectStructureProblemDescription description : descriptions) {
final ProjectConfigurationProblem error = new ProjectConfigurationProblem(description);
final ProjectConfigurationProblem error = new ProjectConfigurationProblem(description, myContext.getProject());
myErrors.put(element, error);
ConfigurationErrors.Bus.addError(error, myContext.getProject());
}
@@ -15,6 +15,10 @@ public abstract class ProjectStructureElement {
myContext = context;
}
public abstract String getPresentableName();
public abstract String getId();
public abstract void check(ProjectStructureProblemsHolder problemsHolder);
public abstract List<ProjectStructureElementUsage> getUsagesInElement();
@@ -26,4 +30,9 @@ public abstract class ProjectStructureElement {
@Override
public abstract int hashCode();
@Override
public String toString() {
return getId();
}
}
@@ -26,17 +26,20 @@ import java.util.List;
public class ProjectStructureProblemDescription {
private final String myMessage;
private final String myDescription;
private final Severity mySeverity;
private final PlaceInProjectStructure myPlace;
private final List<ConfigurationErrorQuickFix> myFixes;
private final ProjectStructureProblemType myProblemType;
public ProjectStructureProblemDescription(@NotNull String message, @Nullable String description, @NotNull Severity severity, @NotNull PlaceInProjectStructure place,
@NotNull List<ConfigurationErrorQuickFix> fixes) {
public ProjectStructureProblemDescription(@NotNull String message,
@Nullable String description,
@NotNull PlaceInProjectStructure place,
@NotNull List<ConfigurationErrorQuickFix> fixes,
@NotNull ProjectStructureProblemType problemType) {
myMessage = message;
myDescription = description;
mySeverity = severity;
myPlace = place;
myFixes = fixes;
myProblemType = problemType;
}
public String getMessage() {
@@ -52,13 +55,16 @@ public class ProjectStructureProblemDescription {
return myFixes;
}
public Severity getSeverity() {
return mySeverity;
public ProjectStructureProblemType.Severity getSeverity() {
return myProblemType.getSeverity();
}
public PlaceInProjectStructure getPlace() {
return myPlace;
}
public enum Severity { ERROR, WARNING }
public String getId() {
final String placePath = myPlace.getPlacePath();
return myProblemType.getId() + "(" + myPlace.getContainingElement().getId() + (placePath != null ? "," + placePath : "") + ")";
}
}
@@ -0,0 +1,51 @@
/*
* 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.roots.ui.configuration.projectRoot.daemon;
import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
public class ProjectStructureProblemType {
public enum Severity { ERROR, WARNING }
private final String myId;
private final Severity mySeverity;
public ProjectStructureProblemType(@NotNull String id, @NotNull Severity severity) {
myId = id;
mySeverity = severity;
}
public static ProjectStructureProblemType error(@NotNull String id) {
return new ProjectStructureProblemType(id, Severity.ERROR);
}
public static ProjectStructureProblemType warning(@NotNull String id) {
return new ProjectStructureProblemType(id, Severity.WARNING);
}
@NotNull
public String getId() {
return myId;
}
@NotNull
public Severity getSeverity() {
return mySeverity;
}
}
@@ -22,9 +22,8 @@ import org.jetbrains.annotations.Nullable;
* @author nik
*/
public interface ProjectStructureProblemsHolder {
void registerError(@NotNull String message, @Nullable String description, @NotNull PlaceInProjectStructure place, @Nullable ConfigurationErrorQuickFix fix);
void registerWarning(@NotNull String message, @Nullable String description, @NotNull PlaceInProjectStructure place, @Nullable ConfigurationErrorQuickFix fix);
void registerProblem(@NotNull String message, @Nullable String description, @NotNull ProjectStructureProblemType problemType,
@NotNull PlaceInProjectStructure place, @Nullable ConfigurationErrorQuickFix fix);
void registerProblem(@NotNull ProjectStructureProblemDescription description);
}
@@ -15,14 +15,12 @@ import java.util.List;
public class ProjectStructureProblemsHolderImpl implements ProjectStructureProblemsHolder {
private List<ProjectStructureProblemDescription> myProblemDescriptions;
public void registerError(@NotNull String message, String description, @NotNull PlaceInProjectStructure place, @Nullable ConfigurationErrorQuickFix fix) {
public void registerProblem(@NotNull String message, @Nullable String description,
@NotNull ProjectStructureProblemType problemType,
@NotNull PlaceInProjectStructure place,
@Nullable ConfigurationErrorQuickFix fix) {
final List<ConfigurationErrorQuickFix> fixes = fix != null ? Collections.singletonList(fix) : Collections.<ConfigurationErrorQuickFix>emptyList();
registerProblem(new ProjectStructureProblemDescription(message, description, ProjectStructureProblemDescription.Severity.ERROR, place, fixes));
}
public void registerWarning(@NotNull String message, String description, @NotNull PlaceInProjectStructure place, @Nullable ConfigurationErrorQuickFix fix) {
final List<ConfigurationErrorQuickFix> fixes = Collections.singletonList(fix);
registerProblem(new ProjectStructureProblemDescription(message, description, ProjectStructureProblemDescription.Severity.WARNING, place, fixes));
registerProblem(new ProjectStructureProblemDescription(message, description, place, fixes, problemType));
}
public void registerProblem(final @NotNull ProjectStructureProblemDescription description) {
@@ -33,16 +31,16 @@ public class ProjectStructureProblemsHolderImpl implements ProjectStructureProbl
}
@Nullable
public ProjectStructureProblemDescription.Severity getSeverity() {
public ProjectStructureProblemType.Severity getSeverity() {
if (myProblemDescriptions == null || myProblemDescriptions.isEmpty()) {
return null;
}
for (ProjectStructureProblemDescription description : myProblemDescriptions) {
if (description.getSeverity() == ProjectStructureProblemDescription.Severity.ERROR) {
return ProjectStructureProblemDescription.Severity.ERROR;
if (description.getSeverity() == ProjectStructureProblemType.Severity.ERROR) {
return ProjectStructureProblemType.Severity.ERROR;
}
}
return ProjectStructureProblemDescription.Severity.WARNING;
return ProjectStructureProblemType.Severity.WARNING;
}
public String composeTooltipMessage() {
@@ -0,0 +1,32 @@
/*
* 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.roots.ui.configuration.projectRoot.daemon;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
public abstract class ProjectStructureProblemsSettings {
public static ProjectStructureProblemsSettings getInstance(@NotNull Project project) {
return ServiceManager.getService(project, ProjectStructureProblemsSettings.class);
}
public abstract boolean isIgnored(@NotNull ProjectStructureProblemDescription description);
public abstract void setIgnored(@NotNull ProjectStructureProblemDescription description, boolean ignored);
}
@@ -0,0 +1,66 @@
/*
* 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.roots.ui.configuration.projectRoot.daemon;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.util.containers.SortedList;
import com.intellij.util.xmlb.XmlSerializerUtil;
import com.intellij.util.xmlb.annotations.AbstractCollection;
import com.intellij.util.xmlb.annotations.Tag;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* @author nik
*/
@State(
name = "ProjectStructureProblems",
storages = {@Storage(file = "$WORKSPACE_FILE$")}
)
public class ProjectStructureProblemsSettingsImpl extends ProjectStructureProblemsSettings implements PersistentStateComponent<ProjectStructureProblemsSettingsImpl> {
@AbstractCollection(surroundWithTag = false, elementTag = "problem", elementValueAttribute = "id")
@Tag("ignored-problems")
public List<String> myIgnoredProblems = new SortedList<String>(String.CASE_INSENSITIVE_ORDER);
@Override
public ProjectStructureProblemsSettingsImpl getState() {
return this;
}
@Override
public void loadState(ProjectStructureProblemsSettingsImpl state) {
XmlSerializerUtil.copyBean(state, this);
}
@Override
public boolean isIgnored(@NotNull ProjectStructureProblemDescription description) {
return myIgnoredProblems.contains(description.getId());
}
@Override
public void setIgnored(@NotNull ProjectStructureProblemDescription description, boolean ignored) {
final String id = description.getId();
if (ignored) {
myIgnoredProblems.add(id);
}
else {
myIgnoredProblems.remove(id);
}
}
}
@@ -43,13 +43,18 @@ public class SdkProjectStructureElement extends ProjectStructureElement {
return mySdk.hashCode();
}
@Override
public String toString() {
return "sdk:" + mySdk.getName();
}
@Override
public boolean highlightIfUnused() {
return false;
}
@Override
public String getPresentableName() {
return "SDK '" + mySdk.getName() + "'";
}
@Override
public String getId() {
return "sdk:" + mySdk.getName();
}
}
@@ -45,7 +45,7 @@ public class UsageInModuleClasspath extends ProjectStructureElementUsage {
@Override
public PlaceInProjectStructure getPlace() {
return new PlaceInModuleClasspath(myContext, myModule, mySourceElement);
return new PlaceInModuleClasspath(myContext, myModule, myContainingElement, mySourceElement);
}
@Override