mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[platform] module dependency analysis rewritten; test scope added
This commit is contained in:
+15
-19
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 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.
|
||||
@@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.moduleDependencies;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
@@ -27,35 +26,31 @@ import com.intellij.openapi.wm.ToolWindowId;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import com.intellij.ui.content.Content;
|
||||
import com.intellij.ui.content.ContentManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User: anna
|
||||
* Date: Feb 10, 2005
|
||||
* @author anna
|
||||
* @since Feb 10, 2005
|
||||
*/
|
||||
@State(
|
||||
name = "DependenciesAnalyzeManager",
|
||||
storages = {@Storage(file = StoragePathMacros.WORKSPACE_FILE)}
|
||||
)
|
||||
@State(name = "DependenciesAnalyzeManager", storages = {@Storage(file = StoragePathMacros.WORKSPACE_FILE)})
|
||||
public class DependenciesAnalyzeManager implements PersistentStateComponent<DependenciesAnalyzeManager.State> {
|
||||
private final Project myProject;
|
||||
private ContentManager myContentManager;
|
||||
|
||||
public static class State {
|
||||
public boolean myForwardDirection;
|
||||
public boolean forwardDirection = true;
|
||||
public boolean includeTests = false;
|
||||
}
|
||||
|
||||
private State myState;
|
||||
private State myState = new State();
|
||||
|
||||
public DependenciesAnalyzeManager(final Project project) {
|
||||
myProject = project;
|
||||
StartupManager.getInstance(myProject).runWhenProjectIsInitialized(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(myProject);
|
||||
ToolWindow toolWindow = toolWindowManager.registerToolWindow(ToolWindowId.MODULES_DEPENDENCIES,
|
||||
true,
|
||||
ToolWindowAnchor.RIGHT,
|
||||
project);
|
||||
ToolWindowManager manager = ToolWindowManager.getInstance(myProject);
|
||||
ToolWindow toolWindow = manager.registerToolWindow(ToolWindowId.MODULES_DEPENDENCIES, true, ToolWindowAnchor.RIGHT, project);
|
||||
myContentManager = toolWindow.getContentManager();
|
||||
toolWindow.setIcon(AllIcons.Toolwindows.ToolWindowModuleDependencies);
|
||||
new ContentManagerWatcher(toolWindow, myContentManager);
|
||||
@@ -63,7 +58,7 @@ public class DependenciesAnalyzeManager implements PersistentStateComponent<Depe
|
||||
});
|
||||
}
|
||||
|
||||
public static DependenciesAnalyzeManager getInstance(Project project){
|
||||
public static DependenciesAnalyzeManager getInstance(Project project) {
|
||||
return ServiceManager.getService(project, DependenciesAnalyzeManager.class);
|
||||
}
|
||||
|
||||
@@ -78,12 +73,13 @@ public class DependenciesAnalyzeManager implements PersistentStateComponent<Depe
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public State getState() {
|
||||
return myState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadState(final State state) {
|
||||
myState = state;
|
||||
public void loadState(State state) {
|
||||
myState = state != null ? state : new State();
|
||||
}
|
||||
}
|
||||
}
|
||||
+304
-371
@@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.moduleDependencies;
|
||||
|
||||
import com.intellij.CommonBundle;
|
||||
@@ -23,39 +22,41 @@ import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.CommonActionsManager;
|
||||
import com.intellij.ide.TreeExpander;
|
||||
import com.intellij.ide.actions.ContextHelpAction;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.idea.ActionsBundle;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.module.ModuleType;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ModuleRootAdapter;
|
||||
import com.intellij.openapi.roots.ModuleRootEvent;
|
||||
import com.intellij.openapi.roots.ModuleRootListener;
|
||||
import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService;
|
||||
import com.intellij.openapi.ui.Splitter;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.pom.NavigatableWithText;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.content.Content;
|
||||
import com.intellij.ui.treeStructure.Tree;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.graph.DFSTBuilder;
|
||||
import com.intellij.util.graph.Graph;
|
||||
import com.intellij.util.graph.GraphAlgorithms;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.TreeExpansionEvent;
|
||||
import javax.swing.event.TreeExpansionListener;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
import javax.swing.event.TreeSelectionListener;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
import javax.swing.tree.TreePath;
|
||||
@@ -65,419 +66,333 @@ import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: anna
|
||||
* Date: Feb 10, 2005
|
||||
* @author anna
|
||||
* @since Feb 10, 2005
|
||||
*/
|
||||
public class ModulesDependenciesPanel extends JPanel implements ModuleRootListener, Disposable {
|
||||
@NonNls private static final String DIRECTION = "FORWARD_ANALIZER";
|
||||
private Content myContent;
|
||||
public class ModulesDependenciesPanel extends JPanel implements Disposable {
|
||||
private static final String HELP_ID = "module.dependencies.tool.window";
|
||||
|
||||
private static final Comparator<DefaultMutableTreeNode> NODE_COMPARATOR = new Comparator<DefaultMutableTreeNode>() {
|
||||
@Override
|
||||
public int compare(DefaultMutableTreeNode o1, DefaultMutableTreeNode o2) {
|
||||
if (!(o1.getUserObject() instanceof MyUserObject)) return 1;
|
||||
if (!(o2.getUserObject() instanceof MyUserObject)) return -1;
|
||||
return (o1.getUserObject().toString().compareToIgnoreCase(o2.getUserObject().toString()));
|
||||
}
|
||||
};
|
||||
|
||||
private static final ColoredTreeCellRenderer NODE_RENDERER = new ColoredTreeCellRenderer() {
|
||||
@Override
|
||||
public void customizeCellRenderer(@NotNull JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
|
||||
Object userObject = ((DefaultMutableTreeNode)value).getUserObject();
|
||||
if (userObject instanceof MyUserObject) {
|
||||
MyUserObject node = (MyUserObject)userObject;
|
||||
setIcon(ModuleType.get(node.myModule).getIcon());
|
||||
append(node.myModule.getName(), node.myInCycle ? SimpleTextAttributes.ERROR_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
}
|
||||
else if (userObject != null) {
|
||||
append(userObject.toString(), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final Project myProject;
|
||||
private Tree myLeftTree;
|
||||
private DefaultTreeModel myLeftTreeModel;
|
||||
|
||||
private final Tree myRightTree;
|
||||
private final DefaultTreeModel myRightTreeModel;
|
||||
|
||||
private Graph<Module> myModulesGraph;
|
||||
private final Module[] myModules;
|
||||
private final DependenciesAnalyzeManager.State myState;
|
||||
|
||||
private final JTextField myPathField = new JTextField();
|
||||
|
||||
private final Tree myLeftTree;
|
||||
private final Tree myRightTree;
|
||||
private final Splitter mySplitter;
|
||||
@NonNls private static final String ourHelpID = "module.dependencies.tool.window";
|
||||
private final JTextComponent myPathField;
|
||||
|
||||
public ModulesDependenciesPanel(final Project project, final Module[] modules) {
|
||||
private Content myContent;
|
||||
private Graph<Module> myModuleGraph;
|
||||
private final Map<Module, Boolean> myCycleMap = ContainerUtil.newHashMap();
|
||||
|
||||
public ModulesDependenciesPanel(@NotNull Project project, @Nullable Module[] modules) {
|
||||
super(new BorderLayout());
|
||||
|
||||
myProject = project;
|
||||
myModules = modules;
|
||||
myModules = modules != null ? modules : ModuleManager.getInstance(project).getModules();
|
||||
myState = DependenciesAnalyzeManager.getInstance(project).getState();
|
||||
updateModuleGraph();
|
||||
|
||||
//noinspection HardCodedStringLiteral
|
||||
myRightTreeModel = new DefaultTreeModel(new DefaultMutableTreeNode("Root"));
|
||||
myRightTree = new Tree(myRightTreeModel);
|
||||
initTree(myRightTree, true);
|
||||
myLeftTree = new Tree(new DefaultTreeModel(new DefaultMutableTreeNode("Root")));
|
||||
installLeftTreeListeners();
|
||||
installTreeActions(myLeftTree, false);
|
||||
|
||||
initLeftTree();
|
||||
myRightTree = new Tree(new DefaultTreeModel(new DefaultMutableTreeNode("Root")));
|
||||
installTreeActions(myRightTree, true);
|
||||
|
||||
mySplitter = new Splitter();
|
||||
mySplitter.setFirstComponent(new MyTreePanel(myLeftTree, myProject));
|
||||
mySplitter.setSecondComponent(new MyTreePanel(myRightTree, myProject));
|
||||
|
||||
setSplitterProportion();
|
||||
add(mySplitter, BorderLayout.CENTER);
|
||||
|
||||
myPathField = new JTextField();
|
||||
myPathField.setEditable(false);
|
||||
add(createNorthPanel(), BorderLayout.NORTH);
|
||||
|
||||
project.getMessageBus().connect(this).subscribe(ProjectTopics.PROJECT_ROOTS, this);
|
||||
}
|
||||
|
||||
private void setSplitterProportion() {
|
||||
if (mySplitter == null){
|
||||
return;
|
||||
}
|
||||
myModulesGraph = buildGraph();
|
||||
DFSTBuilder<Module> builder = new DFSTBuilder<Module>(myModulesGraph);
|
||||
if (builder.isAcyclic()){
|
||||
mySplitter.setProportion(1.f);
|
||||
} else {
|
||||
mySplitter.setProportion(0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
public ModulesDependenciesPanel(final Project project) {
|
||||
this(project, ModuleManager.getInstance(project).getModules());
|
||||
}
|
||||
|
||||
private JComponent createNorthPanel(){
|
||||
DefaultActionGroup group = new DefaultActionGroup();
|
||||
|
||||
group.add(new AnAction(CommonBundle.message("action.close"), AnalysisScopeBundle.message("action.close.modules.dependencies.description"),
|
||||
AllIcons.Actions.Cancel){
|
||||
project.getMessageBus().connect(this).subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootAdapter() {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
DependenciesAnalyzeManager.getInstance(myProject).closeContent(myContent);
|
||||
public void rootsChanged(ModuleRootEvent event) {
|
||||
updateModuleGraph();
|
||||
updateSplitterProportion();
|
||||
updateLeftTree();
|
||||
}
|
||||
});
|
||||
|
||||
appendDependenciesAction(group);
|
||||
|
||||
group.add(new ToggleAction(AnalysisScopeBundle.message("action.module.dependencies.direction"), "", isForwardDirection() ? AllIcons.Actions.SortAsc
|
||||
: AllIcons.Actions.SortDesc){
|
||||
@Override
|
||||
public boolean isSelected(AnActionEvent e) {
|
||||
return isForwardDirection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
PropertiesComponent.getInstance(myProject).setValue(DIRECTION, String.valueOf(state));
|
||||
initLeftTreeModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(final AnActionEvent e) {
|
||||
e.getPresentation().setIcon(isForwardDirection() ? AllIcons.Actions.SortAsc : AllIcons.Actions.SortDesc);
|
||||
}
|
||||
});
|
||||
|
||||
group.add(new ContextHelpAction(ourHelpID));
|
||||
|
||||
ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true);
|
||||
final JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.add(toolbar.getComponent(), BorderLayout.NORTH);
|
||||
panel.add(myPathField, BorderLayout.SOUTH);
|
||||
myPathField.setEditable(false);
|
||||
return panel;
|
||||
updateSplitterProportion();
|
||||
updateLeftTree();
|
||||
}
|
||||
|
||||
private boolean isForwardDirection() {
|
||||
final String value = PropertiesComponent.getInstance(myProject).getValue(DIRECTION);
|
||||
return value == null || Boolean.parseBoolean(value);
|
||||
private void updateModuleGraph() {
|
||||
myModuleGraph = ModuleManager.getInstance(myProject).moduleGraph(myState.includeTests);
|
||||
myCycleMap.clear();
|
||||
}
|
||||
|
||||
private static void appendDependenciesAction(final DefaultActionGroup group) {
|
||||
final AnAction analyzeDepsAction = ActionManager.getInstance().getAction(IdeActions.ACTION_ANALYZE_DEPENDENCIES);
|
||||
group.add(new AnAction(analyzeDepsAction.getTemplatePresentation().getText(),
|
||||
analyzeDepsAction.getTemplatePresentation().getDescription(),
|
||||
AllIcons.Toolwindows.ToolWindowInspection){
|
||||
|
||||
private Iterable<Module> getModuleDependencies(Module module) {
|
||||
final Iterator<Module> iterator = myState.forwardDirection ? myModuleGraph.getIn(module) : myModuleGraph.getOut(module);
|
||||
return new Iterable<Module>() {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
analyzeDepsAction.actionPerformed(e);
|
||||
public Iterator<Module> iterator() {
|
||||
return iterator;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
analyzeDepsAction.update(e);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
private void buildRightTree(Module module){
|
||||
final DefaultMutableTreeNode root = (DefaultMutableTreeNode)myRightTreeModel.getRoot();
|
||||
root.removeAllChildren();
|
||||
final Set<List<Module>> cycles = GraphAlgorithms.getInstance().findCycles(myModulesGraph, module);
|
||||
int index = 1;
|
||||
for (List<Module> modules : cycles) {
|
||||
final DefaultMutableTreeNode cycle = new DefaultMutableTreeNode(
|
||||
AnalysisScopeBundle.message("module.dependencies.cycle.node.text", Integer.toString(index++).toUpperCase()));
|
||||
root.add(cycle);
|
||||
cycle.add(new DefaultMutableTreeNode(new MyUserObject(false, module)));
|
||||
for (Module moduleInCycle : modules) {
|
||||
cycle.add(new DefaultMutableTreeNode(new MyUserObject(false, moduleInCycle)));
|
||||
}
|
||||
}
|
||||
((DefaultTreeModel)myRightTree.getModel()).reload();
|
||||
TreeUtil.expandAll(myRightTree);
|
||||
}
|
||||
|
||||
private void initLeftTreeModel(){
|
||||
final DefaultMutableTreeNode root = (DefaultMutableTreeNode)myLeftTreeModel.getRoot();
|
||||
root.removeAllChildren();
|
||||
myModulesGraph = buildGraph();
|
||||
setSplitterProportion();
|
||||
ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator();
|
||||
final Map<Module, Boolean> inCycle = new HashMap<Module, Boolean>();
|
||||
for (Module module : myModules) {
|
||||
if (progressIndicator != null) {
|
||||
if (progressIndicator.isCanceled()) return;
|
||||
progressIndicator.setText(AnalysisScopeBundle.message("update.module.tree.progress.text", module.getName()));
|
||||
}
|
||||
if (!module.isDisposed()) {
|
||||
Boolean isInCycle = inCycle.get(module);
|
||||
if (isInCycle == null) {
|
||||
isInCycle = !GraphAlgorithms.getInstance().findCycles(myModulesGraph, module).isEmpty();
|
||||
inCycle.put(module, isInCycle);
|
||||
}
|
||||
final DefaultMutableTreeNode moduleNode = new DefaultMutableTreeNode(new MyUserObject(isInCycle.booleanValue(), module));
|
||||
root.add(moduleNode);
|
||||
final Iterator<Module> out = myModulesGraph.getOut(module);
|
||||
while (out.hasNext()) {
|
||||
moduleNode.add(new DefaultMutableTreeNode(new MyUserObject(false, out.next())));
|
||||
}
|
||||
}
|
||||
private boolean isInCycle(Module module) {
|
||||
Boolean inCycle = myCycleMap.get(module);
|
||||
if (inCycle == null) {
|
||||
Set<List<Module>> cycles = GraphAlgorithms.getInstance().findCycles(myModuleGraph, module);
|
||||
inCycle = !cycles.isEmpty();
|
||||
myCycleMap.put(module, inCycle);
|
||||
for (List<Module> cycle : cycles) {
|
||||
for (Module moduleInCycle : cycle) {
|
||||
myCycleMap.put(moduleInCycle, true);
|
||||
}
|
||||
}
|
||||
}, AnalysisScopeBundle.message("update.module.tree.progress.title"), true, myProject);
|
||||
sortSubTree(root);
|
||||
myLeftTreeModel.reload();
|
||||
}
|
||||
return inCycle;
|
||||
}
|
||||
|
||||
private static void sortSubTree(final DefaultMutableTreeNode root) {
|
||||
TreeUtil.sort(root, new Comparator() {
|
||||
@Override
|
||||
public int compare(final Object o1, final Object o2) {
|
||||
DefaultMutableTreeNode node1 = (DefaultMutableTreeNode)o1;
|
||||
DefaultMutableTreeNode node2 = (DefaultMutableTreeNode)o2;
|
||||
if (!(node1.getUserObject() instanceof MyUserObject)){
|
||||
return 1;
|
||||
}
|
||||
else if (!(node2.getUserObject() instanceof MyUserObject)){
|
||||
return -1;
|
||||
}
|
||||
return (node1.getUserObject().toString().compareToIgnoreCase(node2.getUserObject().toString()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void selectCycleUpward(final DefaultMutableTreeNode selection){
|
||||
ArrayList<DefaultMutableTreeNode> selectionNodes = new ArrayList<DefaultMutableTreeNode>();
|
||||
selectionNodes.add(selection);
|
||||
DefaultMutableTreeNode current = (DefaultMutableTreeNode)selection.getParent();
|
||||
boolean flag = false;
|
||||
while (current != null && current.getUserObject() != null){
|
||||
if (current.getUserObject().equals(selection.getUserObject())){
|
||||
flag = true;
|
||||
selectionNodes.add(current);
|
||||
break;
|
||||
}
|
||||
selectionNodes.add(current);
|
||||
current = (DefaultMutableTreeNode)current.getParent();
|
||||
}
|
||||
if (flag){
|
||||
for (DefaultMutableTreeNode node : selectionNodes) {
|
||||
((MyUserObject)node.getUserObject()).setInCycle(true);
|
||||
}
|
||||
}
|
||||
if (current != null) current = (DefaultMutableTreeNode)current.getParent();
|
||||
while (current != null) {
|
||||
final Object userObject = current.getUserObject();
|
||||
if (userObject instanceof MyUserObject) {
|
||||
((MyUserObject)userObject).setInCycle(false);
|
||||
}
|
||||
current = (DefaultMutableTreeNode)current.getParent();
|
||||
}
|
||||
myLeftTree.repaint();
|
||||
}
|
||||
|
||||
private void initLeftTree(){
|
||||
//noinspection HardCodedStringLiteral
|
||||
final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
|
||||
myLeftTreeModel = new DefaultTreeModel(root);
|
||||
initLeftTreeModel();
|
||||
myLeftTree = new Tree(myLeftTreeModel);
|
||||
initTree(myLeftTree, false);
|
||||
|
||||
private void installLeftTreeListeners() {
|
||||
myLeftTree.addTreeExpansionListener(new TreeExpansionListener() {
|
||||
@Override
|
||||
public void treeCollapsed(TreeExpansionEvent event) {
|
||||
}
|
||||
public void treeCollapsed(TreeExpansionEvent event) { }
|
||||
|
||||
@Override
|
||||
public void treeExpanded(TreeExpansionEvent event) {
|
||||
final DefaultMutableTreeNode expandedNode = (DefaultMutableTreeNode)event.getPath().getLastPathComponent();
|
||||
for(int i = 0; i < expandedNode.getChildCount(); i++){
|
||||
DefaultMutableTreeNode expandedNode = (DefaultMutableTreeNode)event.getPath().getLastPathComponent();
|
||||
for (int i = 0; i < expandedNode.getChildCount(); i++) {
|
||||
DefaultMutableTreeNode child = (DefaultMutableTreeNode)expandedNode.getChildAt(i);
|
||||
if (child.getChildCount() == 0){
|
||||
Module module = ((MyUserObject)child.getUserObject()).getModule();
|
||||
final Iterator<Module> out = myModulesGraph.getOut(module);
|
||||
while (out.hasNext()) {
|
||||
final Module nextModule = out.next();
|
||||
child.add(new DefaultMutableTreeNode(new MyUserObject(false, nextModule)));
|
||||
if (child.getChildCount() == 0 && !isLooped(event.getPath(), child)) {
|
||||
Module module = ((MyUserObject)child.getUserObject()).myModule;
|
||||
for (Module dependency : getModuleDependencies(module)) {
|
||||
child.add(new DefaultMutableTreeNode(new MyUserObject(isInCycle(dependency), dependency)));
|
||||
}
|
||||
sortSubTree(child);
|
||||
TreeUtil.sort(child, NODE_COMPARATOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isLooped(TreePath path, DefaultMutableTreeNode child) {
|
||||
for (Object o : path.getPath()) {
|
||||
DefaultMutableTreeNode node = (DefaultMutableTreeNode)o;
|
||||
if (node != child && Comparing.equal(node.getUserObject(), child.getUserObject())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
myLeftTree.addTreeSelectionListener(new TreeSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
final TreePath selectionPath = myLeftTree.getSelectionPath();
|
||||
TreePath selectionPath = myLeftTree.getSelectionPath();
|
||||
if (selectionPath != null) {
|
||||
|
||||
myPathField.setText(StringUtil.join(selectionPath.getPath(), new Function<Object, String>() {
|
||||
@Override
|
||||
public String fun(Object o) {
|
||||
final Object userObject = ((DefaultMutableTreeNode)o).getUserObject();
|
||||
if (userObject instanceof MyUserObject) {
|
||||
return ((MyUserObject)userObject).getModule().getName();
|
||||
}
|
||||
return "";
|
||||
Object userObject = ((DefaultMutableTreeNode)o).getUserObject();
|
||||
return userObject instanceof MyUserObject ? ((MyUserObject)userObject).myModule.getName() : "";
|
||||
}
|
||||
}, ":"));
|
||||
}, " : "));
|
||||
|
||||
final DefaultMutableTreeNode selection = (DefaultMutableTreeNode)selectionPath.getLastPathComponent();
|
||||
if (selection != null){
|
||||
TreeUtil.traverseDepth(selection, new TreeUtil.Traverse() {
|
||||
@Override
|
||||
public boolean accept(Object node) {
|
||||
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)node;
|
||||
if (treeNode.getUserObject() instanceof MyUserObject){
|
||||
((MyUserObject)treeNode.getUserObject()).setInCycle(false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
selectCycleUpward(selection);
|
||||
buildRightTree(((MyUserObject)selection.getUserObject()).getModule());
|
||||
DefaultMutableTreeNode selection = (DefaultMutableTreeNode)selectionPath.getLastPathComponent();
|
||||
if (selection != null) {
|
||||
updateRightTree(((MyUserObject)selection.getUserObject()).myModule);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
TreeUtil.selectFirstNode(myLeftTree);
|
||||
}
|
||||
|
||||
private static ActionGroup createTreePopupActions(final boolean isRightTree, final Tree tree) {
|
||||
DefaultActionGroup group = new DefaultActionGroup();
|
||||
final TreeExpander treeExpander = new TreeExpander() {
|
||||
@Override
|
||||
public void expandAll() {
|
||||
TreeUtil.expandAll(tree);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExpand() {
|
||||
return isRightTree;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collapseAll() {
|
||||
TreeUtil.collapseAll(tree, 3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canCollapse() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
final CommonActionsManager actionManager = CommonActionsManager.getInstance();
|
||||
if (isRightTree){
|
||||
group.add(actionManager.createExpandAllAction(treeExpander, tree));
|
||||
}
|
||||
group.add(actionManager.createCollapseAllAction(treeExpander, tree));
|
||||
final ActionManager globalActionManager = ActionManager.getInstance();
|
||||
group.add(globalActionManager.getAction(IdeActions.ACTION_EDIT_SOURCE));
|
||||
group.add(Separator.getInstance());
|
||||
group.add(globalActionManager.getAction(IdeActions.ACTION_ANALYZE_DEPENDENCIES));
|
||||
group.add(globalActionManager.getAction(IdeActions.ACTION_ANALYZE_BACK_DEPENDENCIES));
|
||||
group.add(globalActionManager.getAction(IdeActions.ACTION_ANALYZE_CYCLIC_DEPENDENCIES));
|
||||
return group;
|
||||
}
|
||||
|
||||
private static void initTree(Tree tree, boolean isRightTree) {
|
||||
private static void installTreeActions(Tree tree, boolean enableExpandAll) {
|
||||
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
|
||||
tree.setCellRenderer(new MyTreeCellRenderer());
|
||||
tree.setCellRenderer(NODE_RENDERER);
|
||||
tree.setRootVisible(false);
|
||||
tree.setShowsRootHandles(true);
|
||||
UIUtil.setLineStyleAngled(tree);
|
||||
|
||||
TreeUtil.installActions(tree);
|
||||
|
||||
new TreeSpeedSearch(tree, new Convertor<TreePath, String>() {
|
||||
@Override
|
||||
public String convert(TreePath o) {
|
||||
return o.getLastPathComponent().toString();
|
||||
}
|
||||
}, true);
|
||||
PopupHandler.installUnknownPopupHandler(tree, createTreePopupActions(isRightTree, tree), ActionManager.getInstance());
|
||||
|
||||
DefaultActionGroup group = new DefaultActionGroup();
|
||||
CommonActionsManager commonActionManager = CommonActionsManager.getInstance();
|
||||
ActionManager globalActionManager = ActionManager.getInstance();
|
||||
|
||||
TreeExpander treeExpander = new MyTreeExpander(tree, enableExpandAll);
|
||||
group.add(commonActionManager.createExpandAllAction(treeExpander, tree));
|
||||
group.add(commonActionManager.createCollapseAllAction(treeExpander, tree));
|
||||
group.add(globalActionManager.getAction(IdeActions.ACTION_EDIT_SOURCE));
|
||||
group.add(Separator.getInstance());
|
||||
group.add(globalActionManager.getAction(IdeActions.ACTION_ANALYZE_DEPENDENCIES));
|
||||
group.add(globalActionManager.getAction(IdeActions.ACTION_ANALYZE_BACK_DEPENDENCIES));
|
||||
group.add(globalActionManager.getAction(IdeActions.ACTION_ANALYZE_CYCLIC_DEPENDENCIES));
|
||||
group.add(globalActionManager.getAction(IdeActions.ACTION_ANALYZE_MODULE_DEPENDENCIES));
|
||||
|
||||
PopupHandler.installUnknownPopupHandler(tree, group, ActionManager.getInstance());
|
||||
}
|
||||
|
||||
|
||||
private Graph<Module> buildGraph() {
|
||||
final Graph<Module> graph = ModuleManager.getInstance(myProject).moduleGraph();
|
||||
if (isForwardDirection()) {
|
||||
return graph;
|
||||
}
|
||||
else {
|
||||
return GraphAlgorithms.getInstance().invertEdgeDirections(graph);
|
||||
}
|
||||
private void updateSplitterProportion() {
|
||||
DFSTBuilder<Module> builder = new DFSTBuilder<Module>(myModuleGraph);
|
||||
mySplitter.setProportion(builder.isAcyclic() ? 1.0f : 0.6f);
|
||||
}
|
||||
|
||||
public void setContent(final Content content) {
|
||||
private JComponent createNorthPanel() {
|
||||
DefaultActionGroup group = new DefaultActionGroup();
|
||||
|
||||
group.add(new AnAction(CommonBundle.message("action.close"), null, AllIcons.Actions.Cancel) {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
DependenciesAnalyzeManager.getInstance(myProject).closeContent(myContent);
|
||||
}
|
||||
});
|
||||
|
||||
final AnAction analyzeDepsAction = ActionManager.getInstance().getAction(IdeActions.ACTION_ANALYZE_DEPENDENCIES);
|
||||
group.add(new AnAction(analyzeDepsAction.getTemplatePresentation().getText(), null, AllIcons.Toolwindows.ToolWindowInspection) {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
analyzeDepsAction.actionPerformed(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
analyzeDepsAction.update(e);
|
||||
}
|
||||
});
|
||||
|
||||
group.add(new ToggleAction(AnalysisScopeBundle.message("action.module.dependencies.direction")) {
|
||||
@Override
|
||||
public boolean isSelected(AnActionEvent e) {
|
||||
return !myState.forwardDirection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
myState.forwardDirection = !state;
|
||||
updateLeftTree();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(@NotNull AnActionEvent e) {
|
||||
e.getPresentation().setIcon(myState.forwardDirection ? AllIcons.Hierarchy.Subtypes : AllIcons.Hierarchy.Supertypes);
|
||||
super.update(e);
|
||||
}
|
||||
});
|
||||
|
||||
group.add(new ToggleAction(AnalysisScopeBundle.message("action.module.dependencies.tests"), null, AllIcons.Modules.TestSourceFolder) {
|
||||
@Override
|
||||
public boolean isSelected(AnActionEvent e) {
|
||||
return myState.includeTests;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
myState.includeTests = state;
|
||||
updateModuleGraph();
|
||||
updateLeftTree();
|
||||
}
|
||||
});
|
||||
|
||||
group.add(new ContextHelpAction(HELP_ID));
|
||||
|
||||
ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true);
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.add(toolbar.getComponent(), BorderLayout.WEST);
|
||||
panel.add(myPathField, BorderLayout.CENTER);
|
||||
return panel;
|
||||
}
|
||||
|
||||
private void updateLeftTree() {
|
||||
final DefaultMutableTreeNode root = (DefaultMutableTreeNode)myLeftTree.getModel().getRoot();
|
||||
root.removeAllChildren();
|
||||
|
||||
ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (Module module : myModules) {
|
||||
if (module.isDisposed()) continue;
|
||||
ProgressManager.progress(AnalysisScopeBundle.message("update.module.tree.progress.text", module.getName()));
|
||||
|
||||
DefaultMutableTreeNode moduleNode = new DefaultMutableTreeNode(new MyUserObject(isInCycle(module), module));
|
||||
root.add(moduleNode);
|
||||
for (Module dependency : getModuleDependencies(module)) {
|
||||
moduleNode.add(new DefaultMutableTreeNode(new MyUserObject(isInCycle(dependency), dependency)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}, AnalysisScopeBundle.message("update.module.tree.progress.title"), true, myProject);
|
||||
|
||||
TreeUtil.sort(root, NODE_COMPARATOR);
|
||||
((DefaultTreeModel)myLeftTree.getModel()).reload();
|
||||
TreeUtil.selectFirstNode(myLeftTree);
|
||||
}
|
||||
|
||||
private void updateRightTree(Module module) {
|
||||
DefaultMutableTreeNode root = (DefaultMutableTreeNode)myRightTree.getModel().getRoot();
|
||||
root.removeAllChildren();
|
||||
|
||||
Set<List<Module>> cycles = GraphAlgorithms.getInstance().findCycles(myModuleGraph, module);
|
||||
int index = 1;
|
||||
for (List<Module> modules : cycles) {
|
||||
DefaultMutableTreeNode cycle = new DefaultMutableTreeNode(AnalysisScopeBundle.message("module.dependencies.cycle.node.text", index++));
|
||||
root.add(cycle);
|
||||
cycle.add(new DefaultMutableTreeNode(new MyUserObject(false, module)));
|
||||
for (Module moduleInCycle : modules) {
|
||||
cycle.add(new DefaultMutableTreeNode(new MyUserObject(false, moduleInCycle)));
|
||||
}
|
||||
}
|
||||
|
||||
((DefaultTreeModel)myRightTree.getModel()).reload();
|
||||
TreeUtil.expandAll(myRightTree);
|
||||
}
|
||||
|
||||
public void setContent(Content content) {
|
||||
myContent = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeRootsChange(ModuleRootEvent event) {
|
||||
}
|
||||
public void dispose() { }
|
||||
|
||||
@Override
|
||||
public void rootsChanged(ModuleRootEvent event) {
|
||||
initLeftTreeModel();
|
||||
TreeUtil.selectFirstNode(myLeftTree);
|
||||
}
|
||||
|
||||
private static class MyUserObject implements NavigatableWithText{
|
||||
private boolean myInCycle;
|
||||
private static class MyUserObject implements NavigatableWithText {
|
||||
private final Module myModule;
|
||||
private final boolean myInCycle;
|
||||
|
||||
public MyUserObject(final boolean inCycle, final Module module) {
|
||||
public MyUserObject(boolean inCycle, Module module) {
|
||||
myInCycle = inCycle;
|
||||
myModule = module;
|
||||
}
|
||||
|
||||
public boolean isInCycle() {
|
||||
return myInCycle;
|
||||
}
|
||||
|
||||
public void setInCycle(final boolean inCycle) {
|
||||
myInCycle = inCycle;
|
||||
}
|
||||
|
||||
public Module getModule() {
|
||||
return myModule;
|
||||
}
|
||||
|
||||
public boolean equals(Object object) {
|
||||
return object instanceof MyUserObject && myModule.equals(((MyUserObject)object).getModule());
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return myModule.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return myModule.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void navigate(boolean requestFocus) {
|
||||
ProjectSettingsService.getInstance(myModule.getProject()).openModuleSettings(myModule);
|
||||
@@ -485,7 +400,7 @@ public class ModulesDependenciesPanel extends JPanel implements ModuleRootListen
|
||||
|
||||
@Override
|
||||
public boolean canNavigate() {
|
||||
return myModule != null && !myModule.isDisposed();
|
||||
return !myModule.isDisposed();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -495,14 +410,30 @@ public class ModulesDependenciesPanel extends JPanel implements ModuleRootListen
|
||||
|
||||
@Override
|
||||
public String getNavigateActionText(boolean focusEditor) {
|
||||
return "Open Module Settings";
|
||||
return ActionsBundle.message("action.ModuleSettings.navigate");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o == this || o instanceof MyUserObject && myModule.equals(((MyUserObject)o).myModule);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return myModule.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return myModule.getName();
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyTreePanel extends JPanel implements DataProvider{
|
||||
private static class MyTreePanel extends JPanel implements DataProvider {
|
||||
private final Tree myTree;
|
||||
private final Project myProject;
|
||||
public MyTreePanel(final Tree tree, Project project) {
|
||||
|
||||
public MyTreePanel(Tree tree, Project project) {
|
||||
super(new BorderLayout());
|
||||
myTree = tree;
|
||||
myProject = project;
|
||||
@@ -511,26 +442,26 @@ public class ModulesDependenciesPanel extends JPanel implements ModuleRootListen
|
||||
|
||||
@Override
|
||||
public Object getData(String dataId) {
|
||||
if (CommonDataKeys.PROJECT.is(dataId)){
|
||||
if (CommonDataKeys.PROJECT.is(dataId)) {
|
||||
return myProject;
|
||||
}
|
||||
if (LangDataKeys.MODULE_CONTEXT.is(dataId)){
|
||||
final TreePath selectionPath = myTree.getLeadSelectionPath();
|
||||
if (selectionPath != null && selectionPath.getLastPathComponent() instanceof DefaultMutableTreeNode){
|
||||
if (LangDataKeys.MODULE_CONTEXT.is(dataId)) {
|
||||
TreePath selectionPath = myTree.getLeadSelectionPath();
|
||||
if (selectionPath != null && selectionPath.getLastPathComponent() instanceof DefaultMutableTreeNode) {
|
||||
DefaultMutableTreeNode node = (DefaultMutableTreeNode)selectionPath.getLastPathComponent();
|
||||
if (node.getUserObject() instanceof MyUserObject){
|
||||
return ((MyUserObject)node.getUserObject()).getModule();
|
||||
if (node.getUserObject() instanceof MyUserObject) {
|
||||
return ((MyUserObject)node.getUserObject()).myModule;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (PlatformDataKeys.HELP_ID.is(dataId)) {
|
||||
return ourHelpID;
|
||||
return HELP_ID;
|
||||
}
|
||||
if (CommonDataKeys.NAVIGATABLE.is(dataId)) {
|
||||
final TreePath selectionPath = myTree.getLeadSelectionPath();
|
||||
if (selectionPath != null && selectionPath.getLastPathComponent() instanceof DefaultMutableTreeNode){
|
||||
TreePath selectionPath = myTree.getLeadSelectionPath();
|
||||
if (selectionPath != null && selectionPath.getLastPathComponent() instanceof DefaultMutableTreeNode) {
|
||||
DefaultMutableTreeNode node = (DefaultMutableTreeNode)selectionPath.getLastPathComponent();
|
||||
if (node.getUserObject() instanceof MyUserObject){
|
||||
if (node.getUserObject() instanceof MyUserObject) {
|
||||
return node.getUserObject();
|
||||
}
|
||||
}
|
||||
@@ -538,32 +469,34 @@ public class ModulesDependenciesPanel extends JPanel implements ModuleRootListen
|
||||
return null;
|
||||
}
|
||||
}
|
||||
private static class MyTreeCellRenderer extends ColoredTreeCellRenderer {
|
||||
|
||||
private static class MyTreeExpander implements TreeExpander {
|
||||
private final Tree myTree;
|
||||
private final boolean myEnableExpandAll;
|
||||
|
||||
public MyTreeExpander(Tree tree, boolean enableExpandAll) {
|
||||
myTree = tree;
|
||||
myEnableExpandAll = enableExpandAll;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customizeCellRenderer(
|
||||
JTree tree,
|
||||
Object value,
|
||||
boolean selected,
|
||||
boolean expanded,
|
||||
boolean leaf,
|
||||
int row,
|
||||
boolean hasFocus
|
||||
){
|
||||
final Object userObject = ((DefaultMutableTreeNode)value).getUserObject();
|
||||
if (!(userObject instanceof MyUserObject)){
|
||||
if (userObject != null){
|
||||
append(userObject.toString(), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
|
||||
}
|
||||
return;
|
||||
}
|
||||
MyUserObject node = (MyUserObject)userObject;
|
||||
Module module = node.getModule();
|
||||
setIcon(ModuleType.get(module).getIcon());
|
||||
if (node.isInCycle()){
|
||||
append(module.getName(), SimpleTextAttributes.ERROR_ATTRIBUTES);
|
||||
} else {
|
||||
append(module.getName(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
}
|
||||
public void expandAll() {
|
||||
TreeUtil.expandAll(myTree);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExpand() {
|
||||
return myEnableExpandAll;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collapseAll() {
|
||||
TreeUtil.collapseAll(myTree, 3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canCollapse() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+34
-50
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 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.
|
||||
@@ -13,85 +13,69 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.moduleDependencies;
|
||||
|
||||
import com.intellij.analysis.AnalysisScope;
|
||||
import com.intellij.analysis.AnalysisScopeBundle;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.LangDataKeys;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.module.ModuleUtil;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.ui.content.Content;
|
||||
import com.intellij.ui.content.ContentFactory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* User: anna
|
||||
* Date: Feb 9, 2005
|
||||
* @author anna
|
||||
* @since Feb 9, 2005
|
||||
*/
|
||||
public class ShowModuleDependenciesAction extends AnAction{
|
||||
public class ShowModuleDependenciesAction extends AnAction {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
final DataContext dataContext = e.getDataContext();
|
||||
final Project project = CommonDataKeys.PROJECT.getData(dataContext);
|
||||
if (project == null){
|
||||
return;
|
||||
}
|
||||
ModulesDependenciesPanel panel;
|
||||
AnalysisScope scope = new AnalysisScope(project);
|
||||
final Module[] modules = LangDataKeys.MODULE_CONTEXT_ARRAY.getData(dataContext);
|
||||
if (modules != null){
|
||||
panel = new ModulesDependenciesPanel(project, modules);
|
||||
scope = new AnalysisScope(modules);
|
||||
} else {
|
||||
final PsiElement element = CommonDataKeys.PSI_FILE.getData(dataContext);
|
||||
final Module module = element != null ? ModuleUtil.findModuleForPsiElement(element) : null;
|
||||
public void update(@NotNull AnActionEvent e) {
|
||||
e.getPresentation().setEnabled(e.getProject() != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
Project project = e.getProject();
|
||||
if (project == null) return;
|
||||
|
||||
Module[] modules = LangDataKeys.MODULE_CONTEXT_ARRAY.getData(e.getDataContext());
|
||||
if (modules == null) {
|
||||
PsiElement element = CommonDataKeys.PSI_FILE.getData(e.getDataContext());
|
||||
Module module = element != null ? ModuleUtilCore.findModuleForPsiElement(element) : null;
|
||||
if (module != null && ModuleManager.getInstance(project).getModules().length > 1) {
|
||||
MyModuleOrProjectScope dlg = new MyModuleOrProjectScope(module.getName());
|
||||
if (dlg.showAndGet()) {
|
||||
if (!dlg.useProjectScope()) {
|
||||
panel = new ModulesDependenciesPanel(project, new Module[]{module});
|
||||
scope = new AnalysisScope(module);
|
||||
}
|
||||
else {
|
||||
panel = new ModulesDependenciesPanel(project);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!dlg.showAndGet()) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
panel = new ModulesDependenciesPanel(project);
|
||||
if (!dlg.useProjectScope()) {
|
||||
modules = new Module[]{module};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Content content = ContentFactory.SERVICE.getInstance().createContent(panel,
|
||||
AnalysisScopeBundle.message(
|
||||
"module.dependencies.toolwindow.title",
|
||||
StringUtil.capitalize(scope.getDisplayName())),
|
||||
false);
|
||||
ModulesDependenciesPanel panel = new ModulesDependenciesPanel(project, modules);
|
||||
AnalysisScope scope = modules != null ? new AnalysisScope(modules) : new AnalysisScope(project);
|
||||
Content content = ContentFactory.SERVICE.getInstance().createContent(panel, scope.getDisplayName(), false);
|
||||
content.setDisposer(panel);
|
||||
panel.setContent(content);
|
||||
DependenciesAnalyzeManager.getInstance(project).addContent(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
final DataContext dataContext = e.getDataContext();
|
||||
final Project project = CommonDataKeys.PROJECT.getData(dataContext);
|
||||
e.getPresentation().setEnabled(project != null);
|
||||
}
|
||||
|
||||
private static class MyModuleOrProjectScope extends DialogWrapper{
|
||||
private static class MyModuleOrProjectScope extends DialogWrapper {
|
||||
private final JRadioButton myProjectScope;
|
||||
private final JRadioButton myModuleScope;
|
||||
|
||||
protected MyModuleOrProjectScope(String moduleName) {
|
||||
super(false);
|
||||
setTitle(AnalysisScopeBundle.message("module.dependencies.scope.dialog.title"));
|
||||
@@ -112,8 +96,8 @@ public class ShowModuleDependenciesAction extends AnAction{
|
||||
return panel;
|
||||
}
|
||||
|
||||
public boolean useProjectScope(){
|
||||
public boolean useProjectScope() {
|
||||
return myProjectScope.isSelected();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -287,6 +287,7 @@ public interface IdeActions {
|
||||
@NonNls String ACTION_ANALYZE_DEPENDENCIES = "ShowPackageDeps";
|
||||
@NonNls String ACTION_ANALYZE_BACK_DEPENDENCIES = "ShowBackwardPackageDeps";
|
||||
@NonNls String ACTION_ANALYZE_CYCLIC_DEPENDENCIES = "ShowPackageCycles";
|
||||
@NonNls String ACTION_ANALYZE_MODULE_DEPENDENCIES = "ShowModulesDependencies";
|
||||
@NonNls String GROUP_MOVE_MODULE_TO_GROUP = "MoveModuleToGroup";
|
||||
@NonNls String ACTION_CLEAR_TEXT = "TextComponent.ClearAction";
|
||||
@NonNls String ACTION_HIGHLIGHT_USAGES_IN_FILE = "HighlightUsagesInFile";
|
||||
|
||||
@@ -21,8 +21,8 @@ action.group.by.scope.type.description=Group by Scope Type (production, test, li
|
||||
action.show.files=Show Files
|
||||
action.show.files.description=Show/Hide Files
|
||||
action.close.dependency.description=Close Dependency Viewer
|
||||
action.close.modules.dependencies.description=Close Modules Dependencies Viewer
|
||||
action.module.dependencies.direction=Dependencies Direction
|
||||
action.module.dependencies.direction=Backward Dependencies (Usages)
|
||||
action.module.dependencies.tests=Include Test Dependencies
|
||||
action.analyzing.cyclic.dependencies.in.scope=Cyclic Dependencies of {0}
|
||||
action.analyze.verb=Analyze
|
||||
action.analysis.noun=Analysis
|
||||
@@ -39,6 +39,8 @@ action.select.in.left.tree.description=Select in left tree (to browse dependenci
|
||||
action.forward.dependency.analysis=Dependency Analysis
|
||||
action.backward.dependency.analysis=Backward Dependency Analysis
|
||||
|
||||
update.module.tree.progress.title=Updating Module Tree
|
||||
update.module.tree.progress.text=Processing module ''{0}'' cycles
|
||||
|
||||
cyclic.dependencies.scope.dialog.title=Specify {0} Scope
|
||||
cyclic.dependencies.scope.dialog.project.button={0} the whole &project
|
||||
@@ -48,11 +50,10 @@ cyclic.dependencies.usage.view.root.node.text=Usages of package ''{0}'' in packa
|
||||
cyclic.dependencies.usage.view.initial.text=Select package to analyze from the left tree
|
||||
cyclic.dependencies.progress.text=Building dependencies graph
|
||||
|
||||
module.dependencies.cycle.node.text=Cycle{0}
|
||||
module.dependencies.cycle.node.text=Cycle {0}
|
||||
module.dependencies.scope.dialog.module.button=Inspect &module ''{0}''
|
||||
module.dependencies.scope.dialog.project.button=Inspect the whole &project
|
||||
module.dependencies.scope.dialog.title=Specify Analysis Scope
|
||||
module.dependencies.toolwindow.title={0}
|
||||
|
||||
backward.dependencies.usage.view.root.node.text=Usages of the left tree scope selection in the right tree scope selection
|
||||
backward.dependencies.usage.view.initial.text=Select where to search in right tree and what to search in left tree.
|
||||
@@ -83,7 +84,6 @@ dependencies.tree.node.default.package.abbreviation=<default package>
|
||||
|
||||
#scope selector
|
||||
dependencies.libraries.node.text=Libraries
|
||||
error.packageset.common.expectations=(test|lib|src)[modulename] expected before :
|
||||
error.packageset.token.expectations=Unexpected ''{0}''
|
||||
error.packageset.pattern.expectations=Package pattern expected
|
||||
error.packageset.rparen.expected=')' expected
|
||||
@@ -110,6 +110,4 @@ project.is.out.of.date=Project Is Out Of Date
|
||||
skip.import.statements.checkbox.title=Skip import statements
|
||||
mark.dependency.illegal.text=Mark Illegal
|
||||
scope.selected.files=Selected files
|
||||
update.module.tree.progress.title=Update modules tree
|
||||
update.module.tree.progress.text=Process module ''{0}'' cycles
|
||||
scope.virtual.files=selection
|
||||
Reference in New Issue
Block a user