diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/multiplatformUtil.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/multiplatformUtil.kt index 0a26110ca2d..4f6bbfb738e 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/multiplatformUtil.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/multiplatformUtil.kt @@ -96,7 +96,7 @@ val ModuleDescriptor.implementingDescriptors: List return implementingModuleInfos.mapNotNull { it.toDescriptor() } } -private fun Module.toInfo(type: SourceType): ModuleSourceInfo? = when (type) { +fun Module.toInfo(type: SourceType): ModuleSourceInfo? = when (type) { PRODUCTION -> productionSourceInfo() TEST -> testSourceInfo() } @@ -115,7 +115,7 @@ val ModuleDescriptor.implementedDescriptors: List return moduleSourceInfo.expectedBy.mapNotNull { it.toDescriptor() } } -private fun ModuleSourceInfo.toDescriptor() = KotlinCacheService.getInstance(module.project) +fun ModuleSourceInfo.toDescriptor() = KotlinCacheService.getInstance(module.project) .getResolutionFacadeByModuleInfo(this, platform)?.moduleDescriptor fun PsiElement.getPlatformModuleInfo(desiredPlatform: TargetPlatform): PlatformModuleInfo? { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/IdeaModuleStructureOracle.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/IdeaModuleStructureOracle.kt index d1495657a70..8b1a440f28f 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/IdeaModuleStructureOracle.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/IdeaModuleStructureOracle.kt @@ -5,9 +5,12 @@ package org.jetbrains.kotlin.idea.project +import com.intellij.openapi.module.Module +import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.idea.caches.project.implementedDescriptors -import org.jetbrains.kotlin.idea.caches.project.implementingDescriptors +import org.jetbrains.kotlin.idea.caches.project.* +import org.jetbrains.kotlin.idea.caches.project.sourceType +import org.jetbrains.kotlin.idea.core.unwrapModuleSourceInfo import org.jetbrains.kotlin.resolve.ModulePath import org.jetbrains.kotlin.resolve.ModuleStructureOracle import java.util.* @@ -18,31 +21,53 @@ class IdeaModuleStructureOracle : ModuleStructureOracle { } override fun findAllReversedDependsOnPaths(module: ModuleDescriptor): List { - val currentPath: Stack = Stack() + val currentPath: Stack = Stack() - return sequence { - yieldPathsFromSubgraph(module, currentPath, getChilds = { it.implementingDescriptors }) + return sequence { + val root = module.moduleInfo + if (root != null) { + yieldPathsFromSubgraph( + root, + currentPath, + getChilds = { + with(DependsOnGraphHelper) { it.unwrapModuleSourceInfo()?.predecessorsInDependsOnGraph() ?: emptyList() } + } + ) + } + }.map { + it.toModulePath() }.toList() } override fun findAllDependsOnPaths(module: ModuleDescriptor): List { - val currentPath: Stack = Stack() + val currentPath: Stack = Stack() - return sequence { - yieldPathsFromSubgraph(module, currentPath, getChilds = { it.implementedDescriptors }) + return sequence { + val root = module.moduleInfo + if (root != null) { + yieldPathsFromSubgraph( + root, + currentPath, + getChilds = { + with(DependsOnGraphHelper) { it.unwrapModuleSourceInfo()?.successorsInDependsOnGraph() ?: emptyList() } + } + ) + } + }.map { + it.toModulePath() }.toList() } - private suspend fun SequenceScope.yieldPathsFromSubgraph( - root: ModuleDescriptor, - currentPath: Stack, - getChilds: (ModuleDescriptor) -> List + private suspend fun SequenceScope.yieldPathsFromSubgraph( + root: ModuleInfo, + currentPath: Stack, + getChilds: (ModuleInfo) -> List ) { currentPath.push(root) val childs = getChilds(root) if (childs.isEmpty()) { - yield(ModulePath(currentPath.toList())) + yield(ModuleInfoPath(currentPath.toList())) } else { childs.forEach { yieldPathsFromSubgraph(it, currentPath, getChilds) @@ -51,4 +76,47 @@ class IdeaModuleStructureOracle : ModuleStructureOracle { currentPath.pop() } -} \ No newline at end of file + + private class ModuleInfoPath(val nodes: List) + + private fun ModuleInfoPath.toModulePath(): ModulePath = + ModulePath(nodes.mapNotNull { it.unwrapModuleSourceInfo()?.toDescriptor() }) +} + +object DependsOnGraphHelper { + fun ModuleDescriptor.predecessorsInDependsOnGraph(): List { + return moduleSourceInfo + ?.predecessorsInDependsOnGraph() + ?.mapNotNull { it.toDescriptor() } + ?: emptyList() + } + + fun ModuleSourceInfo.predecessorsInDependsOnGraph(): List { + return this.module.predecessorsInDependsOnGraph().mapNotNull { it.toInfo(sourceType) } + } + + fun Module.predecessorsInDependsOnGraph(): List { + return implementingModules + } + + fun ModuleDescriptor.successorsInDependsOnGraph(): List { + return moduleSourceInfo + ?.successorsInDependsOnGraph() + ?.mapNotNull { it.toDescriptor() } + ?: emptyList() + } + + fun ModuleSourceInfo.successorsInDependsOnGraph(): List { + return module.successorsInDependsOnGraph().mapNotNull { it.toInfo(sourceType) } + } + + fun Module.successorsInDependsOnGraph(): List { + return implementedModules + } +} + +private val ModuleDescriptor.moduleInfo: ModuleInfo? + get() = getCapability(ModuleInfo.Capability)?.unwrapModuleSourceInfo() + +private val ModuleDescriptor.moduleSourceInfo: ModuleSourceInfo? + get() = moduleInfo as? ModuleSourceInfo \ No newline at end of file diff --git a/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/diamondDuplicateActuals/bottom/bottom.kt b/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/diamondDuplicateActuals/bottom/bottom.kt index 51e1f53ea3a..668cc774835 100644 --- a/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/diamondDuplicateActuals/bottom/bottom.kt +++ b/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/diamondDuplicateActuals/bottom/bottom.kt @@ -1,6 +1,6 @@ package sample -actual class A { +actual class A { actual fun foo(): Int = 45 fun fromBottom(): Int = 0 } @@ -11,6 +11,6 @@ fun main() { // Any behaviour is acceptable, as the code is erroneous. // At the time of writing this test, we resolve to nearest A, i.e. // 'fromBottom' is resolved, and 'fromLeft' is not. - A().fromLeft() - A().fromBottom() + A().fromLeft() + A().fromBottom() } \ No newline at end of file diff --git a/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/diamondDuplicateActuals/top/top.kt b/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/diamondDuplicateActuals/top/top.kt index 73b99064d04..f4efb6f71fb 100644 --- a/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/diamondDuplicateActuals/top/top.kt +++ b/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/diamondDuplicateActuals/top/top.kt @@ -1,5 +1,5 @@ package sample -expect class A { - fun foo(): Int +expect class A { + fun foo(): Int } \ No newline at end of file diff --git a/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/diamondSeesTwoActuals/top/top.kt b/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/diamondSeesTwoActuals/top/top.kt index a359748ada8..c3c51289f62 100644 --- a/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/diamondSeesTwoActuals/top/top.kt +++ b/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/diamondSeesTwoActuals/top/top.kt @@ -1,5 +1,5 @@ package sample -expect class A { - fun foo(): Int +expect class A { + fun foo(): Int } \ No newline at end of file diff --git a/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateActualsExplicit/bottom/bottom.kt b/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateActualsExplicit/bottom/bottom.kt index 678301c2c64..28c702441a3 100644 --- a/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateActualsExplicit/bottom/bottom.kt +++ b/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateActualsExplicit/bottom/bottom.kt @@ -1,3 +1,3 @@ package foo -actual class A +actual class A diff --git a/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateActualsExplicit/top/top.kt b/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateActualsExplicit/top/top.kt index f38997819fd..84366910dfb 100644 --- a/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateActualsExplicit/top/top.kt +++ b/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateActualsExplicit/top/top.kt @@ -1,3 +1,3 @@ package foo -expect class A \ No newline at end of file +expect class A \ No newline at end of file diff --git a/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateActualsImplicit/bottom/bottom.kt b/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateActualsImplicit/bottom/bottom.kt index e67a624a9a4..f446f5fd76b 100644 --- a/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateActualsImplicit/bottom/bottom.kt +++ b/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateActualsImplicit/bottom/bottom.kt @@ -1,6 +1,6 @@ package foo -class ActualInMiddleCompatibleInBottom -actual class CompatibleInMiddleActualInBottom +class ActualInMiddleCompatibleInBottom +actual class CompatibleInMiddleActualInBottom -class CompatibleInMiddleAndBottom +class CompatibleInMiddleAndBottom diff --git a/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateActualsImplicit/top/top.kt b/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateActualsImplicit/top/top.kt index 986d4c60a35..f181e7bdbfa 100644 --- a/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateActualsImplicit/top/top.kt +++ b/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateActualsImplicit/top/top.kt @@ -1,6 +1,6 @@ package foo -expect class ActualInMiddleCompatibleInBottom -expect class CompatibleInMiddleActualInBottom +expect class ActualInMiddleCompatibleInBottom +expect class CompatibleInMiddleActualInBottom -expect class CompatibleInMiddleAndBottom \ No newline at end of file +expect class CompatibleInMiddleAndBottom \ No newline at end of file diff --git a/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateActualsOneWeaklyIncompatible/bottom/bottom.kt b/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateActualsOneWeaklyIncompatible/bottom/bottom.kt index d6d3776a3d4..b3de2e61b79 100644 --- a/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateActualsOneWeaklyIncompatible/bottom/bottom.kt +++ b/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateActualsOneWeaklyIncompatible/bottom/bottom.kt @@ -1,3 +1,3 @@ package foo -private class A \ No newline at end of file +private class A \ No newline at end of file diff --git a/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateActualsOneWeaklyIncompatible/top/top.kt b/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateActualsOneWeaklyIncompatible/top/top.kt index 4daacb52744..84366910dfb 100644 --- a/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateActualsOneWeaklyIncompatible/top/top.kt +++ b/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateActualsOneWeaklyIncompatible/top/top.kt @@ -1,3 +1,3 @@ package foo -expect class A \ No newline at end of file +expect class A \ No newline at end of file diff --git a/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateExpectsExplicit/bottom/bottom.kt b/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateExpectsExplicit/bottom/bottom.kt index 52b8666f932..0f462fb0178 100644 --- a/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateExpectsExplicit/bottom/bottom.kt +++ b/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateExpectsExplicit/bottom/bottom.kt @@ -1 +1 @@ -actual class A \ No newline at end of file +actual class A \ No newline at end of file diff --git a/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateExpectsImplicit/bottom/bottom.kt b/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateExpectsImplicit/bottom/bottom.kt index 72e8e852980..97858c1e487 100644 --- a/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateExpectsImplicit/bottom/bottom.kt +++ b/idea/testData/multiModuleHighlighting/hierarchicalExpectActualMatching/duplicateExpectsImplicit/bottom/bottom.kt @@ -1,3 +1,3 @@ // Note that here we have no ambiguity, becuase we don't consider // declarations without 'expect' as potential weakly-compatible 'expect'-counterpart -actual class A \ No newline at end of file +actual class A \ No newline at end of file