qualified module names: don't show module name in Project View if it matches directory structure (IDEA-166061)

If module name can be composed by appending its directory name to a module name for the parent directory it makes no sense to show the full module name on the directory node in Project View.
This commit is contained in:
nik
2017-02-01 14:43:57 +03:00
parent 8619b14d83
commit 83e84fc677
6 changed files with 81 additions and 4 deletions
@@ -15,14 +15,21 @@
*/
package com.intellij.projectView;
import com.intellij.ide.projectView.PresentationData;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.ide.util.treeView.PresentableNodeDescriptor;
import com.intellij.module.ModuleGroupTestsKt;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.impl.ModuleManagerImpl;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.ui.Queryable;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.PsiTestUtil;
import org.junit.Assert;
import java.util.List;
import java.util.function.Function;
public class ProjectTreeStructureTest extends BaseProjectViewTestCase {
@@ -182,4 +189,48 @@ public class ProjectTreeStructureTest extends BaseProjectViewTestCase {
" A.java\n" +
" testContentRootUnderExcluded.iml\n");
}
public void testQualifiedModuleNames() throws Exception {
VirtualFile testDataRoot = ModuleRootManager.getInstance(myModule).getContentRoots()[0];
Module a = createModule("a");
PsiTestUtil.addContentRoot(a, testDataRoot.findFileByRelativePath("a"));
Module main = createModule("a.main");
PsiTestUtil.addContentRoot(main, testDataRoot.findFileByRelativePath("a/main"));
Module util = createModule("util");
PsiTestUtil.addContentRoot(util, testDataRoot.findFileByRelativePath("a/util"));
Module b = createModule("x.b");
PsiTestUtil.addContentRoot(b, testDataRoot.findFileByRelativePath("a/b"));
myStructure.setShowLibraryContents(false);
//todo[nik] this function is generic enough, it can be moved to testFramework
Function<Object, String> nodePresenter = o -> {
AbstractTreeNode node = (AbstractTreeNode)o;
node.update();
PresentationData presentation = node.getPresentation();
List<PresentableNodeDescriptor.ColoredFragment> fragments = presentation.getColoredText();
if (fragments.isEmpty()) {
return presentation.getPresentableText();
}
return StringUtil.join(fragments, PresentableNodeDescriptor.ColoredFragment::getText, "");
};
String treeStructure = ModuleGroupTestsKt.runWithQualifiedModuleNamesEnabled(() -> PlatformTestUtil.print(myStructure, myStructure.getRootElement(), nodePresenter));
assertEquals("testQualifiedModuleNames\n" +
" a.iml\n" +
" a.main.iml\n" +
" qualifiedModuleNames [testQualifiedModuleNames]\n" +
" a\n" +
" b [x.b]\n" +
" b.txt\n" +
" main\n" +
" main.txt\n" +
" util\n" +
" util.txt\n" +
" testQualifiedModuleNames.iml\n" +
" util.iml\n" +
" x.b.iml\n",
treeStructure);
}
}
@@ -26,6 +26,7 @@ import com.intellij.idea.ActionsBundle;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileTypes.FileTypeRegistry;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleGrouperKt;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.OrderEntry;
@@ -99,7 +100,7 @@ public class PsiDirectoryNode extends BasePsiNode<PsiDirectory> implements Navig
if (!shouldShowModuleName()) {
data.addText(directoryFile.getName() + " ", SimpleTextAttributes.REGULAR_ATTRIBUTES);
}
else if (Comparing.equal(module.getName(), directoryFile.getName())) {
else if (moduleNameMatchesDirectoryName(module, directoryFile, fi)) {
data.addText(directoryFile.getName(), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
}
else {
@@ -135,6 +136,28 @@ public class PsiDirectoryNode extends BasePsiNode<PsiDirectory> implements Navig
setupIcon(data, psiDirectory);
}
private static boolean moduleNameMatchesDirectoryName(Module module, VirtualFile directoryFile, ProjectFileIndex fileIndex) {
String moduleName = module.getName();
String directoryName = directoryFile.getName();
if (moduleName.equals(directoryName)) {
return true;
}
if (ModuleGrouperKt.isQualifiedModuleNamesEnabled() && moduleName.endsWith(directoryName)) {
int parentPrefixLength = moduleName.length() - directoryName.length() - 1;
if (parentPrefixLength > 0 && moduleName.charAt(parentPrefixLength) == '.') {
VirtualFile parentDirectory = directoryFile.getParent();
if (ProjectRootsUtil.isModuleContentRoot(parentDirectory, module.getProject())) {
Module parentModule = fileIndex.getModuleForFile(parentDirectory);
if (parentModule != null && parentModule.getName().length() == parentPrefixLength
&& moduleName.startsWith(parentModule.getName())) {
return true;
}
}
}
}
return false;
}
protected void setupIcon(PresentationData data, PsiDirectory psiDirectory) {
final VirtualFile virtualFile = psiDirectory.getVirtualFile();
if (PlatformUtils.isAppCode()) {
@@ -26,15 +26,18 @@ import com.intellij.openapi.util.registry.Registry
* @author nik
*/
fun getQualifiedNameModuleGrouper(project: Project): ModuleGrouper {
return runWithQualifiedModuleNamesEnabled { ModuleGrouper.instanceFor(project) }
}
fun <T> runWithQualifiedModuleNamesEnabled(action: () -> T): T {
val property = Registry.get("project.qualified.module.names")
return try {
property.setValue(true)
ModuleGrouper.instanceFor(project)
action()
}
finally {
property.setValue(false)
}
}
fun renameModule(module: Module, newName: String) {