IDEA-330315 Fix modules with names like a.b.c not showing when a is also a module

This is much more complicated than it seems.

At the moment, we don't fully support modules that are children
of other modules. Some limited support was implemented for
the Packages View, but for the Project View it's much harder
because the file system structure and the module grouping structure
can conflict with each other.

So the only implementation that's reasonably possible without
redesigning the whole module structure is to let nested modules
to be flattened under the topmost common group. This was
already implemented to a certain extent, but there was a special
exception made in case the top level group is also a module.
Since this is not supported properly, though, it led in some cases
to some modules not showing up at all.

For example, if there are modules named 'a', 'a.b' and 'a.b.c',
then this code would look for the shortest parent group path
that's also a module name. In this case it's 'a'. However,
since this is a top-level group, the code would explicitly
ignore it, as it doesn't have a parent to be used as the parent
for the module a.b.c. Eventually this module was completely
ignored, because it was considered to be a child of the group a.b,
which didn't exist either because a.b is a module and not a group.

This code was placed here in the first place to avoid nodes
with the same names in the project tree. For example,
if we consider a.b to be both a group and a module,
then we'd have to put both in the tree under 'a', which
just looks too ugly. So the code ensured that instead of

-a (group)
 -a.b (group)
  -a.b.c
 -a.b (module)

we got

-a (group)
 -a.b (module)
 -a.b.c (module)

So far so good, but this code only worked if 'a' is not a module
in itself. If it is a module, then we still end up with two 'a's
at the top level, and there's no way around it without rethinking
the entire approach.

Fix this mess by ignoring the first level altogether. Since
it's going to end up in the tree as a group anyway,
we might as well think of it as a group and forget that it
can also be a module. This fix leads to the following structure:

-a (group)
 -a.b (module)
 -a.b.c (module)
-a (module)

This is far from perfect, but at least it works.

As a side effect, this fix effectively disables sub-modules
support for the Package View. Now all modules are grouped
under the common group. But at least they're all properly displayed.

A test for this three-level thing was added, and the test
for the Package View with sub-modules was updated accordingly.

GitOrigin-RevId: b48260512e0944c962c04fcbff3df96230f2ff5b
This commit is contained in:
Sergei Tachenov
2023-11-17 18:08:30 +02:00
committed by intellij-monorepo-bot
parent f6af5745f7
commit f1d88aa658
2 changed files with 36 additions and 8 deletions

View File

@@ -188,6 +188,34 @@ class ModulesInProjectViewTest : ModulesInProjectViewTestCase() {
""".trimMargin())
}
fun `test three-level modules`() {
val root = directoryContent {
dir("module1") {
dir("subdir") {}
}
dir("module1.module2") {
dir("subdir") {}
}
dir("module1.module2.module3") {
dir("subdir") {}
}
}.generateInVirtualTempDir()
PsiTestUtil.addContentRoot(createModule("module1"), root.findChild("module1")!!)
PsiTestUtil.addContentRoot(createModule("module1.module2"), root.findChild("module1.module2")!!)
PsiTestUtil.addContentRoot(createModule("module1.module2.module3"), root.findChild("module1.module2.module3")!!)
assertStructureEqual("""
|Project
| Group: module1
| module1.module2
| subdir
| module1.module2.module3
| subdir
| module1
| subdir
|
""".trimMargin())
}
fun `test modules in nested groups`() {
val root = directoryContent {
dir("module1") {
@@ -282,15 +310,15 @@ class ModulesInPackageViewTest : ModulesInProjectViewTestCase() {
|Project
| Group: module1
| Module name=module1.module11
| Module name=module1.module11.main
| Module name=module1.module11.test
| Module name=module1.module11.main
| Module name=module1.module11.test
| Module name=module1.module12
| Module name=module1.module12.main
| Module name=module1.module12.test
| Module name=module1.module12.main
| Module name=module1.module12.test
| Group: module2
| Module name=module2.module22
| Module name=module2.module22.main
| Module name=module2.module22.test
| Module name=module2.module22.main
| Module name=module2.module22.test
|
""".trimMargin())
}

View File

@@ -24,8 +24,8 @@ internal class ModuleGroupsTree private constructor(private val grouper: ModuleG
val groupPath = grouper.getGroupPath(module)
if (groupPath.isNotEmpty()) {
val group = ModuleGroup(groupPath)
val moduleNamePrefixLen = (1 .. groupPath.size).firstOrNull { groupPath.subList(0, it) in moduleAsGroupPaths }
val parentGroupForModule = if (moduleNamePrefixLen != null && moduleNamePrefixLen > 1) {
val moduleNamePrefixLen = (2 .. groupPath.size).firstOrNull { groupPath.subList(0, it) in moduleAsGroupPaths }
val parentGroupForModule = if (moduleNamePrefixLen != null) {
//if there are modules with names 'a.foo' and 'a.foo.bar.baz' the both should be shown as children of module group 'a' to avoid
// nodes with same text in the tree
ModuleGroup(groupPath.subList(0, moduleNamePrefixLen - 1))