mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-22 06:20:54 +07:00
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
327 lines
11 KiB
Kotlin
327 lines
11 KiB
Kotlin
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
|
package com.intellij.projectView
|
|
|
|
import com.intellij.ide.highlighter.ModuleFileType
|
|
import com.intellij.ide.projectView.impl.PackageViewPane
|
|
import com.intellij.openapi.application.WriteAction
|
|
import com.intellij.openapi.module.Module
|
|
import com.intellij.openapi.module.ModuleManager
|
|
import com.intellij.openapi.ui.Queryable
|
|
import com.intellij.platform.ide.progress.runWithModalProgressBlocking
|
|
import com.intellij.project.stateStore
|
|
import com.intellij.testFramework.PsiTestUtil
|
|
import com.intellij.util.io.directoryContent
|
|
import com.intellij.util.io.generateInVirtualTempDir
|
|
|
|
abstract class ModulesInProjectViewTestCase : BaseProjectViewTestCase() {
|
|
init {
|
|
myPrintInfo = Queryable.PrintInfo()
|
|
}
|
|
|
|
override fun setUp() {
|
|
super.setUp()
|
|
myStructure.isShowLibraryContents = false
|
|
}
|
|
|
|
override fun doCreateRealModule(moduleName: String): Module {
|
|
return WriteAction.computeAndWait<Module, RuntimeException> {
|
|
/* iml files are created under .idea directory to ensure that they won't affect expected structure of Project View;
|
|
this is needed to ensure that tests work the same way under the old project model and under workspace model where all modules
|
|
are saved when a single module is unloaded */
|
|
val imlPath = project.stateStore.projectBasePath.resolve(".idea/$moduleName${ModuleFileType.DOT_DEFAULT_EXTENSION}")
|
|
ModuleManager.getInstance(myProject).newModule(imlPath, moduleType.id)
|
|
}
|
|
}
|
|
|
|
override fun getTestPath(): String? = null
|
|
}
|
|
|
|
// directory-based project must be used to ensure that .iws/.ipr file won't break the test (they may be created if workspace model is used)
|
|
class ModulesInProjectViewTest : ModulesInProjectViewTestCase() {
|
|
fun `test unloaded modules`() {
|
|
val root = directoryContent {
|
|
dir("loaded") {
|
|
dir("unloaded-inner") {
|
|
dir("subdir") { }
|
|
file("y.txt")
|
|
}
|
|
}
|
|
dir("unloaded") {
|
|
dir("loaded-inner") {
|
|
dir("subdir") { }
|
|
file("z.txt")
|
|
}
|
|
}
|
|
}.generateInVirtualTempDir()
|
|
PsiTestUtil.addContentRoot(createModule("loaded"), root.findChild("loaded")!!)
|
|
PsiTestUtil.addContentRoot(createModule("unloaded-inner"), root.findFileByRelativePath("loaded/unloaded-inner")!!)
|
|
PsiTestUtil.addContentRoot(createModule("unloaded"), root.findChild("unloaded")!!)
|
|
PsiTestUtil.addContentRoot(createModule("loaded-inner"), root.findFileByRelativePath("unloaded/loaded-inner")!!)
|
|
val expected = """
|
|
Project
|
|
loaded
|
|
unloaded-inner
|
|
subdir
|
|
y.txt
|
|
unloaded
|
|
loaded-inner
|
|
subdir
|
|
z.txt
|
|
|
|
""".trimIndent()
|
|
assertStructureEqual(expected)
|
|
|
|
runWithModalProgressBlocking(myProject, "") {
|
|
ModuleManager.getInstance(myProject).setUnloadedModules(listOf("unloaded", "unloaded-inner"))
|
|
}
|
|
assertStructureEqual("""
|
|
Project
|
|
loaded
|
|
unloaded-inner
|
|
subdir
|
|
y.txt
|
|
unloaded
|
|
loaded-inner
|
|
subdir
|
|
z.txt
|
|
""".trimIndent())
|
|
}
|
|
|
|
fun `test unloaded module with qualified name`() {
|
|
val root = directoryContent {
|
|
dir("unloaded") {
|
|
dir("subdir") {}
|
|
file("y.txt")
|
|
}
|
|
dir("unloaded2") {
|
|
dir("subdir") {}
|
|
}
|
|
}.generateInVirtualTempDir()
|
|
PsiTestUtil.addContentRoot(createModule("foo.bar.unloaded"), root.findChild("unloaded")!!)
|
|
PsiTestUtil.addContentRoot(createModule("unloaded2"), root.findChild("unloaded2")!!)
|
|
|
|
val expected = """
|
|
Project
|
|
Group: foo.bar
|
|
unloaded
|
|
subdir
|
|
y.txt
|
|
unloaded2
|
|
subdir
|
|
""".trimIndent()
|
|
assertStructureEqual(expected)
|
|
|
|
runWithModalProgressBlocking(myProject, "") {
|
|
ModuleManager.getInstance(myProject).setUnloadedModules(listOf("unloaded"))
|
|
}
|
|
assertStructureEqual(expected)
|
|
}
|
|
|
|
fun `test do not show parent groups for single module`() {
|
|
val root = directoryContent {
|
|
dir("module") {
|
|
dir("subdir") {}
|
|
}
|
|
}.generateInVirtualTempDir()
|
|
PsiTestUtil.addContentRoot(createModule("foo.bar.module"), root.findChild("module")!!)
|
|
assertStructureEqual("""
|
|
|Project
|
|
| module
|
|
| subdir
|
|
|
|
|
""".trimMargin())
|
|
}
|
|
|
|
fun `test flatten modules option`() {
|
|
val root = directoryContent {
|
|
dir("module1") {}
|
|
dir("module2") {}
|
|
}.generateInVirtualTempDir()
|
|
PsiTestUtil.addContentRoot(createModule("foo.bar.module1"), root.findChild("module1")!!)
|
|
PsiTestUtil.addContentRoot(createModule("foo.bar.module2"), root.findChild("module2")!!)
|
|
myStructure.isFlattenModules = true
|
|
assertStructureEqual("""
|
|
|Project
|
|
| module1
|
|
| module2
|
|
|
|
|
""".trimMargin())
|
|
}
|
|
|
|
fun `test do not show groups duplicating module names`() {
|
|
val root = directoryContent {
|
|
dir("foo") {}
|
|
dir("foo.bar") {}
|
|
}.generateInVirtualTempDir()
|
|
PsiTestUtil.addContentRoot(createModule("xxx.foo"), root.findChild("foo")!!)
|
|
PsiTestUtil.addContentRoot(createModule("xxx.foo.bar"), root.findChild("foo.bar")!!)
|
|
assertStructureEqual("""
|
|
|Project
|
|
| Group: xxx
|
|
| foo
|
|
| foo.bar
|
|
|
|
|
""".trimMargin())
|
|
}
|
|
|
|
fun `test modules with common parent group`() {
|
|
val root = directoryContent {
|
|
dir("module1") {
|
|
dir("subdir") {}
|
|
}
|
|
dir("module2") {
|
|
dir("subdir") {}
|
|
}
|
|
}.generateInVirtualTempDir()
|
|
PsiTestUtil.addContentRoot(createModule("foo.bar.module1"), root.findChild("module1")!!)
|
|
PsiTestUtil.addContentRoot(createModule("foo.baz.module2"), root.findChild("module2")!!)
|
|
assertStructureEqual("""
|
|
|Project
|
|
| Group: foo
|
|
| Group: bar
|
|
| module1
|
|
| subdir
|
|
| Group: baz
|
|
| module2
|
|
| subdir
|
|
|
|
|
""".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") {
|
|
dir("subdir") {}
|
|
}
|
|
dir("module2") {
|
|
dir("subdir") {}
|
|
}
|
|
}.generateInVirtualTempDir()
|
|
PsiTestUtil.addContentRoot(createModule("foo.bar.module1"), root.findChild("module1")!!)
|
|
PsiTestUtil.addContentRoot(createModule("foo.module2"), root.findChild("module2")!!)
|
|
assertStructureEqual("""
|
|
|Project
|
|
| Group: foo
|
|
| Group: bar
|
|
| module1
|
|
| subdir
|
|
| module2
|
|
| subdir
|
|
|
|
|
""".trimMargin())
|
|
}
|
|
|
|
}
|
|
|
|
class ModulesInPackageViewTest : ModulesInProjectViewTestCase() {
|
|
|
|
init {
|
|
myPrintInfo = Queryable.PrintInfo(arrayOf("id"), arrayOf("name"))
|
|
}
|
|
|
|
override fun setUp() {
|
|
packageViewPaneId = PackageViewPane.ID
|
|
super.setUp()
|
|
}
|
|
|
|
fun `test nested modules`() {
|
|
val root = directoryContent {
|
|
dir("module1") {
|
|
dir("module11") {
|
|
dir("main") {
|
|
dir("src") {}
|
|
}
|
|
dir("test") {
|
|
dir("src") {}
|
|
}
|
|
}
|
|
dir("module12") {
|
|
dir("main") {
|
|
dir("src") {}
|
|
}
|
|
dir("test") {
|
|
dir("src") {}
|
|
}
|
|
}
|
|
}
|
|
dir("module2") {
|
|
dir("module22") {
|
|
dir("main") {
|
|
dir("src") {}
|
|
}
|
|
dir("test") {
|
|
dir("src") {}
|
|
}
|
|
}
|
|
}
|
|
}.generateInVirtualTempDir()
|
|
PsiTestUtil.addContentRoot(createModule("module1"), root.findFileByRelativePath("module1")!!)
|
|
PsiTestUtil.addContentRoot(createModule("module1.module11"), root.findFileByRelativePath("module1/module11")!!)
|
|
val module11main = createModule("module1.module11.main")
|
|
PsiTestUtil.addContentRoot(module11main, root.findFileByRelativePath("module1/module11/main")!!)
|
|
PsiTestUtil.addSourceContentToRoots(module11main, root.findFileByRelativePath("module1/module11/main/src")!!)
|
|
val module11test = createModule("module1.module11.test")
|
|
PsiTestUtil.addContentRoot(module11test, root.findFileByRelativePath("module1/module11/test")!!)
|
|
PsiTestUtil.addSourceContentToRoots(module11test, root.findFileByRelativePath("module1/module11/test/src")!!)
|
|
PsiTestUtil.addContentRoot(createModule("module1.module12"), root.findFileByRelativePath("module1/module12")!!)
|
|
val module12main = createModule("module1.module12.main")
|
|
PsiTestUtil.addContentRoot(module12main, root.findFileByRelativePath("module1/module12/main")!!)
|
|
PsiTestUtil.addSourceContentToRoots(module12main, root.findFileByRelativePath("module1/module12/main/src")!!)
|
|
val module12test = createModule("module1.module12.test")
|
|
PsiTestUtil.addContentRoot(module12test, root.findFileByRelativePath("module1/module12/test")!!)
|
|
PsiTestUtil.addSourceContentToRoots(module12test, root.findFileByRelativePath("module1/module12/test/src")!!)
|
|
PsiTestUtil.addContentRoot(createModule("module2"), root.findFileByRelativePath("module2")!!)
|
|
PsiTestUtil.addContentRoot(createModule("module2.module22"), root.findFileByRelativePath("module2/module22")!!)
|
|
val module22main = createModule("module2.module22.main")
|
|
PsiTestUtil.addContentRoot(module22main, root.findFileByRelativePath("module2/module22/main")!!)
|
|
PsiTestUtil.addSourceContentToRoots(module22main, root.findFileByRelativePath("module2/module22/main/src")!!)
|
|
val module22test = createModule("module2.module22.test")
|
|
PsiTestUtil.addContentRoot(module22test, root.findFileByRelativePath("module2/module22/test")!!)
|
|
PsiTestUtil.addSourceContentToRoots(module22test, root.findFileByRelativePath("module2/module22/test/src")!!)
|
|
assertStructureEqual("""
|
|
|Project
|
|
| Group: module1
|
|
| Module name=module1.module11
|
|
| Module name=module1.module11.main
|
|
| Module name=module1.module11.test
|
|
| Module name=module1.module12
|
|
| 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
|
|
|
|
|
""".trimMargin())
|
|
}
|
|
|
|
}
|