mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
qualified module names: support cases when a module works as a module group (IDEA-166061)
If name of one module is prefix of name of another, the node for the first module will be shown as a parent node for the second module. Common code which create module and module group nodes extracted to ModuleGroupingTreeHelper class.
This commit is contained in:
+1
-1
@@ -119,7 +119,7 @@ public class IdeaProjectSettingsService extends ProjectSettingsService implement
|
||||
@Override
|
||||
public boolean processModulesMoved(final Module[] modules, @Nullable final ModuleGroup targetGroup) {
|
||||
final ModuleStructureConfigurable rootConfigurable = ModuleStructureConfigurable.getInstance(myProject);
|
||||
if (rootConfigurable.updateProjectTree(modules, targetGroup)) { //inside project root editor
|
||||
if (rootConfigurable.updateProjectTree(modules)) { //inside project root editor
|
||||
if (targetGroup != null) {
|
||||
rootConfigurable.selectNodeInTree(targetGroup.toString());
|
||||
}
|
||||
|
||||
+88
-119
@@ -24,8 +24,7 @@ import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.IdeBundle;
|
||||
import com.intellij.ide.highlighter.ModuleFileType;
|
||||
import com.intellij.ide.projectView.impl.ModuleGroup;
|
||||
import com.intellij.ide.projectView.impl.ModuleGroupUtil;
|
||||
import com.intellij.openapi.module.ModuleGrouper;
|
||||
import com.intellij.ide.projectView.impl.ModuleGroupingTreeHelper;
|
||||
import com.intellij.ide.util.projectWizard.ModuleBuilder;
|
||||
import com.intellij.ide.util.projectWizard.NamePathComponent;
|
||||
import com.intellij.ide.util.projectWizard.ProjectWizardUtil;
|
||||
@@ -54,6 +53,7 @@ import com.intellij.openapi.ui.*;
|
||||
import com.intellij.openapi.util.ActionCallback;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.NullableComputable;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
@@ -94,6 +94,9 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
|
||||
if (editableObject2 instanceof Module && editableObject1 instanceof String) return 1;
|
||||
if (editableObject1 instanceof Module && editableObject2 instanceof String) return -1;
|
||||
|
||||
if (editableObject2 instanceof Module && editableObject1 instanceof Facet) return 1;
|
||||
if (editableObject1 instanceof Module && editableObject2 instanceof Facet) return -1;
|
||||
|
||||
if (editableObject2 instanceof ModuleGroup && editableObject1 instanceof String) return 1;
|
||||
if (editableObject1 instanceof ModuleGroup && editableObject2 instanceof String) return -1;
|
||||
|
||||
@@ -166,7 +169,7 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
|
||||
protected void loadTree() {
|
||||
createProjectNodes();
|
||||
|
||||
((DefaultTreeModel)myTree.getModel()).reload();
|
||||
getTreeModel().reload();
|
||||
|
||||
myUiDisposed = false;
|
||||
}
|
||||
@@ -217,27 +220,12 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
|
||||
|
||||
|
||||
private void createProjectNodes() {
|
||||
final Map<ModuleGroup, MyNode> moduleGroup2NodeMap = new HashMap<>();
|
||||
final Module[] modules = myModuleManager.getModules();
|
||||
for (final Module module : modules) {
|
||||
ModuleGrouper moduleGrouper = getModuleGrouper();
|
||||
MyNode moduleNode = new ModuleNode(new ModuleConfigurable(myContext.myModulesConfigurator, module, TREE_UPDATER, moduleGrouper));
|
||||
boolean nodesAdded = myFacetEditorFacade.addFacetsNodes(module, moduleNode);
|
||||
nodesAdded |= addNodesFromExtensions(module, moduleNode);
|
||||
if (nodesAdded) {
|
||||
myTree.setShowsRootHandles(true);
|
||||
}
|
||||
final List<String> groupPath = myHideModuleGroups || myFlattenModules ? Collections.emptyList() : moduleGrouper.getGroupPath(module);
|
||||
if (groupPath.isEmpty()) {
|
||||
myRoot.add(moduleNode);
|
||||
}
|
||||
else {
|
||||
final MyNode moduleGroupNode = ModuleGroupUtil
|
||||
.buildModuleGroupPath(new ModuleGroup(groupPath), myRoot, moduleGroup2NodeMap,
|
||||
parentChildRelation -> parentChildRelation.getParent().add(parentChildRelation.getChild()),
|
||||
ModuleStructureConfigurable::createModuleGroupNode);
|
||||
moduleGroupNode.add(moduleNode);
|
||||
}
|
||||
ModuleGrouper moduleGrouper = getModuleGrouper();
|
||||
ModuleGroupingTreeHelper<MyNode> helper = ModuleGroupingTreeHelper.forEmptyTree(!myHideModuleGroups && !myFlattenModules,
|
||||
moduleGrouper, ModuleStructureConfigurable::createModuleGroupNode, this::createModuleNode, getNodeComparator());
|
||||
helper.createModuleNodes(Arrays.asList(myModuleManager.getModules()), myRoot, getTreeModel());
|
||||
if (containsSecondLevelNodes(myRoot)) {
|
||||
myTree.setShowsRootHandles(true);
|
||||
}
|
||||
sortDescendants(myRoot);
|
||||
if (myProject.isDefault()) { //do not add modules node in case of template project
|
||||
@@ -252,13 +240,34 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
|
||||
//myProjectNode.add(myLevel2Nodes.get(LibraryTablesRegistrar.PROJECT_LEVEL));
|
||||
}
|
||||
|
||||
private static boolean containsSecondLevelNodes(TreeNode rootNode) {
|
||||
int count = rootNode.getChildCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
TreeNode child = rootNode.getChildAt(i);
|
||||
if (child.getChildCount() > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ModuleNode createModuleNode(Module module, ModuleGrouper moduleGrouper) {
|
||||
ModuleConfigurable configurable = new ModuleConfigurable(myContext.myModulesConfigurator, module, TREE_UPDATER, moduleGrouper);
|
||||
List<String> groupPath = moduleGrouper.getModuleAsGroupPath(module);
|
||||
ModuleNode node = new ModuleNode(configurable, groupPath != null ? new ModuleGroup(groupPath) : null);
|
||||
myFacetEditorFacade.addFacetsNodes(module, node);
|
||||
addNodesFromExtensions(module, node);
|
||||
return node;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static MyNode createModuleGroupNode(ModuleGroup moduleGroup) {
|
||||
final NamedConfigurable moduleGroupConfigurable = new TextConfigurable<>(moduleGroup, moduleGroup.toString(),
|
||||
ProjectBundle.message("module.group.banner.text", moduleGroup.toString()),
|
||||
ProjectBundle.message("project.roots.module.groups.text"),
|
||||
PlatformIcons.CLOSED_MODULE_GROUP_ICON);
|
||||
return new ModuleGroupNode(moduleGroupConfigurable, moduleGroup);
|
||||
return new ModuleGroupNodeImpl(moduleGroupConfigurable, moduleGroup);
|
||||
}
|
||||
|
||||
private void addRootNodesFromExtensions(final MyNode root, final Project project) {
|
||||
@@ -267,53 +276,35 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
|
||||
}
|
||||
}
|
||||
|
||||
private boolean addNodesFromExtensions(final Module module, final MyNode moduleNode) {
|
||||
boolean nodesAdded = false;
|
||||
private void addNodesFromExtensions(final Module module, final MyNode moduleNode) {
|
||||
for (final ModuleStructureExtension extension : ModuleStructureExtension.EP_NAME.getExtensions()) {
|
||||
nodesAdded |= extension.addModuleNodeChildren(module, moduleNode, TREE_UPDATER);
|
||||
extension.addModuleNodeChildren(module, moduleNode, TREE_UPDATER);
|
||||
}
|
||||
return nodesAdded;
|
||||
}
|
||||
|
||||
public boolean updateProjectTree(final Module[] modules, final ModuleGroup group) {
|
||||
public boolean updateProjectTree(final Module[] modules) {
|
||||
if (myRoot.getChildCount() == 0) return false; //isn't visible
|
||||
final MyNode[] nodes = new MyNode[modules.length];
|
||||
int i = 0;
|
||||
List<Pair<MyNode, Module>> nodes = new ArrayList<>(modules.length);
|
||||
for (Module module : modules) {
|
||||
MyNode node = findModuleNode(module);
|
||||
LOG.assertTrue(node != null, "Module " + module.getName() + " is not in project.");
|
||||
node.removeFromParent();
|
||||
nodes[i++] = node;
|
||||
nodes.add(Pair.create(node, module));
|
||||
}
|
||||
for (final MyNode moduleNode : nodes) {
|
||||
List<String> groupPath = myHideModuleGroups || myFlattenModules
|
||||
? Collections.emptyList()
|
||||
: group != null ? group.getGroupPathList() : Collections.emptyList();
|
||||
if (groupPath.isEmpty()) {
|
||||
myRoot.add(moduleNode);
|
||||
}
|
||||
else {
|
||||
final MyNode moduleGroupNode = getOrCreateModuleGroupNode(groupPath, null);
|
||||
moduleGroupNode.add(moduleNode);
|
||||
}
|
||||
Module module = (Module)moduleNode.getConfigurable().getEditableObject();
|
||||
myFacetEditorFacade.addFacetsNodes(module, moduleNode);
|
||||
addNodesFromExtensions(module, moduleNode);
|
||||
}
|
||||
sortDescendants(myRoot);
|
||||
ModuleGroupingTreeHelper<MyNode> helper = createGroupingHelper();
|
||||
helper.moveModuleNodesToProperGroup(nodes, myRoot, getTreeModel(), myTree);
|
||||
return true;
|
||||
}
|
||||
|
||||
private MyNode getOrCreateModuleGroupNode(List<String> groupPath, @Nullable DefaultTreeModel treeModel) {
|
||||
return ModuleGroupUtil.updateModuleGroupPath(new ModuleGroup(groupPath), myRoot, group1 -> findNodeByObject(myRoot, group1),
|
||||
parentChildRelation -> {
|
||||
MyNode parent = parentChildRelation.getParent();
|
||||
parent.add(parentChildRelation.getChild());
|
||||
if (treeModel != null) {
|
||||
treeModel.nodesWereInserted(parent, new int[]{parent.getChildCount() - 1});
|
||||
}
|
||||
},
|
||||
ModuleStructureConfigurable::createModuleGroupNode);
|
||||
private DefaultTreeModel getTreeModel() {
|
||||
return (DefaultTreeModel)myTree.getModel();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ModuleGroupingTreeHelper<MyNode> createGroupingHelper() {
|
||||
return ModuleGroupingTreeHelper.forTree(myRoot, (node) -> node instanceof ModuleGroupNode ? ((ModuleGroupNode)node).getModuleGroup() : null,
|
||||
(node) -> node instanceof ModuleNode ? ((ModuleNode)node).getModule() : null,
|
||||
!myHideModuleGroups && !myFlattenModules, getModuleGrouper(), ModuleStructureConfigurable::createModuleGroupNode,
|
||||
this::createModuleNode, getNodeComparator());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -336,7 +327,7 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
|
||||
if (node != null) {
|
||||
final TreeNode parent = node.getParent();
|
||||
node.removeFromParent();
|
||||
((DefaultTreeModel)myTree.getModel()).reload(parent);
|
||||
getTreeModel().reload(parent);
|
||||
}
|
||||
myContext.getDaemonAnalyzer().removeElement(new LibraryProjectStructureElement(myContext, library));
|
||||
}
|
||||
@@ -553,7 +544,6 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
|
||||
}
|
||||
|
||||
private void addModuleNode(final Module module) {
|
||||
MyNode node = new ModuleNode(new ModuleConfigurable(myContext.myModulesConfigurator, module, TREE_UPDATER, getModuleGrouper()));
|
||||
final TreePath selectionPath = myTree.getSelectionPath();
|
||||
MyNode parent = null;
|
||||
if (selectionPath != null) {
|
||||
@@ -573,10 +563,8 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
|
||||
}
|
||||
}
|
||||
if (parent == null) parent = myRoot;
|
||||
addNode(node, parent);
|
||||
myFacetEditorFacade.addFacetsNodes(module, node);
|
||||
addNodesFromExtensions(module, node);
|
||||
((DefaultTreeModel)myTree.getModel()).reload(parent);
|
||||
MyNode node = createModuleNode(module, getModuleGrouper());
|
||||
TreeUtil.insertNode(parent, node, getTreeModel(), getNodeComparator());
|
||||
selectNodeInTree(node);
|
||||
final ProjectStructureDaemonAnalyzer daemonAnalyzer = myContext.getDaemonAnalyzer();
|
||||
daemonAnalyzer.queueUpdate(new ModuleProjectStructureElement(myContext, module));
|
||||
@@ -632,9 +620,16 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
|
||||
}
|
||||
}
|
||||
|
||||
private class ModuleNode extends MyNode {
|
||||
public ModuleNode(@NotNull ModuleConfigurable configurable) {
|
||||
private class ModuleNode extends MyNode implements ModuleGroupNode {
|
||||
private final ModuleGroup myModuleAsGroup;
|
||||
|
||||
public ModuleNode(@NotNull ModuleConfigurable configurable, @Nullable ModuleGroup moduleAsGroup) {
|
||||
super(configurable);
|
||||
myModuleAsGroup = moduleAsGroup;
|
||||
}
|
||||
|
||||
public ModuleGroup getModuleGroup() {
|
||||
return myModuleAsGroup;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -658,45 +653,36 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
|
||||
|
||||
@Override
|
||||
protected void reloadNode(DefaultTreeModel treeModel) {
|
||||
TreeNode parent = getParent();
|
||||
List<String> actualPath = parent instanceof ModuleGroupNode ? ((ModuleGroupNode)parent).myModuleGroup.getGroupPathList() : Collections.emptyList();
|
||||
List<String> expectedPath = getModuleGrouper().getGroupPath(getModule());
|
||||
if (!actualPath.equals(expectedPath)) {
|
||||
TreePath path = myTree.getSelectionPath();
|
||||
boolean wasSelected = path != null && this.equals(path.getLastPathComponent());
|
||||
boolean autoScrollWasEnabled = myAutoScrollEnabled;
|
||||
try {
|
||||
myAutoScrollEnabled = false;
|
||||
MyNode newParent = getOrCreateModuleGroupNode(expectedPath, treeModel);
|
||||
treeModel.removeNodeFromParent(this);
|
||||
while (parent instanceof ModuleGroupNode && parent.getChildCount() == 0) {
|
||||
TreeNode grandParent = parent.getParent();
|
||||
treeModel.removeNodeFromParent((MutableTreeNode)parent);
|
||||
parent = grandParent;
|
||||
}
|
||||
|
||||
newParent.add(this);
|
||||
treeModel.nodesWereInserted(newParent, new int[]{newParent.getChildCount() - 1});
|
||||
if (wasSelected) {
|
||||
myTree.expandPath(TreeUtil.getPath(myRoot, newParent));
|
||||
myTree.setSelectionPath(TreeUtil.getPath(myRoot, this));
|
||||
}
|
||||
}
|
||||
finally {
|
||||
myAutoScrollEnabled = autoScrollWasEnabled;
|
||||
}
|
||||
boolean autoScrollWasEnabled = myAutoScrollEnabled;
|
||||
try {
|
||||
myAutoScrollEnabled = false;
|
||||
ModuleGroupingTreeHelper<MyNode> helper = createGroupingHelper();
|
||||
MyNode newNode = helper.moveModuleNodeToProperGroup(this, getModule(), myRoot, treeModel, myTree);
|
||||
treeModel.reload(newNode);
|
||||
}
|
||||
finally {
|
||||
myAutoScrollEnabled = autoScrollWasEnabled;
|
||||
}
|
||||
super.reloadNode(treeModel);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ModuleGroupNode extends MyNode {
|
||||
private interface ModuleGroupNode extends MutableTreeNode {
|
||||
@Nullable
|
||||
ModuleGroup getModuleGroup();
|
||||
}
|
||||
|
||||
private static class ModuleGroupNodeImpl extends MyNode implements ModuleGroupNode {
|
||||
private final ModuleGroup myModuleGroup;
|
||||
|
||||
public ModuleGroupNode(@NotNull NamedConfigurable configurable, ModuleGroup moduleGroup) {
|
||||
public ModuleGroupNodeImpl(@NotNull NamedConfigurable configurable, @NotNull ModuleGroup moduleGroup) {
|
||||
super(configurable, true);
|
||||
myModuleGroup = moduleGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleGroup getModuleGroup() {
|
||||
return myModuleGroup;
|
||||
}
|
||||
}
|
||||
|
||||
private class FacetInModuleRemoveHandler extends RemoveConfigurableHandler<Facet> {
|
||||
@@ -796,7 +782,7 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
myFlattenModules = state;
|
||||
regroupModules(myFlattenModules);
|
||||
regroupModules();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -830,39 +816,22 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
myHideModuleGroups = state;
|
||||
regroupModules(state);
|
||||
regroupModules();
|
||||
}
|
||||
}
|
||||
|
||||
private void regroupModules(boolean removeGroupNodes) {
|
||||
private void regroupModules() {
|
||||
DefaultMutableTreeNode selection = null;
|
||||
final TreePath selectionPath = myTree.getSelectionPath();
|
||||
if (selectionPath != null) {
|
||||
selection = (DefaultMutableTreeNode)selectionPath.getLastPathComponent();
|
||||
}
|
||||
ModuleGrouper grouper = getModuleGrouper();
|
||||
for (Module module : grouper.getAllModules()) {
|
||||
final List<String> groupPath = grouper.getGroupPath(module);
|
||||
updateProjectTree(new Module[]{module}, !groupPath.isEmpty() ? new ModuleGroup(groupPath) : null);
|
||||
}
|
||||
if (removeGroupNodes) {
|
||||
removeModuleGroups();
|
||||
}
|
||||
createGroupingHelper().moveAllModuleNodesToProperGroups(myRoot, getTreeModel());
|
||||
if (selection != null) {
|
||||
TreeUtil.selectInTree(selection, true, myTree);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeModuleGroups() {
|
||||
for (int i = myRoot.getChildCount() - 1; i >= 0; i--) {
|
||||
final MyNode node = (MyNode)myRoot.getChildAt(i);
|
||||
if (node.getConfigurable().getEditableObject() instanceof ModuleGroup) {
|
||||
node.removeFromParent();
|
||||
}
|
||||
}
|
||||
((DefaultTreeModel)myTree.getModel()).reload(myRoot);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractAddGroup createAddAction() {
|
||||
return new AbstractAddGroup(ProjectBundle.message("add.new.header.text")) {
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright 2000-2017 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.ide.projectView.impl
|
||||
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleGrouper
|
||||
import com.intellij.openapi.util.Pair
|
||||
import com.intellij.util.ui.tree.TreeUtil
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import java.util.*
|
||||
import javax.swing.JTree
|
||||
import javax.swing.tree.DefaultTreeModel
|
||||
import javax.swing.tree.MutableTreeNode
|
||||
import javax.swing.tree.TreeNode
|
||||
|
||||
/**
|
||||
* Provides methods to build trees where nodes are grouped by modules (and optionally by module groups).
|
||||
*
|
||||
* @author nik
|
||||
*/
|
||||
class ModuleGroupingTreeHelper<N: MutableTreeNode> private constructor(
|
||||
private val groupingEnabled: Boolean,
|
||||
private val grouper: ModuleGrouper,
|
||||
private val moduleGroupNodeFactory: (ModuleGroup) -> N,
|
||||
private val moduleNodeFactory: (Module, ModuleGrouper) -> N,
|
||||
private val nodeComparator: Comparator<in N>
|
||||
) {
|
||||
private val nodeForGroup = HashMap<ModuleGroup, N>()
|
||||
private val nodeData = HashMap<N, ModuleTreeNodeData>()
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun <N : MutableTreeNode> forEmptyTree(groupingEnabled: Boolean, grouper: ModuleGrouper,
|
||||
moduleGroupNodeFactory: (ModuleGroup) -> N, moduleNodeFactory: (Module, ModuleGrouper) -> N,
|
||||
nodeComparator: Comparator<in N>) =
|
||||
ModuleGroupingTreeHelper(groupingEnabled, grouper, moduleGroupNodeFactory, moduleNodeFactory, nodeComparator)
|
||||
|
||||
@JvmStatic
|
||||
fun <N : MutableTreeNode> forTree(rootNode: N, moduleGroupByNode: (N) -> ModuleGroup?, moduleByNode: (N) -> Module?,
|
||||
groupingEnabled: Boolean, grouper: ModuleGrouper,
|
||||
moduleGroupNodeFactory: (ModuleGroup) -> N, moduleNodeFactory: (Module, ModuleGrouper) -> N,
|
||||
nodeComparator: Comparator<in N>): ModuleGroupingTreeHelper<N> {
|
||||
val helper = ModuleGroupingTreeHelper(groupingEnabled, grouper, moduleGroupNodeFactory, moduleNodeFactory, nodeComparator)
|
||||
TreeUtil.traverse(rootNode) { node ->
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val group = moduleGroupByNode(node as N)
|
||||
val module = moduleByNode(node)
|
||||
if (group != null) {
|
||||
helper.nodeForGroup[group] = node
|
||||
}
|
||||
if (group != null || module != null) {
|
||||
helper.nodeData[node] = ModuleTreeNodeData(module, group)
|
||||
}
|
||||
true
|
||||
}
|
||||
return helper
|
||||
}
|
||||
}
|
||||
|
||||
fun createModuleNodes(modules: Collection<Module>, rootNode: N, model: DefaultTreeModel): List<N> {
|
||||
val nodes = modules.map { createModuleNode(it, rootNode, model) }
|
||||
TreeUtil.sortRecursively(rootNode, nodeComparator)
|
||||
model.nodeStructureChanged(rootNode)
|
||||
return nodes
|
||||
}
|
||||
|
||||
private fun createModuleNode(module: Module, rootNode: N, model: DefaultTreeModel): N {
|
||||
val group = ModuleGroup(grouper.getGroupPath(module))
|
||||
val parentNode = getOrCreateNodeForModuleGroup(group, rootNode, model, true)
|
||||
val moduleNode = moduleNodeFactory(module, grouper)
|
||||
insertModuleNode(moduleNode, parentNode, module, model, true)
|
||||
return moduleNode
|
||||
}
|
||||
|
||||
/**
|
||||
* If [bulkOperation] is true, no events will be fired and new node will be added into arbitrary place in the children list
|
||||
*/
|
||||
private fun insertModuleNode(moduleNode: N, parentNode: N, module: Module, model: DefaultTreeModel, bulkOperation: Boolean) {
|
||||
val moduleAsGroup = grouper.getModuleAsGroupPath(module)
|
||||
if (moduleAsGroup != null) {
|
||||
val moduleGroup = ModuleGroup(moduleAsGroup)
|
||||
val oldModuleGroupNode = nodeForGroup[moduleGroup]
|
||||
if (oldModuleGroupNode != null) {
|
||||
moveChildren(oldModuleGroupNode, moduleNode, model)
|
||||
model.removeNodeFromParent(oldModuleGroupNode)
|
||||
removeNode(oldModuleGroupNode)
|
||||
}
|
||||
nodeForGroup[moduleGroup] = moduleNode
|
||||
nodeData[moduleNode] = ModuleTreeNodeData(module, moduleGroup)
|
||||
}
|
||||
else {
|
||||
nodeData[moduleNode] = ModuleTreeNodeData(module, null)
|
||||
}
|
||||
|
||||
insertNode(moduleNode, parentNode, model, bulkOperation)
|
||||
}
|
||||
|
||||
private fun moveChildren(fromNode: N, toNode: N, model: DefaultTreeModel) {
|
||||
val children = TreeUtil.childrenToArray(fromNode)
|
||||
moveChildren(children, toNode, model)
|
||||
}
|
||||
|
||||
private fun moveChildren(children: List<TreeNode>, toNode: N, model: DefaultTreeModel) {
|
||||
TreeUtil.addChildrenTo(toNode, children)
|
||||
TreeUtil.sortChildren(toNode, nodeComparator)
|
||||
model.nodeStructureChanged(toNode)
|
||||
}
|
||||
|
||||
/**
|
||||
* If [bulkOperation] is true, no events will be fired and new node will be added into arbitrary place in the children list
|
||||
*/
|
||||
private fun getOrCreateNodeForModuleGroup(group: ModuleGroup, rootNode: N, model: DefaultTreeModel, bulkOperation: Boolean): N {
|
||||
if (!groupingEnabled) return rootNode
|
||||
|
||||
var parentNode = rootNode
|
||||
val path = group.groupPathList
|
||||
for (i in path.indices) {
|
||||
val current = ModuleGroup(path.subList(0, i+1))
|
||||
var node = nodeForGroup[current]
|
||||
if (node == null) {
|
||||
node = moduleGroupNodeFactory(current)
|
||||
insertNode(node, parentNode, model, bulkOperation)
|
||||
nodeForGroup[current] = node
|
||||
nodeData[node] = ModuleTreeNodeData(null,group)
|
||||
}
|
||||
parentNode = node
|
||||
}
|
||||
return parentNode
|
||||
}
|
||||
|
||||
private fun insertNode(node: N, parentNode: N, model: DefaultTreeModel, bulkOperation: Boolean) {
|
||||
if (bulkOperation) {
|
||||
parentNode.insert(node, parentNode.childCount)
|
||||
}
|
||||
else {
|
||||
TreeUtil.insertNode(node, parentNode, model, nodeComparator)
|
||||
}
|
||||
}
|
||||
|
||||
fun moveAllModuleNodesToProperGroups(rootNode: N, model: DefaultTreeModel) {
|
||||
val modules = nodeData.values.map { it.module }.filterNotNull()
|
||||
nodeData.keys.forEach { it.removeFromParent() }
|
||||
nodeData.clear()
|
||||
nodeForGroup.clear()
|
||||
createModuleNodes(modules, rootNode, model)
|
||||
}
|
||||
|
||||
fun moveModuleNodesToProperGroup(nodes: List<Pair<N, Module>>, rootNode: N, model: DefaultTreeModel, tree: JTree) {
|
||||
nodes.forEach {
|
||||
moveModuleNodeToProperGroup(it.first, it.second, rootNode, model, tree)
|
||||
}
|
||||
}
|
||||
|
||||
fun moveModuleNodeToProperGroup(node: N, module: Module, rootNode: N, model: DefaultTreeModel, tree: JTree): N {
|
||||
val actualGroup = ModuleGroup(grouper.getGroupPath(module))
|
||||
val parent = node.parent
|
||||
val expectedParent = if (groupingEnabled) nodeForGroup[actualGroup] else rootNode
|
||||
if (expectedParent == parent) return node
|
||||
|
||||
val selectionPath = tree.selectionPath
|
||||
val wasSelected = selectionPath?.lastPathComponent == node
|
||||
model.removeNodeFromParent(node)
|
||||
|
||||
val nodeAsGroup = nodeData[node]?.group
|
||||
removeNode(node)
|
||||
if (nodeAsGroup != null) {
|
||||
val childrenToKeep = TreeUtil.childrenToArray(node).filter { it in nodeData }
|
||||
if (childrenToKeep.isNotEmpty()) {
|
||||
val newGroupNode = getOrCreateNodeForModuleGroup(nodeAsGroup, rootNode, model, false)
|
||||
moveChildren(childrenToKeep, newGroupNode, model)
|
||||
}
|
||||
}
|
||||
|
||||
removeEmptySyntheticModuleGroupNodes(parent, model)
|
||||
|
||||
val newParent = getOrCreateNodeForModuleGroup(actualGroup, rootNode, model, false)
|
||||
val newNode = moduleNodeFactory(module, grouper)
|
||||
insertModuleNode(newNode, newParent, module, model, false)
|
||||
|
||||
if (wasSelected) {
|
||||
tree.expandPath(TreeUtil.getPath(rootNode, newParent))
|
||||
tree.selectionPath = TreeUtil.getPath(rootNode, newNode)
|
||||
}
|
||||
return newNode
|
||||
}
|
||||
|
||||
private fun removeEmptySyntheticModuleGroupNodes(parentNode: TreeNode?, model: DefaultTreeModel) {
|
||||
var parent = parentNode
|
||||
while (parent is MutableTreeNode && parent in nodeData && nodeData[parent]?.module == null && parent.childCount == 0) {
|
||||
val grandParent = parent.parent
|
||||
model.removeNodeFromParent(parent)
|
||||
removeNode(parent as N)
|
||||
parent = grandParent
|
||||
}
|
||||
}
|
||||
|
||||
private fun removeNode(node: N) {
|
||||
val group = nodeData.remove(node)?.group
|
||||
if (group != null) {
|
||||
nodeForGroup.remove(group)
|
||||
}
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
fun getNodeForGroupMap() = Collections.unmodifiableMap(nodeForGroup)
|
||||
|
||||
@TestOnly
|
||||
fun getModuleByNodeMap() = nodeData.mapValues { it.value.module }.filterValues { it != null }
|
||||
|
||||
@TestOnly
|
||||
fun getGroupByNodeMap() = nodeData.mapValues { it.value.group }.filterValues { it != null }
|
||||
}
|
||||
|
||||
private class ModuleTreeNodeData(val module: Module?, val group: ModuleGroup?)
|
||||
+258
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.ide.projectView
|
||||
|
||||
import com.intellij.ide.projectView.impl.ModuleGroup
|
||||
import com.intellij.ide.projectView.impl.ModuleGroupingTreeHelper
|
||||
import com.intellij.module.getQualifiedNameModuleGrouper
|
||||
import com.intellij.module.renameModule
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleGrouper
|
||||
import com.intellij.openapi.util.Pair
|
||||
import com.intellij.testFramework.PlatformTestCase
|
||||
import com.intellij.testFramework.PlatformTestUtil
|
||||
import com.intellij.ui.treeStructure.Tree
|
||||
import com.intellij.util.ui.tree.TreeUtil
|
||||
import junit.framework.TestCase
|
||||
import java.util.*
|
||||
import javax.swing.tree.DefaultMutableTreeNode
|
||||
import javax.swing.tree.DefaultTreeModel
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class ModuleGroupingTreeHelperTest: PlatformTestCase() {
|
||||
private lateinit var tree: Tree
|
||||
private lateinit var root: MockModuleTreeNode
|
||||
private lateinit var model: DefaultTreeModel
|
||||
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
root = MockModuleTreeNode("root")
|
||||
model = DefaultTreeModel(root)
|
||||
tree = Tree(model)
|
||||
}
|
||||
|
||||
fun `test disabled grouping`() {
|
||||
createHelper(false).createModuleNodes("a.main")
|
||||
assertTreeEqual("""
|
||||
-root
|
||||
a.main""")
|
||||
createHelperFromTree(true).moveAllModuleNodesAndCheckResult("""
|
||||
-root
|
||||
-a
|
||||
a.main""")
|
||||
}
|
||||
|
||||
fun `test single module`() {
|
||||
createHelper().createModuleNodes("a.main")
|
||||
assertTreeEqual("""
|
||||
-root
|
||||
-a
|
||||
a.main""")
|
||||
|
||||
createHelperFromTree(false).moveAllModuleNodesAndCheckResult("""
|
||||
-root
|
||||
a.main""")
|
||||
}
|
||||
|
||||
fun `test two modules`() {
|
||||
createHelper().createModuleNodes("a.main", "a.util")
|
||||
assertTreeEqual("""
|
||||
-root
|
||||
-a
|
||||
a.main
|
||||
a.util
|
||||
""")
|
||||
|
||||
createHelperFromTree(false).moveAllModuleNodesAndCheckResult("""
|
||||
-root
|
||||
a.main
|
||||
a.util""")
|
||||
}
|
||||
|
||||
fun `test two groups`() {
|
||||
createHelper().createModuleNodes("a.main", "b.util", "a.util", "b.main")
|
||||
assertTreeEqual("""
|
||||
-root
|
||||
-a
|
||||
a.main
|
||||
a.util
|
||||
-b
|
||||
b.main
|
||||
b.util
|
||||
""")
|
||||
|
||||
createHelperFromTree(false).moveAllModuleNodesAndCheckResult("""
|
||||
-root
|
||||
a.main
|
||||
a.util
|
||||
b.main
|
||||
b.util
|
||||
""")
|
||||
}
|
||||
|
||||
fun `test module as a group`() {
|
||||
createHelper().createModuleNodes("a.impl", "a", "a.tests")
|
||||
assertTreeEqual("""
|
||||
-root
|
||||
-a
|
||||
a.impl
|
||||
a.tests
|
||||
""")
|
||||
|
||||
createHelperFromTree(false).moveAllModuleNodesAndCheckResult("""
|
||||
-root
|
||||
a
|
||||
a.impl
|
||||
a.tests""")
|
||||
}
|
||||
|
||||
fun `test move module node to new group`() {
|
||||
val nodes = createHelper().createModuleNodes("main", "util")
|
||||
assertTreeEqual("""
|
||||
-root
|
||||
main
|
||||
util""")
|
||||
val node = nodes.find { it.second.name == "main" }!!
|
||||
renameModule(node.second, "a.main")
|
||||
moveModuleNodeToProperGroupAndCheckResult(node, """
|
||||
-root
|
||||
-a
|
||||
a.main
|
||||
util""")
|
||||
}
|
||||
|
||||
fun `test move module node from parent module`() {
|
||||
val nodes = createHelper().createModuleNodes("a", "a.main")
|
||||
assertTreeEqual("""
|
||||
-root
|
||||
-a
|
||||
a.main""")
|
||||
val node = nodes.find { it.second.name == "a.main" }!!
|
||||
renameModule(node.second, "main")
|
||||
moveModuleNodeToProperGroupAndCheckResult(node, """
|
||||
-root
|
||||
a
|
||||
main""")
|
||||
}
|
||||
|
||||
fun `test move module node to parent module`() {
|
||||
val nodes = createHelper().createModuleNodes("a", "main")
|
||||
val node = nodes.find { it.second.name == "main" }!!
|
||||
renameModule(node.second, "a.main")
|
||||
moveModuleNodeToProperGroupAndCheckResult(node, """
|
||||
-root
|
||||
-a
|
||||
a.main""")
|
||||
}
|
||||
|
||||
fun `test module node become parent module`() {
|
||||
val nodes = createHelper().createModuleNodes("b", "a.main")
|
||||
val node = nodes.find { it.second.name == "b" }!!
|
||||
renameModule(node.second, "a")
|
||||
moveModuleNodeToProperGroupAndCheckResult(node, """
|
||||
-root
|
||||
-a
|
||||
a.main""")
|
||||
}
|
||||
|
||||
fun `test parent module become ordinary module`() {
|
||||
val nodes = createHelper().createModuleNodes("a", "a.main")
|
||||
val node = nodes.find { it.second.name == "a" }!!
|
||||
renameModule(node.second, "b")
|
||||
moveModuleNodeToProperGroupAndCheckResult(node, """
|
||||
-root
|
||||
-a
|
||||
a.main
|
||||
b""")
|
||||
}
|
||||
|
||||
private fun moveModuleNodeToProperGroupAndCheckResult(node: Pair<MockModuleTreeNode, Module>,
|
||||
expected: String) {
|
||||
val helper = createHelperFromTree()
|
||||
helper.checkConsistency()
|
||||
helper.moveModuleNodeToProperGroup(node.first, node.second, root, model, tree)
|
||||
assertTreeEqual(expected)
|
||||
helper.checkConsistency()
|
||||
}
|
||||
|
||||
private fun ModuleGroupingTreeHelper<MockModuleTreeNode>.moveAllModuleNodesAndCheckResult(expected: String) {
|
||||
checkConsistency()
|
||||
moveAllModuleNodesToProperGroups(root, model)
|
||||
assertTreeEqual(expected)
|
||||
checkConsistency()
|
||||
}
|
||||
|
||||
private fun ModuleGroupingTreeHelper<MockModuleTreeNode>.createModuleNodes(vararg names: String): List<Pair<MockModuleTreeNode, Module>> {
|
||||
val modules = createModules(*names)
|
||||
val nodes = createModuleNodes(modules, root, model)
|
||||
return nodes.map { Pair(it, (it as MockModuleNode).module)}
|
||||
}
|
||||
|
||||
private fun assertTreeEqual(expected: String) {
|
||||
TreeUtil.expandAll(tree)
|
||||
PlatformTestUtil.assertTreeEqual(tree, expected.trimIndent() + "\n")
|
||||
}
|
||||
|
||||
private fun createHelper(enableGrouping: Boolean = true): ModuleGroupingTreeHelper<MockModuleTreeNode> {
|
||||
val grouper = getQualifiedNameModuleGrouper(myProject)
|
||||
return ModuleGroupingTreeHelper.forEmptyTree(enableGrouping, grouper, ::MockModuleGroupNode, ::MockModuleNode, nodeComparator)
|
||||
}
|
||||
|
||||
private fun createHelperFromTree(enableGrouping: Boolean = true): ModuleGroupingTreeHelper<MockModuleTreeNode> {
|
||||
val grouper = getQualifiedNameModuleGrouper(myProject)
|
||||
return ModuleGroupingTreeHelper.forTree(root, { it.moduleGroup }, { (it as? MockModuleNode)?.module },
|
||||
enableGrouping, grouper, ::MockModuleGroupNode, ::MockModuleNode, nodeComparator)
|
||||
}
|
||||
|
||||
private fun createModules(vararg names: String) = names.map { createModule(it) }
|
||||
|
||||
private fun ModuleGroupingTreeHelper<MockModuleTreeNode>.checkConsistency() {
|
||||
val expectedNodeForGroup = HashMap<ModuleGroup, MockModuleTreeNode>(getNodeForGroupMap())
|
||||
val expectedGroupByNode = HashMap<MockModuleTreeNode, ModuleGroup>(getGroupByNodeMap())
|
||||
val expectedModuleByNode = HashMap<MockModuleTreeNode, Module>(getModuleByNodeMap())
|
||||
TreeUtil.traverse(root, { o ->
|
||||
val node = o as MockModuleTreeNode
|
||||
if (node == root) return@traverse true
|
||||
TestCase.assertSame(node, expectedNodeForGroup[node.moduleGroup])
|
||||
expectedNodeForGroup.remove(node.moduleGroup)
|
||||
TestCase.assertEquals(node.moduleGroup, expectedGroupByNode[node])
|
||||
expectedGroupByNode.remove(node)
|
||||
if (node is MockModuleNode) {
|
||||
TestCase.assertEquals(node.module, expectedModuleByNode[node])
|
||||
expectedModuleByNode.remove(node)
|
||||
}
|
||||
true
|
||||
})
|
||||
assertEmpty("Unexpected nodes in helper", expectedNodeForGroup.entries)
|
||||
assertEmpty("Unexpected groups in helper", expectedGroupByNode.entries)
|
||||
assertEmpty("Unexpected modules in helper", expectedModuleByNode.entries)
|
||||
}
|
||||
}
|
||||
|
||||
private val nodeComparator = Comparator.comparing { node: MockModuleTreeNode -> node.text }
|
||||
|
||||
private open class MockModuleTreeNode(userObject: Any, val text: String = userObject.toString()): DefaultMutableTreeNode(text) {
|
||||
open val moduleGroup: ModuleGroup? = null
|
||||
override fun toString() = text
|
||||
}
|
||||
|
||||
private class MockModuleNode(val module: Module, grouper: ModuleGrouper): MockModuleTreeNode(module, module.name) {
|
||||
override val moduleGroup = grouper.getModuleAsGroupPath(module)?.let(::ModuleGroup)
|
||||
}
|
||||
|
||||
private class MockModuleGroupNode(override val moduleGroup: ModuleGroup): MockModuleTreeNode(moduleGroup)
|
||||
@@ -332,16 +332,28 @@ public final class TreeUtil {
|
||||
}
|
||||
|
||||
public static void sort(@NotNull final DefaultMutableTreeNode node, @Nullable Comparator comparator) {
|
||||
final List<TreeNode> children = childrenToArray(node);
|
||||
Collections.sort(children, comparator);
|
||||
node.removeAllChildren();
|
||||
addChildrenTo(node, children);
|
||||
sortRecursively(node, comparator);
|
||||
}
|
||||
|
||||
public static <T extends MutableTreeNode> void sortRecursively(@NotNull T node, @Nullable Comparator<? super T> comparator) {
|
||||
sortChildren(node, comparator);
|
||||
for (int i = 0; i < node.getChildCount(); i++) {
|
||||
sort((DefaultMutableTreeNode) node.getChildAt(i), comparator);
|
||||
//noinspection unchecked
|
||||
sortRecursively((T) node.getChildAt(i), comparator);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addChildrenTo(@NotNull final MutableTreeNode node, @NotNull final List<TreeNode> children) {
|
||||
public static <T extends MutableTreeNode> void sortChildren(@NotNull T node, @Nullable Comparator<? super T> comparator) {
|
||||
//noinspection unchecked
|
||||
final List<T> children = (List)childrenToArray(node);
|
||||
Collections.sort(children, comparator);
|
||||
for (int i = node.getChildCount() - 1; i >= 0; i--) {
|
||||
node.remove(i);
|
||||
}
|
||||
addChildrenTo(node, children);
|
||||
}
|
||||
|
||||
public static void addChildrenTo(@NotNull final MutableTreeNode node, @NotNull final List<? extends TreeNode> children) {
|
||||
for (final Object aChildren : children) {
|
||||
final MutableTreeNode child = (MutableTreeNode)aChildren;
|
||||
node.insert(child, node.getChildCount());
|
||||
|
||||
+1
-11
@@ -17,7 +17,6 @@ package com.intellij.module
|
||||
|
||||
import com.intellij.ide.projectView.impl.ModuleGroup
|
||||
import com.intellij.openapi.module.ModuleGrouper
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.testFramework.PlatformTestCase
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
@@ -59,14 +58,5 @@ class GroupModulesByQualifiedNamesTest : PlatformTestCase() {
|
||||
}
|
||||
|
||||
private val grouper: ModuleGrouper
|
||||
get() {
|
||||
val property = Registry.get("project.qualified.module.names")
|
||||
return try {
|
||||
property.setValue(true)
|
||||
ModuleGrouper.instanceFor(myProject)
|
||||
}
|
||||
finally {
|
||||
property.setValue(false)
|
||||
}
|
||||
}
|
||||
get() = getQualifiedNameModuleGrouper(myProject)
|
||||
}
|
||||
|
||||
@@ -43,6 +43,11 @@ abstract class ModuleGrouper {
|
||||
|
||||
abstract fun getGroupPathByModuleName(name: String): List<String>
|
||||
|
||||
/**
|
||||
* If [module] itself can be considered as a group, returns its groups. Otherwise returns null.
|
||||
*/
|
||||
abstract fun getModuleAsGroupPath(module: Module): List<String>?
|
||||
|
||||
abstract fun getAllModules(): Array<Module>
|
||||
|
||||
companion object {
|
||||
@@ -76,6 +81,8 @@ private class QualifiedNameGrouper(project: Project, model: ModifiableModuleMode
|
||||
override fun getShortenedNameByFullModuleName(name: String) = StringUtil.getShortName(name)
|
||||
|
||||
override fun getGroupPathByModuleName(name: String) = name.split('.').dropLast(1)
|
||||
|
||||
override fun getModuleAsGroupPath(module: Module) = getModuleName(module).split('.')
|
||||
}
|
||||
|
||||
private class ExplicitModuleGrouper(project: Project, model: ModifiableModuleModel?): ModuleGrouperBase(project, model) {
|
||||
@@ -87,4 +94,6 @@ private class ExplicitModuleGrouper(project: Project, model: ModifiableModuleMod
|
||||
override fun getShortenedNameByFullModuleName(name: String) = name
|
||||
|
||||
override fun getGroupPathByModuleName(name: String): List<String> = emptyList()
|
||||
|
||||
override fun getModuleAsGroupPath(module: Module) = null
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.module
|
||||
|
||||
import com.intellij.openapi.application.runWriteAction
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleGrouper
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
fun getQualifiedNameModuleGrouper(project: Project): ModuleGrouper {
|
||||
val property = Registry.get("project.qualified.module.names")
|
||||
return try {
|
||||
property.setValue(true)
|
||||
ModuleGrouper.instanceFor(project)
|
||||
}
|
||||
finally {
|
||||
property.setValue(false)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun renameModule(module: Module, newName: String) {
|
||||
val model = ModuleManager.getInstance(module.project).modifiableModel
|
||||
model.renameModule(module, newName)
|
||||
runWriteAction { model.commit() }
|
||||
}
|
||||
Reference in New Issue
Block a user