Split ModuleSourceInfo into ModuleProductionSourceInfo and ModuleTestSourceInfo
This commit is contained in:
@@ -16,7 +16,10 @@
|
|||||||
<item name='com.intellij.openapi.roots.OrderEnumerator com.intellij.openapi.roots.OrderEnumerator exportedOnly()'>
|
<item name='com.intellij.openapi.roots.OrderEnumerator com.intellij.openapi.roots.OrderEnumerator exportedOnly()'>
|
||||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||||
</item>
|
</item>
|
||||||
<item name='com.intellij.openapi.roots.OrderEnumerator com.intellij.openapi.roots.OrderEnumerator recursively()'>
|
<item name='com.intellij.openapi.roots.OrderEnumerator com.intellij.openapi.roots.OrderEnumerator productionOnly()'>
|
||||||
|
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||||
|
</item>
|
||||||
|
<item name='com.intellij.openapi.roots.OrderEnumerator com.intellij.openapi.roots.OrderEnumerator recursively()'>
|
||||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||||
</item>
|
</item>
|
||||||
<item
|
<item
|
||||||
|
|||||||
@@ -35,18 +35,21 @@ import com.intellij.openapi.module.impl.scopes.LibraryScopeBase
|
|||||||
import com.intellij.openapi.roots.OrderRootType
|
import com.intellij.openapi.roots.OrderRootType
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import org.jetbrains.jet.utils.emptyOrSingletonList
|
import org.jetbrains.jet.utils.emptyOrSingletonList
|
||||||
|
import com.intellij.openapi.roots.OrderEnumerator
|
||||||
|
|
||||||
private abstract class IdeaModuleInfo : ModuleInfo {
|
public abstract class IdeaModuleInfo : ModuleInfo {
|
||||||
abstract fun contentScope(): GlobalSearchScope
|
abstract fun contentScope(): GlobalSearchScope
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun orderEntryToModuleInfo(project: Project, orderEntry: OrderEntry): List<IdeaModuleInfo> {
|
private fun orderEntryToModuleInfo(project: Project, orderEntry: OrderEntry, productionOnly: Boolean): List<IdeaModuleInfo> {
|
||||||
|
fun Module.toInfos() = if (productionOnly) listOf(productionSourceInfo()) else listOf(testSourceInfo(), productionSourceInfo())
|
||||||
|
|
||||||
return when (orderEntry) {
|
return when (orderEntry) {
|
||||||
is ModuleSourceOrderEntry -> {
|
is ModuleSourceOrderEntry -> {
|
||||||
listOf(orderEntry.getOwnerModule().toSourceInfo())
|
orderEntry.getOwnerModule().toInfos()
|
||||||
}
|
}
|
||||||
is ModuleOrderEntry -> {
|
is ModuleOrderEntry -> {
|
||||||
emptyOrSingletonList(orderEntry.getModule()?.toSourceInfo())
|
orderEntry.getModule()?.toInfos().orEmpty()
|
||||||
}
|
}
|
||||||
is LibraryOrderEntry -> {
|
is LibraryOrderEntry -> {
|
||||||
val library = orderEntry.getLibrary() ?: return listOf()
|
val library = orderEntry.getLibrary() ?: return listOf()
|
||||||
@@ -62,27 +65,42 @@ private fun orderEntryToModuleInfo(project: Project, orderEntry: OrderEntry): Li
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: (module refactoring) there should be separate ModuleTestInfo
|
fun ideaModelDependencies(module: Module, productionOnly: Boolean): List<IdeaModuleInfo> {
|
||||||
private data class ModuleSourceInfo(val module: Module) : IdeaModuleInfo() {
|
//NOTE: lib dependencies can be processed several times during recursive traversal
|
||||||
override val name = Name.special("<sources for module ${module.getName()}>")
|
val result = LinkedHashSet<IdeaModuleInfo>()
|
||||||
|
val dependencyEnumerator = ModuleRootManager.getInstance(module).orderEntries().compileOnly().recursively().exportedOnly()
|
||||||
override fun contentScope() = GlobalSearchScope.moduleScope(module)
|
if (productionOnly) {
|
||||||
|
dependencyEnumerator.productionOnly()
|
||||||
override fun dependencies(): List<IdeaModuleInfo> {
|
|
||||||
//NOTE: lib dependencies can be processed several times during recursive traversal
|
|
||||||
val result = LinkedHashSet<IdeaModuleInfo>()
|
|
||||||
ModuleRootManager.getInstance(module).orderEntries().compileOnly().recursively().exportedOnly().forEach {
|
|
||||||
orderEntry ->
|
|
||||||
result.addAll(orderEntryToModuleInfo(module.getProject(), orderEntry!!))
|
|
||||||
true
|
|
||||||
}
|
|
||||||
return result.toList()
|
|
||||||
}
|
}
|
||||||
|
dependencyEnumerator.forEach {
|
||||||
|
orderEntry ->
|
||||||
|
result.addAll(orderEntryToModuleInfo(module.getProject(), orderEntry!!, productionOnly))
|
||||||
|
true
|
||||||
|
}
|
||||||
|
return result.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Module.toSourceInfo() = ModuleSourceInfo(this)
|
public data class ModuleProductionSourceInfo(val module: Module) : IdeaModuleInfo() {
|
||||||
|
override val name = Name.special("<production sources for module ${module.getName()}>")
|
||||||
|
|
||||||
private data class LibraryInfo(val project: Project, val library: Library) : IdeaModuleInfo() {
|
override fun contentScope() = module.getModuleScope(false)
|
||||||
|
|
||||||
|
override fun dependencies() = ideaModelDependencies(module, productionOnly = true)
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: (module refactoring) do not create ModuleTestSourceInfo when there are not test roots for module
|
||||||
|
public data class ModuleTestSourceInfo(val module: Module) : IdeaModuleInfo() {
|
||||||
|
override val name = Name.special("<test sources for module ${module.getName()}>")
|
||||||
|
|
||||||
|
override fun contentScope() = module.getModuleScope().intersectWith(GlobalSearchScope.notScope(module.getModuleScope(false)))
|
||||||
|
|
||||||
|
override fun dependencies() = ideaModelDependencies(module, productionOnly = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun Module.productionSourceInfo(): ModuleProductionSourceInfo = ModuleProductionSourceInfo(this)
|
||||||
|
public fun Module.testSourceInfo(): ModuleTestSourceInfo = ModuleTestSourceInfo(this)
|
||||||
|
|
||||||
|
public data class LibraryInfo(val project: Project, val library: Library) : IdeaModuleInfo() {
|
||||||
override val name: Name = Name.special("<library ${library.getName()}>")
|
override val name: Name = Name.special("<library ${library.getName()}>")
|
||||||
|
|
||||||
override fun contentScope() = LibraryWithoutSourceScope(project, library)
|
override fun contentScope() = LibraryWithoutSourceScope(project, library)
|
||||||
|
|||||||
+1
-1
@@ -83,7 +83,7 @@ fun createModuleResolverProvider(
|
|||||||
|
|
||||||
private fun collectAllModuleInfosFromIdeaModel(project: Project): List<IdeaModuleInfo> {
|
private fun collectAllModuleInfosFromIdeaModel(project: Project): List<IdeaModuleInfo> {
|
||||||
val ideaModules = ModuleManager.getInstance(project).getModules().toList()
|
val ideaModules = ModuleManager.getInstance(project).getModules().toList()
|
||||||
val modulesSourcesInfos = ideaModules.map { it.toSourceInfo() }
|
val modulesSourcesInfos = ideaModules.flatMap { listOf(it.productionSourceInfo(), it.testSourceInfo()) }
|
||||||
|
|
||||||
//TODO: (module refactoring) include libraries that are not among dependencies of any module
|
//TODO: (module refactoring) include libraries that are not among dependencies of any module
|
||||||
val ideaLibraries = ideaModules.flatMap {
|
val ideaLibraries = ideaModules.flatMap {
|
||||||
|
|||||||
@@ -65,7 +65,14 @@ private fun getModuleInfoByVirtualFile(project: Project, virtualFile: VirtualFil
|
|||||||
val projectFileIndex = ProjectFileIndex.SERVICE.getInstance(project)
|
val projectFileIndex = ProjectFileIndex.SERVICE.getInstance(project)
|
||||||
|
|
||||||
val module = projectFileIndex.getModuleForFile(virtualFile)
|
val module = projectFileIndex.getModuleForFile(virtualFile)
|
||||||
if (module != null) return module.toSourceInfo()
|
if (module != null) {
|
||||||
|
if (projectFileIndex.isInTestSourceContent(virtualFile)) {
|
||||||
|
return module.testSourceInfo()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return module.productionSourceInfo()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val orderEntries = projectFileIndex.getOrderEntriesForFile(virtualFile)
|
val orderEntries = projectFileIndex.getOrderEntriesForFile(virtualFile)
|
||||||
|
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ class IdeaModuleInfoTest : ModuleTestCase() {
|
|||||||
val (a, b) = modules()
|
val (a, b) = modules()
|
||||||
b.addDependency(a)
|
b.addDependency(a)
|
||||||
|
|
||||||
b.source.assertDependenciesEqual(b.source, a.source)
|
b.production.assertDependenciesEqual(b.production, a.production)
|
||||||
assertDoesntContain(a.source.dependencies(), b.source)
|
assertDoesntContain(a.production.dependencies(), b.production)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testCircularDependency() {
|
fun testCircularDependency() {
|
||||||
@@ -42,8 +42,8 @@ class IdeaModuleInfoTest : ModuleTestCase() {
|
|||||||
b.addDependency(a)
|
b.addDependency(a)
|
||||||
a.addDependency(b)
|
a.addDependency(b)
|
||||||
|
|
||||||
a.source.assertDependenciesEqual(a.source, b.source)
|
a.production.assertDependenciesEqual(a.production, b.production)
|
||||||
b.source.assertDependenciesEqual(b.source, a.source)
|
b.production.assertDependenciesEqual(b.production, a.production)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testExportedDependency() {
|
fun testExportedDependency() {
|
||||||
@@ -52,9 +52,9 @@ class IdeaModuleInfoTest : ModuleTestCase() {
|
|||||||
b.addDependency(a, exported = true)
|
b.addDependency(a, exported = true)
|
||||||
c.addDependency(b)
|
c.addDependency(b)
|
||||||
|
|
||||||
a.source.assertDependenciesEqual(a.source)
|
a.production.assertDependenciesEqual(a.production)
|
||||||
b.source.assertDependenciesEqual(b.source, a.source)
|
b.production.assertDependenciesEqual(b.production, a.production)
|
||||||
c.source.assertDependenciesEqual(c.source, b.source, a.source)
|
c.production.assertDependenciesEqual(c.production, b.production, a.production)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testRedundantExportedDependency() {
|
fun testRedundantExportedDependency() {
|
||||||
@@ -64,9 +64,9 @@ class IdeaModuleInfoTest : ModuleTestCase() {
|
|||||||
c.addDependency(a)
|
c.addDependency(a)
|
||||||
c.addDependency(b)
|
c.addDependency(b)
|
||||||
|
|
||||||
a.source.assertDependenciesEqual(a.source)
|
a.production.assertDependenciesEqual(a.production)
|
||||||
b.source.assertDependenciesEqual(b.source, a.source)
|
b.production.assertDependenciesEqual(b.production, a.production)
|
||||||
c.source.assertDependenciesEqual(c.source, a.source, b.source)
|
c.production.assertDependenciesEqual(c.production, a.production, b.production)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testCircularExportedDependency() {
|
fun testCircularExportedDependency() {
|
||||||
@@ -76,9 +76,9 @@ class IdeaModuleInfoTest : ModuleTestCase() {
|
|||||||
c.addDependency(b, exported = true)
|
c.addDependency(b, exported = true)
|
||||||
a.addDependency(c, exported = true)
|
a.addDependency(c, exported = true)
|
||||||
|
|
||||||
a.source.assertDependenciesEqual(a.source, c.source, b.source)
|
a.production.assertDependenciesEqual(a.production, c.production, b.production)
|
||||||
b.source.assertDependenciesEqual(b.source, a.source, c.source)
|
b.production.assertDependenciesEqual(b.production, a.production, c.production)
|
||||||
c.source.assertDependenciesEqual(c.source, b.source, a.source)
|
c.production.assertDependenciesEqual(c.production, b.production, a.production)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testSimpleLibDependency() {
|
fun testSimpleLibDependency() {
|
||||||
@@ -86,7 +86,7 @@ class IdeaModuleInfoTest : ModuleTestCase() {
|
|||||||
val lib = projectLibrary()
|
val lib = projectLibrary()
|
||||||
a.addDependency(lib)
|
a.addDependency(lib)
|
||||||
|
|
||||||
a.source.assertDependenciesEqual(a.source, lib.classes)
|
a.production.assertDependenciesEqual(a.production, lib.classes)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testCircularExportedDependencyWithLib() {
|
fun testCircularExportedDependencyWithLib() {
|
||||||
@@ -103,9 +103,9 @@ class IdeaModuleInfoTest : ModuleTestCase() {
|
|||||||
b.addDependency(lib)
|
b.addDependency(lib)
|
||||||
c.addDependency(lib)
|
c.addDependency(lib)
|
||||||
|
|
||||||
a.source.assertDependenciesEqual(a.source, lib.classes, c.source, b.source)
|
a.production.assertDependenciesEqual(a.production, lib.classes, c.production, b.production)
|
||||||
b.source.assertDependenciesEqual(b.source, a.source, c.source, lib.classes)
|
b.production.assertDependenciesEqual(b.production, a.production, c.production, lib.classes)
|
||||||
c.source.assertDependenciesEqual(c.source, b.source, a.source, lib.classes)
|
c.production.assertDependenciesEqual(c.production, b.production, a.production, lib.classes)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testSeveralModulesExportLibs() {
|
fun testSeveralModulesExportLibs() {
|
||||||
@@ -119,7 +119,7 @@ class IdeaModuleInfoTest : ModuleTestCase() {
|
|||||||
c.addDependency(a)
|
c.addDependency(a)
|
||||||
c.addDependency(b)
|
c.addDependency(b)
|
||||||
|
|
||||||
c.source.assertDependenciesEqual(c.source, a.source, lib1.classes, b.source, lib2.classes)
|
c.production.assertDependenciesEqual(c.production, a.production, lib1.classes, b.production, lib2.classes)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testSeveralModulesExportSameLib() {
|
fun testSeveralModulesExportSameLib() {
|
||||||
@@ -132,7 +132,7 @@ class IdeaModuleInfoTest : ModuleTestCase() {
|
|||||||
c.addDependency(a)
|
c.addDependency(a)
|
||||||
c.addDependency(b)
|
c.addDependency(b)
|
||||||
|
|
||||||
c.source.assertDependenciesEqual(c.source, a.source, lib.classes, b.source)
|
c.production.assertDependenciesEqual(c.production, a.production, lib.classes, b.production)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testRuntimeDependency() {
|
fun testRuntimeDependency() {
|
||||||
@@ -141,7 +141,7 @@ class IdeaModuleInfoTest : ModuleTestCase() {
|
|||||||
b.addDependency(a, dependencyScope = DependencyScope.RUNTIME)
|
b.addDependency(a, dependencyScope = DependencyScope.RUNTIME)
|
||||||
b.addDependency(projectLibrary(), dependencyScope = DependencyScope.RUNTIME)
|
b.addDependency(projectLibrary(), dependencyScope = DependencyScope.RUNTIME)
|
||||||
|
|
||||||
b.source.assertDependenciesEqual(b.source)
|
b.production.assertDependenciesEqual(b.production)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testProvidedDependency() {
|
fun testProvidedDependency() {
|
||||||
@@ -151,7 +151,35 @@ class IdeaModuleInfoTest : ModuleTestCase() {
|
|||||||
b.addDependency(a, dependencyScope = DependencyScope.PROVIDED)
|
b.addDependency(a, dependencyScope = DependencyScope.PROVIDED)
|
||||||
b.addDependency(lib, dependencyScope = DependencyScope.PROVIDED)
|
b.addDependency(lib, dependencyScope = DependencyScope.PROVIDED)
|
||||||
|
|
||||||
b.source.assertDependenciesEqual(b.source, a.source, lib.classes)
|
b.production.assertDependenciesEqual(b.production, a.production, lib.classes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testSimpleTestDependency() {
|
||||||
|
val (a, b) = modules()
|
||||||
|
b.addDependency(a, dependencyScope = DependencyScope.TEST)
|
||||||
|
|
||||||
|
a.production.assertDependenciesEqual(a.production)
|
||||||
|
a.test.assertDependenciesEqual(a.test, a.production)
|
||||||
|
b.production.assertDependenciesEqual(b.production)
|
||||||
|
b.test.assertDependenciesEqual(b.test, b.production, a.test, a.production)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testLibTestDependency() {
|
||||||
|
val a = module("a")
|
||||||
|
val lib = projectLibrary()
|
||||||
|
a.addDependency(lib, dependencyScope = DependencyScope.TEST)
|
||||||
|
|
||||||
|
a.production.assertDependenciesEqual(a.production)
|
||||||
|
a.test.assertDependenciesEqual(a.test, a.production, lib.classes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testExportedTestDependency() {
|
||||||
|
val (a, b, c) = modules()
|
||||||
|
b.addDependency(a, exported = true)
|
||||||
|
c.addDependency(b, dependencyScope = DependencyScope.TEST)
|
||||||
|
|
||||||
|
c.production.assertDependenciesEqual(c.production)
|
||||||
|
c.test.assertDependenciesEqual(c.test, c.production, b.test, b.production, a.test, a.production)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Module.addDependency(
|
private fun Module.addDependency(
|
||||||
@@ -160,8 +188,12 @@ class IdeaModuleInfoTest : ModuleTestCase() {
|
|||||||
exported: Boolean = false
|
exported: Boolean = false
|
||||||
) = ModuleRootModificationUtil.addDependency(this, other, dependencyScope, exported)
|
) = ModuleRootModificationUtil.addDependency(this, other, dependencyScope, exported)
|
||||||
|
|
||||||
private val Module.source: ModuleProductionSourceInfo
|
private val Module.production: ModuleProductionSourceInfo
|
||||||
get() = productionSourceInfo()
|
get() = productionSourceInfo()
|
||||||
|
|
||||||
|
private val Module.test: ModuleTestSourceInfo
|
||||||
|
get() = testSourceInfo()
|
||||||
|
|
||||||
private val Library.classes: LibraryInfo
|
private val Library.classes: LibraryInfo
|
||||||
get() = LibraryInfo(getProject()!!, this)
|
get() = LibraryInfo(getProject()!!, this)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user