validation in artifacts migrated to use ProjectStructureDaemonAnalyzer

This commit is contained in:
nik
2009-11-17 15:33:41 +03:00
parent 7aadc6b65b
commit 2be654964d
24 changed files with 407 additions and 176 deletions
@@ -15,7 +15,7 @@
*/
package com.intellij.packaging.impl.ui;
import com.intellij.packaging.ui.ArtifactValidationManager;
import com.intellij.packaging.ui.ArtifactProblemsHolder;
import com.intellij.packaging.ui.ArtifactEditorContext;
import com.intellij.packaging.ui.ArtifactProblemQuickFix;
import org.jetbrains.annotations.NotNull;
@@ -24,10 +24,10 @@ import org.jetbrains.annotations.Nullable;
/**
* @author nik
*/
public abstract class ArtifactValidationManagerBase implements ArtifactValidationManager {
public abstract class ArtifactProblemsHolderBase implements ArtifactProblemsHolder {
private ArtifactEditorContext myContext;
protected ArtifactValidationManagerBase(ArtifactEditorContext context) {
protected ArtifactProblemsHolderBase(ArtifactEditorContext context) {
myContext = context;
}
@@ -21,7 +21,7 @@ import com.intellij.packaging.elements.CompositePackagingElement;
import com.intellij.packaging.elements.PackagingElement;
import com.intellij.packaging.elements.PackagingElementOutputKind;
import com.intellij.packaging.elements.PackagingElementResolvingContext;
import com.intellij.packaging.ui.ArtifactValidationManager;
import com.intellij.packaging.ui.ArtifactProblemsHolder;
import com.intellij.packaging.ui.PackagingSourceItem;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -50,7 +50,7 @@ public abstract class ArtifactType {
public String getPresentableName() {
return myTitle;
}
}
@NotNull
public abstract Icon getIcon();
@@ -89,7 +89,7 @@ public abstract class ArtifactType {
return Collections.emptyList();
}
public void checkRootElement(@NotNull CompositePackagingElement<?> rootElement, @NotNull Artifact artifact, @NotNull ArtifactValidationManager manager) {
public void checkRootElement(@NotNull CompositePackagingElement<?> rootElement, @NotNull Artifact artifact, @NotNull ArtifactProblemsHolder manager) {
}
@Nullable
@@ -22,7 +22,7 @@ import org.jetbrains.annotations.Nullable;
/**
* @author nik
*/
public interface ArtifactValidationManager {
public interface ArtifactProblemsHolder {
ArtifactEditorContext getContext();
@@ -67,14 +67,8 @@ public class ModulesConfigurator implements ModulesProvider, ModuleEditor.Change
private static final Logger LOG = Logger.getInstance("#" + ModulesConfigurator.class.getName());
private final Project myProject;
//private final ModuleStructureConfigurable myProjectRootConfigurable;
private boolean myModified = false;
private final ProjectConfigurable myProjectConfigurable;
private final List<ModuleEditor> myModuleEditors = new ArrayList<ModuleEditor>();
private final Comparator<ModuleEditor> myModuleEditorComparator = new Comparator<ModuleEditor>() {
final ModulesAlphaComparator myModulesComparator = new ModulesAlphaComparator();
@@ -87,10 +81,12 @@ public class ModulesConfigurator implements ModulesProvider, ModuleEditor.Change
return false;
}
};
private boolean myModified = false;
private ModifiableModuleModel myModuleModel;
private ProjectFacetsConfigurator myFacetsConfigurator;
private StructureConfigurableContext myContext;
private List<ModuleEditor.ChangeListener> myAllModulesChangeListeners = new ArrayList<ModuleEditor.ChangeListener>();
public ModulesConfigurator(Project project, ProjectJdksModel projectJdksModel) {
myProject = project;
@@ -211,6 +207,13 @@ public class ModulesConfigurator implements ModulesProvider, ModuleEditor.Change
public void moduleStateChanged(final ModifiableRootModel moduleRootModel) {
myProjectConfigurable.updateCircularDependencyWarning();
for (ModuleEditor.ChangeListener listener : myAllModulesChangeListeners) {
listener.moduleStateChanged(moduleRootModel);
}
}
public void addAllModuleChangeListener(ModuleEditor.ChangeListener listener) {
myAllModulesChangeListeners.add(listener);
}
public GraphGenerator<ModifiableRootModel> createGraphGenerator() {
@@ -18,7 +18,6 @@ package com.intellij.openapi.roots.ui.configuration.artifacts;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectStructureElementConfigurable;
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.util.Comparing;
@@ -41,13 +40,12 @@ public class ArtifactConfigurable extends ProjectStructureElementConfigurable<Ar
private boolean myIsInUpdateName;
private ProjectStructureElement myProjectStructureElement;
public ArtifactConfigurable(Artifact originalArtifact, ArtifactsStructureConfigurableContextImpl artifactsStructureContext, final Runnable updateTree,
StructureConfigurableContext context) {
public ArtifactConfigurable(Artifact originalArtifact, ArtifactsStructureConfigurableContextImpl artifactsStructureContext, final Runnable updateTree) {
super(true, updateTree);
myOriginalArtifact = originalArtifact;
myArtifactsStructureContext = artifactsStructureContext;
myEditor = artifactsStructureContext.getOrCreateEditor(originalArtifact);
myProjectStructureElement = new ArtifactProjectStructureElement(context, myArtifactsStructureContext, myOriginalArtifact);
myProjectStructureElement = myArtifactsStructureContext.getOrCreateArtifactElement(myOriginalArtifact);
}
public void setDisplayName(String name) {
@@ -50,7 +50,6 @@ import java.util.List;
public class ArtifactEditorContextImpl implements ArtifactEditorContext {
private final ArtifactsStructureConfigurableContext myParent;
private final ArtifactEditorEx myEditor;
private ArtifactValidationManagerImpl myValidationManager;
public ArtifactEditorContextImpl(ArtifactsStructureConfigurableContext parent, ArtifactEditorEx editor) {
myParent = parent;
@@ -155,7 +154,7 @@ public class ArtifactEditorContextImpl implements ArtifactEditorContext {
}
public void queueValidation() {
myEditor.queueValidation();
myParent.queueValidation(getArtifact());
}
@NotNull
@@ -163,14 +162,6 @@ public class ArtifactEditorContextImpl implements ArtifactEditorContext {
return myEditor.getArtifact().getArtifactType();
}
public ArtifactValidationManagerImpl getValidationManager() {
return myValidationManager;
}
public void setValidationManager(ArtifactValidationManagerImpl validationManager) {
myValidationManager = validationManager;
}
public List<Module> chooseModules(final List<Module> modules, final String title) {
ChooseModulesDialog dialog = new ChooseModulesDialog(getProject(), modules, title, null);
dialog.show();
@@ -111,7 +111,6 @@ public class ArtifactEditorImpl implements ArtifactEditorEx {
});
setOutputPath(outputPath);
myValidationManager = new ArtifactValidationManagerImpl(this);
myContext.setValidationManager(myValidationManager);
updateShowContentCheckbox();
}
@@ -174,7 +173,7 @@ public class ArtifactEditorImpl implements ArtifactEditorEx {
}
public void queueValidation() {
myValidationManager.queueValidation();
myContext.queueValidation();
}
public JComponent createMainComponent() {
@@ -400,6 +399,10 @@ public class ArtifactEditorImpl implements ArtifactEditorEx {
myLayoutTreeComponent.setRootElement(newRootElement);
}
public ArtifactValidationManagerImpl getValidationManager() {
return myValidationManager;
}
private class MyDataProvider implements TypeSafeDataProvider {
public void calcData(DataKey key, DataSink sink) {
if (ARTIFACTS_EDITOR_KEY.equals(key)) {
@@ -0,0 +1,57 @@
/*
* Copyright 2000-2009 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.artifacts;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemDescription;
import com.intellij.packaging.elements.PackagingElement;
import com.intellij.packaging.ui.ArtifactProblemQuickFix;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author nik
*/
public class ArtifactProblemDescription extends ProjectStructureProblemDescription {
private ArtifactProblemQuickFix myQuickFix;
private PackagingElement<?> myPlace;
public ArtifactProblemDescription(@NotNull String message, @NotNull Severity severity) {
super(message, severity);
}
public ArtifactProblemDescription(@NotNull String message, @NotNull Severity severity, @Nullable ArtifactProblemQuickFix quickFix) {
super(message, severity);
myQuickFix = quickFix;
}
public ArtifactProblemDescription(@NotNull String message,
@NotNull Severity severity,
@Nullable PackagingElement<?> place,
@Nullable ArtifactProblemQuickFix quickFix) {
super(message, severity);
myPlace = place;
myQuickFix = quickFix;
}
@Nullable
public ArtifactProblemQuickFix getQuickFix() {
return myQuickFix;
}
public PackagingElement<?> getPlace() {
return myPlace;
}
}
@@ -0,0 +1,41 @@
/*
* Copyright 2000-2009 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.artifacts;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemDescription;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemsHolder;
import com.intellij.packaging.elements.PackagingElement;
import com.intellij.packaging.impl.ui.ArtifactProblemsHolderBase;
import com.intellij.packaging.ui.ArtifactEditorContext;
import com.intellij.packaging.ui.ArtifactProblemQuickFix;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author nik
*/
public class ArtifactProblemsHolderImpl extends ArtifactProblemsHolderBase {
private ProjectStructureProblemsHolder myProblemsHolder;
public ArtifactProblemsHolderImpl(ArtifactEditorContext context, ProjectStructureProblemsHolder problemsHolder) {
super(context);
myProblemsHolder = problemsHolder;
}
public void registerProblem(@NotNull String message, @Nullable PackagingElement<?> place, @Nullable ArtifactProblemQuickFix quickFix) {
myProblemsHolder.registerProblem(new ArtifactProblemDescription(message, ProjectStructureProblemDescription.Severity.ERROR, place, quickFix));
}
}
@@ -39,15 +39,23 @@ public class ArtifactProjectStructureElement extends ProjectStructureElement {
private final ArtifactsStructureConfigurableContext myArtifactsStructureContext;
private final Artifact myOriginalArtifact;
public ArtifactProjectStructureElement(StructureConfigurableContext context,
ArtifactsStructureConfigurableContext artifactsStructureContext, Artifact artifact) {
ArtifactProjectStructureElement(StructureConfigurableContext context,
ArtifactsStructureConfigurableContext artifactsStructureContext, Artifact artifact) {
super(context);
myArtifactsStructureContext = artifactsStructureContext;
myOriginalArtifact = artifactsStructureContext.getOriginalArtifact(artifact);
}
@Override
public void check(ProjectStructureProblemsHolder problemsHolder) {
public void check(final ProjectStructureProblemsHolder problemsHolder) {
final ArtifactEditorEx artifactEditor = (ArtifactEditorEx)myArtifactsStructureContext.getOrCreateEditor(myOriginalArtifact);
artifactEditor.getLayoutTreeComponent().saveElementProperties();
final Artifact artifact = artifactEditor.getArtifact();
artifact.getArtifactType().checkRootElement(artifactEditor.getRootElement(), artifact, new ArtifactProblemsHolderImpl(artifactEditor.getContext(), problemsHolder));
}
public Artifact getOriginalArtifact() {
return myOriginalArtifact;
}
@Override
@@ -74,8 +82,7 @@ public class ArtifactProjectStructureElement extends ProjectStructureElement {
else if (packagingElement instanceof ArtifactPackagingElement) {
final Artifact usedArtifact = ((ArtifactPackagingElement)packagingElement).findArtifact(myArtifactsStructureContext);
if (usedArtifact != null) {
final ArtifactProjectStructureElement artifactElement =
new ArtifactProjectStructureElement(myContext, myArtifactsStructureContext, usedArtifact);
final ArtifactProjectStructureElement artifactElement = myArtifactsStructureContext.getOrCreateArtifactElement(usedArtifact);
usages.add(new UsageInArtifact(myOriginalArtifact, myArtifactsStructureContext, artifactElement,
ArtifactProjectStructureElement.this, getPathFromRoot(parents, "/"), packagingElement));
}
@@ -109,4 +116,5 @@ public class ArtifactProjectStructureElement extends ProjectStructureElement {
public boolean highlightIfUnused() {
return false;
}
}
@@ -18,60 +18,32 @@ package com.intellij.openapi.roots.ui.configuration.artifacts;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.roots.ui.configuration.artifacts.nodes.CompositePackagingElementNode;
import com.intellij.openapi.roots.ui.configuration.artifacts.nodes.PackagingElementNode;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemDescription;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemsHolderImpl;
import com.intellij.openapi.util.Disposer;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.packaging.elements.PackagingElement;
import com.intellij.packaging.impl.ui.ArtifactValidationManagerBase;
import com.intellij.packaging.ui.ArtifactProblemQuickFix;
import com.intellij.util.ui.update.MergingUpdateQueue;
import com.intellij.util.ui.update.Update;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author nik
*/
public class ArtifactValidationManagerImpl extends ArtifactValidationManagerBase implements Disposable {
private MergingUpdateQueue myValidationQueue;
public class ArtifactValidationManagerImpl implements Disposable {
private ArtifactErrorPanel myErrorPanel;
private final ArtifactEditorImpl myArtifactEditor;
private Map<PackagingElementNode<?>, String> myErrorsForNodes = new HashMap<PackagingElementNode<?>, String>();
private Map<PackagingElement<?>, String> myErrorsForElements = new HashMap<PackagingElement<?>, String>();
ArtifactValidationManagerImpl(ArtifactEditorImpl artifactEditor) {
super(artifactEditor.getContext());
Disposer.register(artifactEditor, this);
myArtifactEditor = artifactEditor;
myErrorPanel = new ArtifactErrorPanel(artifactEditor);
final JComponent mainComponent = artifactEditor.getMainComponent();
myValidationQueue = new MergingUpdateQueue("ArtifactValidation", 300, false, mainComponent, this, mainComponent);
}
private void runValidation() {
myErrorPanel.clearError();
myErrorsForNodes.clear();
myErrorsForElements.clear();
myArtifactEditor.getLayoutTreeComponent().saveElementProperties();
final Artifact artifact = myArtifactEditor.getArtifact();
artifact.getArtifactType().checkRootElement(myArtifactEditor.getRootElement(), artifact, this);
myArtifactEditor.getLayoutTreeComponent().updateTreeNodesPresentation();
}
public void registerProblem(@NotNull String message, @Nullable PackagingElement<?> place, @Nullable ArtifactProblemQuickFix quickFix) {
if (place != null) {
final LayoutTree layoutTree = myArtifactEditor.getLayoutTreeComponent().getLayoutTree();
myErrorsForElements.put(place, message);
final List<PackagingElementNode<?>> nodes = layoutTree.findNodes(Collections.singletonList(place));
for (PackagingElementNode<?> node : nodes) {
addNodeToErrorsWithParents(node, message);
}
}
myErrorPanel.showError(message, quickFix);
}
private void addNodeToErrorsWithParents(PackagingElementNode<?> node, String message) {
@@ -87,14 +59,6 @@ public class ArtifactValidationManagerImpl extends ArtifactValidationManagerBase
public void dispose() {
}
public void queueValidation() {
myValidationQueue.queue(new Update("validate") {
public void run() {
runValidation();
}
});
}
public JComponent getMainErrorPanel() {
return myErrorPanel.getMainPanel();
}
@@ -110,4 +74,33 @@ public class ArtifactValidationManagerImpl extends ArtifactValidationManagerBase
public String getProblem(PackagingElementNode<?> node) {
return myErrorsForNodes.get(node);
}
public void updateProblems(@Nullable ProjectStructureProblemsHolderImpl holder) {
myErrorPanel.clearError();
myErrorsForNodes.clear();
myErrorsForElements.clear();
if (holder != null) {
final List<ProjectStructureProblemDescription> problemDescriptions = holder.getProblemDescriptions();
if (problemDescriptions != null) {
for (ProjectStructureProblemDescription description : problemDescriptions) {
final String message = description.getMessage();
ArtifactProblemQuickFix quickFix = null;
if (description instanceof ArtifactProblemDescription) {
quickFix = ((ArtifactProblemDescription)description).getQuickFix();
final PackagingElement<?> place = ((ArtifactProblemDescription)description).getPlace();
if (place != null) {
final LayoutTree layoutTree = myArtifactEditor.getLayoutTreeComponent().getLayoutTree();
myErrorsForElements.put(place, message);
final List<PackagingElementNode<?>> nodes = layoutTree.findNodes(Collections.singletonList(place));
for (PackagingElementNode<?> node : nodes) {
addNodeToErrorsWithParents(node, message);
}
}
}
myErrorPanel.showError(message, quickFix);
}
}
}
myArtifactEditor.getLayoutTreeComponent().updateTreeNodesPresentation();
}
}
@@ -27,6 +27,8 @@ import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ui.configuration.ModuleEditor;
import com.intellij.openapi.roots.ui.configuration.projectRoot.BaseStructureConfigurable;
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
@@ -64,7 +66,15 @@ public class ArtifactsStructureConfigurable extends BaseStructureConfigurable {
public void artifactAdded(@NotNull Artifact artifact) {
final MyNode node = addArtifactNode(artifact);
selectNodeInTree(node);
myContext.getDaemonAnalyzer().queueUpdate(new ArtifactProjectStructureElement(myContext, myPackagingEditorContext, artifact));
myContext.getDaemonAnalyzer().queueUpdate(myPackagingEditorContext.getOrCreateArtifactElement(artifact));
}
});
context.getModulesConfigurator().addAllModuleChangeListener(new ModuleEditor.ChangeListener() {
public void moduleStateChanged(ModifiableRootModel moduleRootModel) {
for (ProjectStructureElement element : getProjectStructureElements()) {
myContext.getDaemonAnalyzer().queueUpdate(element, true, false);
}
}
});
}
@@ -87,13 +97,13 @@ public class ArtifactsStructureConfigurable extends BaseStructureConfigurable {
protected Collection<? extends ProjectStructureElement> getProjectStructureElements() {
final List<ProjectStructureElement> elements = new ArrayList<ProjectStructureElement>();
for (Artifact artifact : myPackagingEditorContext.getArtifactModel().getArtifacts()) {
elements.add(new ArtifactProjectStructureElement(myContext, myPackagingEditorContext, artifact));
elements.add(myPackagingEditorContext.getOrCreateArtifactElement(artifact));
}
return elements;
}
private MyNode addArtifactNode(final Artifact artifact) {
final MyNode node = new MyNode(new ArtifactConfigurable(artifact, myPackagingEditorContext, TREE_UPDATER, myContext));
final MyNode node = new MyNode(new ArtifactConfigurable(artifact, myPackagingEditorContext, TREE_UPDATER));
addNode(node, myRoot);
return node;
}
@@ -216,7 +226,7 @@ public class ArtifactsStructureConfigurable extends BaseStructureConfigurable {
@Override
protected void removeArtifact(Artifact artifact) {
myPackagingEditorContext.getOrCreateModifiableArtifactModel().removeArtifact(artifact);
myContext.getDaemonAnalyzer().removeElement(new ArtifactProjectStructureElement(myContext, myPackagingEditorContext, artifact));
myContext.getDaemonAnalyzer().removeElement(myPackagingEditorContext.getOrCreateArtifactElement(artifact));
}
protected void processRemovedItems() {
@@ -49,4 +49,9 @@ public interface ArtifactsStructureConfigurableContext extends PackagingElementR
@Nullable
ModifiableModuleModel getModifiableModuleModel();
void queueValidation(Artifact artifact);
@NotNull
ArtifactProjectStructureElement getOrCreateArtifactElement(@NotNull Artifact artifact);
}
@@ -15,11 +15,16 @@
*/
package com.intellij.openapi.roots.ui.configuration.artifacts;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ui.configuration.FacetsProvider;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureDaemonAnalyzerListener;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemsHolderImpl;
import com.intellij.openapi.util.Disposer;
import com.intellij.packaging.artifacts.*;
import com.intellij.packaging.elements.CompositePackagingElement;
@@ -34,7 +39,7 @@ import java.util.Map;
/**
* @author nik
*/
class ArtifactsStructureConfigurableContextImpl implements ArtifactsStructureConfigurableContext {
public class ArtifactsStructureConfigurableContextImpl implements ArtifactsStructureConfigurableContext {
private ModifiableArtifactModel myModifiableModel;
private final ManifestFilesInfo myManifestFilesInfo = new ManifestFilesInfo();
private ArtifactAdapter myModifiableModelListener;
@@ -43,6 +48,7 @@ class ArtifactsStructureConfigurableContextImpl implements ArtifactsStructureCon
private Map<Artifact, CompositePackagingElement<?>> myModifiableRoots = new HashMap<Artifact, CompositePackagingElement<?>>();
private Map<Artifact, ArtifactEditorImpl> myArtifactEditors = new HashMap<Artifact, ArtifactEditorImpl>();
private Map<ArtifactPointer, ArtifactEditorSettings> myEditorSettings = new HashMap<ArtifactPointer, ArtifactEditorSettings>();
private Map<Artifact, ArtifactProjectStructureElement> myArtifactElements = new HashMap<Artifact, ArtifactProjectStructureElement>();
private final ArtifactEditorSettings myDefaultSettings;
public ArtifactsStructureConfigurableContextImpl(StructureConfigurableContext context, Project project,
@@ -51,6 +57,31 @@ class ArtifactsStructureConfigurableContextImpl implements ArtifactsStructureCon
myModifiableModelListener = modifiableModelListener;
myContext = context;
myProject = project;
context.getDaemonAnalyzer().addListener(new ProjectStructureDaemonAnalyzerListener() {
public void usagesCollected(@NotNull ProjectStructureElement containingElement) {
}
public void problemsChanged(@NotNull ProjectStructureElement element) {
if (element instanceof ArtifactProjectStructureElement) {
final Artifact originalArtifact = ((ArtifactProjectStructureElement)element).getOriginalArtifact();
final ArtifactEditorImpl artifactEditor = myArtifactEditors.get(originalArtifact);
if (artifactEditor != null) {
updateProblems(originalArtifact, artifactEditor);
}
}
}
public void allProblemsChanged() {
for (Map.Entry<Artifact, ArtifactEditorImpl> entry : myArtifactEditors.entrySet()) {
updateProblems(entry.getKey(), entry.getValue());
}
}
});
}
private void updateProblems(Artifact originalArtifact, ArtifactEditorImpl artifactEditor) {
final ProjectStructureProblemsHolderImpl holder = myContext.getDaemonAnalyzer().getProblemsHolder(getOrCreateArtifactElement(originalArtifact));
artifactEditor.getValidationManager().updateProblems(holder);
}
@NotNull
@@ -78,6 +109,10 @@ class ArtifactsStructureConfigurableContextImpl implements ArtifactsStructureCon
return myContext.getModulesConfigurator().getModuleModel();
}
public void queueValidation(Artifact artifact) {
myContext.getDaemonAnalyzer().queueUpdate(getOrCreateArtifactElement(artifact), true, false);
}
public CompositePackagingElement<?> getRootElement(@NotNull Artifact artifact) {
artifact = getOriginalArtifact(artifact);
if (myModifiableModel != null) {
@@ -98,14 +133,18 @@ class ArtifactsStructureConfigurableContextImpl implements ArtifactsStructureCon
return root;
}
public void editLayout(@NotNull Artifact artifact, Runnable action) {
artifact = getOriginalArtifact(artifact);
final ModifiableArtifact modifiableArtifact = getOrCreateModifiableArtifactModel().getOrCreateModifiableArtifact(artifact);
if (modifiableArtifact.getRootElement() == artifact.getRootElement()) {
modifiableArtifact.setRootElement(getOrCreateModifiableRootElement(artifact));
}
action.run();
myContext.getDaemonAnalyzer().queueUpdate(new ArtifactProjectStructureElement(myContext, this, artifact));
public void editLayout(@NotNull final Artifact artifact, final Runnable action) {
final Artifact originalArtifact = getOriginalArtifact(artifact);
new WriteAction() {
protected void run(final Result result) {
final ModifiableArtifact modifiableArtifact = getOrCreateModifiableArtifactModel().getOrCreateModifiableArtifact(originalArtifact);
if (modifiableArtifact.getRootElement() == originalArtifact.getRootElement()) {
modifiableArtifact.setRootElement(getOrCreateModifiableRootElement(originalArtifact));
}
action.run();
}
}.execute();
myContext.getDaemonAnalyzer().queueUpdate(getOrCreateArtifactElement(originalArtifact));
}
public ArtifactEditorImpl getOrCreateEditor(Artifact artifact) {
@@ -175,6 +214,7 @@ class ArtifactsStructureConfigurableContextImpl implements ArtifactsStructureCon
if (myModifiableModel != null) {
myModifiableModel.dispose();
}
myArtifactElements.clear();
}
public void saveEditorSettings() {
@@ -184,4 +224,14 @@ class ArtifactsStructureConfigurableContextImpl implements ArtifactsStructureCon
myEditorSettings.put(pointer, artifactEditor.createSettings());
}
}
@NotNull
public ArtifactProjectStructureElement getOrCreateArtifactElement(@NotNull Artifact artifact) {
ArtifactProjectStructureElement element = myArtifactElements.get(getOriginalArtifact(artifact));
if (element == null) {
element = new ArtifactProjectStructureElement(myContext, this, artifact);
myArtifactElements.put(artifact, element);
}
return element;
}
}
@@ -19,7 +19,6 @@ import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable;
import com.intellij.openapi.roots.ui.configuration.artifacts.ArtifactProjectStructureElement;
import com.intellij.openapi.roots.ui.configuration.artifacts.ArtifactsStructureConfigurableContext;
import com.intellij.openapi.roots.ui.configuration.artifacts.nodes.ArtifactsTreeNode;
import com.intellij.openapi.roots.ui.configuration.projectRoot.FindUsagesInProjectStructureActionBase;
@@ -67,7 +66,7 @@ public abstract class ArtifactEditorFindUsagesActionBase extends FindUsagesInPro
return new LibraryProjectStructureElement(context, (Library)sourceObject);
}
else if (sourceObject instanceof Artifact) {
return new ArtifactProjectStructureElement(context, myArtifactContext, (Artifact)sourceObject);
return myArtifactContext.getOrCreateArtifactElement((Artifact)sourceObject);
}
return null;
}
@@ -18,7 +18,7 @@ package com.intellij.openapi.roots.ui.configuration.artifacts.nodes;
import com.intellij.ide.projectView.PresentationData;
import com.intellij.openapi.editor.markup.EffectType;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.roots.ui.configuration.artifacts.ArtifactEditorContextImpl;
import com.intellij.openapi.roots.ui.configuration.artifacts.ArtifactEditorImpl;
import com.intellij.openapi.util.MultiValuesMap;
import com.intellij.packaging.elements.CompositePackagingElement;
import com.intellij.packaging.elements.PackagingElement;
@@ -55,7 +55,7 @@ public class PackagingElementNode<E extends PackagingElement<?>> extends Artifac
private void doAddElement(E packagingElement) {
myPackagingElements.add(packagingElement);
((ArtifactEditorContextImpl)myContext).getValidationManager().elementAddedToNode(this, packagingElement);
((ArtifactEditorImpl)myContext.getThisArtifactEditor()).getValidationManager().elementAddedToNode(this, packagingElement);
}
@Nullable
@@ -93,7 +93,7 @@ public class PackagingElementNode<E extends PackagingElement<?>> extends Artifac
@Override
protected void update(PresentationData presentation) {
final String message = ((ArtifactEditorContextImpl)myContext).getValidationManager().getProblem(this);
final String message = ((ArtifactEditorImpl)myContext.getThisArtifactEditor()).getValidationManager().getProblem(this);
if (message == null) {
super.update(presentation);
return;
@@ -104,7 +104,7 @@ public class PackagingElementNode<E extends PackagingElement<?>> extends Artifac
presentation.setTooltip(message);
}
private SimpleTextAttributes addErrorHighlighting(SimpleTextAttributes attributes) {
private static SimpleTextAttributes addErrorHighlighting(SimpleTextAttributes attributes) {
final TextAttributes textAttributes = attributes.toTextAttributes();
textAttributes.setEffectType(EffectType.WAVE_UNDERSCORE);
textAttributes.setEffectColor(Color.RED);
@@ -30,10 +30,7 @@ import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureDaemonAnalyzer;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemDescription;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemsHolder;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.*;
import com.intellij.openapi.ui.MasterDetailsComponent;
import com.intellij.openapi.ui.NamedConfigurable;
import com.intellij.openapi.util.ActionCallback;
@@ -77,8 +74,20 @@ public abstract class BaseStructureConfigurable extends MasterDetailsComponent i
public void init(StructureConfigurableContext context) {
myContext = context;
myContext.getDaemonAnalyzer().addListener(new Runnable() {
public void run() {
myContext.getDaemonAnalyzer().addListener(new ProjectStructureDaemonAnalyzerListener() {
public void usagesCollected(@NotNull ProjectStructureElement containingElement) {
updateTree();
}
public void problemsChanged(@NotNull ProjectStructureElement element) {
updateTree();
}
public void allProblemsChanged() {
updateTree();
}
private void updateTree() {
if (!myTree.isShowing()) return;
myTree.revalidate();
@@ -173,7 +182,7 @@ public abstract class BaseStructureConfigurable extends MasterDetailsComponent i
if (projectStructureElement != null) {
final ProjectStructureDaemonAnalyzer daemonAnalyzer = myContext.getDaemonAnalyzer();
final boolean unused = daemonAnalyzer.isUnused(projectStructureElement);
final ProjectStructureProblemsHolder problemsHolder = daemonAnalyzer.getProblemsHolder(projectStructureElement);
final ProjectStructureProblemsHolderImpl problemsHolder = daemonAnalyzer.getProblemsHolder(projectStructureElement);
if (problemsHolder == null) {
daemonAnalyzer.queueUpdate(projectStructureElement, true, false);
}
@@ -34,10 +34,10 @@ public class LibraryProjectStructureElement extends ProjectStructureElement {
final LibraryEx library = (LibraryEx)myLibrary;
final String libraryName = myLibrary.getName();//todo[nik] get modified name?
if (!library.allPathsValid(OrderRootType.CLASSES)) {
problemsHolder.addError(ProjectBundle.message("project.roots.tooltip.library.misconfigured", libraryName));
problemsHolder.registerError(ProjectBundle.message("project.roots.tooltip.library.misconfigured", libraryName));
}
else if (!library.allPathsValid(JavadocOrderRootType.getInstance()) || !library.allPathsValid(OrderRootType.SOURCES)) {
problemsHolder.addWarning(ProjectBundle.message("project.roots.tooltip.library.misconfigured", libraryName));
problemsHolder.registerWarning(ProjectBundle.message("project.roots.tooltip.library.misconfigured", libraryName));
}
}
@@ -34,7 +34,7 @@ public class ModuleProjectStructureElement extends ProjectStructureElement {
final Module[] all = moduleModel.getModules();
for (Module each : all) {
if (each != myModule && myContext.getRealName(each).equals(myContext.getRealName(myModule))) {
problemsHolder.addError(ProjectBundle.message("project.roots.module.duplicate.name.message"));
problemsHolder.registerError(ProjectBundle.message("project.roots.module.duplicate.name.message"));
break;
}
}
@@ -45,9 +45,9 @@ public class ModuleProjectStructureElement extends ProjectStructureElement {
for (OrderEntry entry : entries) {
if (!entry.isValid()){
if (entry instanceof JdkOrderEntry && ((JdkOrderEntry)entry).getJdkName() == null) {
problemsHolder.addError(ProjectBundle.message("project.roots.module.jdk.problem.message"));
problemsHolder.registerError(ProjectBundle.message("project.roots.module.jdk.problem.message"));
} else {
problemsHolder.addError(ProjectBundle.message("project.roots.library.problem.message", entry.getPresentableName()));
problemsHolder.registerError(ProjectBundle.message("project.roots.library.problem.message", entry.getPresentableName()));
}
}
}
@@ -7,9 +7,11 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.MultiValuesMap;
import com.intellij.util.EventDispatcher;
import com.intellij.util.ui.update.MergingUpdateQueue;
import com.intellij.util.ui.update.Update;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.*;
@@ -20,12 +22,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
*/
public class ProjectStructureDaemonAnalyzer implements Disposable {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.ui.configuration.projectRoot.validation.ProjectStructureDaemonAnalyzer");
private Map<ProjectStructureElement, ProjectStructureProblemsHolder> myProblemHolders = new HashMap<ProjectStructureElement, ProjectStructureProblemsHolder>();
private Map<ProjectStructureElement, ProjectStructureProblemsHolderImpl> myProblemHolders = new HashMap<ProjectStructureElement, ProjectStructureProblemsHolderImpl>();
private MultiValuesMap<ProjectStructureElement, ProjectStructureElementUsage> mySourceElement2Usages = new MultiValuesMap<ProjectStructureElement, ProjectStructureElementUsage>();
private MultiValuesMap<ProjectStructureElement, ProjectStructureElementUsage> myContainingElement2Usages = new MultiValuesMap<ProjectStructureElement, ProjectStructureElementUsage>();
private Set<ProjectStructureElement> myElementWithNotCalculatedUsages = new HashSet<ProjectStructureElement>();
private MergingUpdateQueue myAnalyzerQueue;
private List<Runnable> myListeners = new ArrayList<Runnable>();
private final EventDispatcher<ProjectStructureDaemonAnalyzerListener> myDispatcher = EventDispatcher.create(ProjectStructureDaemonAnalyzerListener.class);
private final AtomicBoolean myStopped = new AtomicBoolean(false);
public ProjectStructureDaemonAnalyzer(StructureConfigurableContext context) {
@@ -45,7 +47,7 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
}
private void doCheck(final ProjectStructureElement element) {
final ProjectStructureProblemsHolder problemsHolder = new ProjectStructureProblemsHolder();
final ProjectStructureProblemsHolderImpl problemsHolder = new ProjectStructureProblemsHolderImpl();
new ReadAction() {
protected void run(final Result result) {
if (myStopped.get()) return;
@@ -64,18 +66,11 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
LOG.debug("updating problems for " + element);
}
myProblemHolders.put(element, problemsHolder);
fireProblemsUpdated();
myDispatcher.getMulticaster().problemsChanged(element);
}
});
}
private void fireProblemsUpdated() {
Runnable[] listeners = myListeners.toArray(new Runnable[myListeners.size()]);
for (Runnable listener : listeners) {
listener.run();
}
}
private void doCollectUsages(final ProjectStructureElement element) {
final List<ProjectStructureElementUsage> usages = new ReadAction<List<ProjectStructureElementUsage>>() {
protected void run(final Result<List<ProjectStructureElementUsage>> result) {
@@ -96,7 +91,7 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
LOG.debug("updating usages for " + element);
}
updateUsages(element, usages);
fireProblemsUpdated();
myDispatcher.getMulticaster().usagesCollected(element);
}
});
}
@@ -137,7 +132,7 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
}
}
removeUsagesInElement(element);
fireProblemsUpdated();
myDispatcher.getMulticaster().problemsChanged(element);
}
public boolean isUnused(ProjectStructureElement element) {
@@ -180,7 +175,7 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
public void clearAllProblems() {
myProblemHolders.clear();
fireProblemsUpdated();
myDispatcher.getMulticaster().allProblemsChanged();
}
public void dispose() {
@@ -188,7 +183,8 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
myAnalyzerQueue.cancelAllUpdates();
}
public ProjectStructureProblemsHolder getProblemsHolder(ProjectStructureElement element) {
@Nullable
public ProjectStructureProblemsHolderImpl getProblemsHolder(ProjectStructureElement element) {
return myProblemHolders.get(element);
}
@@ -197,14 +193,13 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
for (ProjectStructureElement element : elements) {
updateUsages(element, element.getUsagesInElement());
}
fireProblemsUpdated();
final Collection<ProjectStructureElementUsage> usages = mySourceElement2Usages.get(selected);
return usages != null ? usages : Collections.<ProjectStructureElementUsage>emptyList();
}
public void addListener(Runnable runnable) {
LOG.debug("listener added " + runnable);
myListeners.add(runnable);
public void addListener(ProjectStructureDaemonAnalyzerListener listener) {
LOG.debug("listener added " + listener);
myDispatcher.addListener(listener);
}
public void reset() {
@@ -0,0 +1,32 @@
/*
* Copyright 2000-2009 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;
import java.util.EventListener;
/**
* @author nik
*/
public interface ProjectStructureDaemonAnalyzerListener extends EventListener {
void usagesCollected(@NotNull ProjectStructureElement containingElement);
void problemsChanged(@NotNull ProjectStructureElement element);
void allProblemsChanged();
}
@@ -15,6 +15,8 @@
*/
package com.intellij.openapi.roots.ui.configuration.projectRoot.daemon;
import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
@@ -22,7 +24,7 @@ public class ProjectStructureProblemDescription {
private String myMessage;
private final Severity mySeverity;
public ProjectStructureProblemDescription(String message, Severity severity) {
public ProjectStructureProblemDescription(@NotNull String message, @NotNull Severity severity) {
myMessage = message;
mySeverity = severity;
}
@@ -1,57 +1,29 @@
/*
* Copyright 2000-2009 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.util.SmartList;
import com.intellij.util.StringBuilderSpinAllocator;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
public class ProjectStructureProblemsHolder {
private List<ProjectStructureProblemDescription> myProblemDescriptions;
public interface ProjectStructureProblemsHolder {
void registerError(@NotNull String message);
public void addError(String message) {
addProblem(message, ProjectStructureProblemDescription.Severity.ERROR);
}
void registerWarning(@NotNull String message);
public void addWarning(String message) {
addProblem(message, ProjectStructureProblemDescription.Severity.WARNING);
}
public void addProblem(String description, ProjectStructureProblemDescription.Severity severity) {
if (myProblemDescriptions == null) {
myProblemDescriptions = new SmartList<ProjectStructureProblemDescription>();
}
myProblemDescriptions.add(new ProjectStructureProblemDescription(description, severity));
}
@Nullable
public ProjectStructureProblemDescription.Severity getSeverity() {
if (myProblemDescriptions == null || myProblemDescriptions.isEmpty()) {
return null;
}
for (ProjectStructureProblemDescription description : myProblemDescriptions) {
if (description.getSeverity() == ProjectStructureProblemDescription.Severity.ERROR) {
return ProjectStructureProblemDescription.Severity.ERROR;
}
}
return ProjectStructureProblemDescription.Severity.WARNING;
}
public String composeTooltipMessage() {
final StringBuilder buf = StringBuilderSpinAllocator.alloc();
try {
if (myProblemDescriptions != null) {
for (ProjectStructureProblemDescription problemDescription : myProblemDescriptions) {
buf.append(problemDescription.getMessage()).append("\n");
}
}
return buf.toString();
}
finally {
StringBuilderSpinAllocator.dispose(buf);
}
}
void registerProblem(@NotNull ProjectStructureProblemDescription description);
}
@@ -0,0 +1,63 @@
package com.intellij.openapi.roots.ui.configuration.projectRoot.daemon;
import com.intellij.util.SmartList;
import com.intellij.util.StringBuilderSpinAllocator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* @author nik
*/
public class ProjectStructureProblemsHolderImpl implements ProjectStructureProblemsHolder {
private List<ProjectStructureProblemDescription> myProblemDescriptions;
public void registerError(@NotNull String message) {
registerProblem(new ProjectStructureProblemDescription(message, ProjectStructureProblemDescription.Severity.ERROR));
}
public void registerWarning(@NotNull String message) {
registerProblem(new ProjectStructureProblemDescription(message, ProjectStructureProblemDescription.Severity.WARNING));
}
public void registerProblem(final @NotNull ProjectStructureProblemDescription description) {
if (myProblemDescriptions == null) {
myProblemDescriptions = new SmartList<ProjectStructureProblemDescription>();
}
myProblemDescriptions.add(description);
}
@Nullable
public ProjectStructureProblemDescription.Severity getSeverity() {
if (myProblemDescriptions == null || myProblemDescriptions.isEmpty()) {
return null;
}
for (ProjectStructureProblemDescription description : myProblemDescriptions) {
if (description.getSeverity() == ProjectStructureProblemDescription.Severity.ERROR) {
return ProjectStructureProblemDescription.Severity.ERROR;
}
}
return ProjectStructureProblemDescription.Severity.WARNING;
}
public String composeTooltipMessage() {
final StringBuilder buf = StringBuilderSpinAllocator.alloc();
try {
if (myProblemDescriptions != null) {
for (ProjectStructureProblemDescription problemDescription : myProblemDescriptions) {
buf.append(problemDescription.getMessage()).append("\n");
}
}
return buf.toString();
}
finally {
StringBuilderSpinAllocator.dispose(buf);
}
}
@Nullable
public List<ProjectStructureProblemDescription> getProblemDescriptions() {
return myProblemDescriptions;
}
}