From 83e84fc677dd9a2f805771a34309e083a4b3e3db Mon Sep 17 00:00:00 2001 From: nik Date: Wed, 1 Feb 2017 14:43:27 +0300 Subject: [PATCH] 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. --- .../qualifiedModuleNames/a/b/b.txt | 0 .../qualifiedModuleNames/a/main/main.txt | 0 .../qualifiedModuleNames/a/util/util.txt | 0 .../projectView/ProjectTreeStructureTest.java | 53 ++++++++++++++++++- .../impl/nodes/PsiDirectoryNode.java | 25 ++++++++- .../com/intellij/module/moduleGroupTests.kt | 7 ++- 6 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 java/java-tests/testData/projectView/qualifiedModuleNames/a/b/b.txt create mode 100644 java/java-tests/testData/projectView/qualifiedModuleNames/a/main/main.txt create mode 100644 java/java-tests/testData/projectView/qualifiedModuleNames/a/util/util.txt diff --git a/java/java-tests/testData/projectView/qualifiedModuleNames/a/b/b.txt b/java/java-tests/testData/projectView/qualifiedModuleNames/a/b/b.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/java/java-tests/testData/projectView/qualifiedModuleNames/a/main/main.txt b/java/java-tests/testData/projectView/qualifiedModuleNames/a/main/main.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/java/java-tests/testData/projectView/qualifiedModuleNames/a/util/util.txt b/java/java-tests/testData/projectView/qualifiedModuleNames/a/util/util.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/java/java-tests/testSrc/com/intellij/projectView/ProjectTreeStructureTest.java b/java/java-tests/testSrc/com/intellij/projectView/ProjectTreeStructureTest.java index 5eecadf0d209..7162a44d1059 100644 --- a/java/java-tests/testSrc/com/intellij/projectView/ProjectTreeStructureTest.java +++ b/java/java-tests/testSrc/com/intellij/projectView/ProjectTreeStructureTest.java @@ -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 nodePresenter = o -> { + AbstractTreeNode node = (AbstractTreeNode)o; + node.update(); + PresentationData presentation = node.getPresentation(); + List 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); + } } diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiDirectoryNode.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiDirectoryNode.java index e32b00009027..a4108c25eae4 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiDirectoryNode.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiDirectoryNode.java @@ -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 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 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()) { diff --git a/platform/testFramework/src/com/intellij/module/moduleGroupTests.kt b/platform/testFramework/src/com/intellij/module/moduleGroupTests.kt index 792db4c6ab4d..f29542424054 100644 --- a/platform/testFramework/src/com/intellij/module/moduleGroupTests.kt +++ b/platform/testFramework/src/com/intellij/module/moduleGroupTests.kt @@ -26,15 +26,18 @@ import com.intellij.openapi.util.registry.Registry * @author nik */ fun getQualifiedNameModuleGrouper(project: Project): ModuleGrouper { + return runWithQualifiedModuleNamesEnabled { ModuleGrouper.instanceFor(project) } +} + +fun 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) {