From 9f7d7e55daa67fcff5d3a32f5381ad00a0389c82 Mon Sep 17 00:00:00 2001 From: Pavel Kirpichenkov Date: Wed, 3 Feb 2021 17:54:40 +0300 Subject: [PATCH] Consider platform compatibility in library usage index Logic of module dependencies is enhanced to filter out incompatible common -> platform dependencies. However the reversed index for getting all modules that use libraries doesn't take this filtering into account and returns all modules based exclusively on order entries. This leads to incorrect library dependency calculation. ^KT-44638 Verification pending --- .../kotlin/idea/caches/project/IdeaModuleInfos.kt | 2 +- .../caches/project/LibraryDependenciesCache.kt | 15 +++++++++++++-- .../platformDependencyInCommon/common/common.kt | 6 ++++++ .../platformDependencyInCommon/dependencies.txt | 10 ++++++++++ .../platformDependencyInCommon/js/js.kt | 6 ++++++ .../platformDependencyInCommon/jvm/jvm.kt | 6 ++++++ .../idea/caches/resolve/IdeaModuleInfoTest.kt | 11 +++++++++++ .../MultiplatformAnalysisTestGenerated.java | 5 +++++ 8 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 idea/testData/multiplatform/platformDependencyInCommon/common/common.kt create mode 100644 idea/testData/multiplatform/platformDependencyInCommon/dependencies.txt create mode 100644 idea/testData/multiplatform/platformDependencyInCommon/js/js.kt create mode 100644 idea/testData/multiplatform/platformDependencyInCommon/jvm/jvm.kt diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/IdeaModuleInfos.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/IdeaModuleInfos.kt index 0d15a2642ab..7ca053f60b5 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/IdeaModuleInfos.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/IdeaModuleInfos.kt @@ -173,7 +173,7 @@ private fun ideaModelDependencies( return correctedResult } -private fun TargetPlatform.canDependOn(other: IdeaModuleInfo, isHmppEnabled: Boolean): Boolean { +internal fun TargetPlatform.canDependOn(other: IdeaModuleInfo, isHmppEnabled: Boolean): Boolean { if (isHmppEnabled) { // HACK: allow depending on stdlib even if platforms do not match if (isNative() && other is AbstractKlibLibraryInfo && other.libraryRoot.endsWith(KONAN_STDLIB_NAME)) return true diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/LibraryDependenciesCache.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/LibraryDependenciesCache.kt index c12a7514054..8ce53fdfddf 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/LibraryDependenciesCache.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/LibraryDependenciesCache.kt @@ -19,6 +19,7 @@ import com.intellij.util.containers.ContainerUtil import com.intellij.util.containers.MultiMap import org.jetbrains.kotlin.idea.core.util.CachedValue import org.jetbrains.kotlin.idea.core.util.getValue +import org.jetbrains.kotlin.idea.project.isHMPPEnabled import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.platform.isCommon import java.util.* @@ -62,7 +63,7 @@ class LibraryDependenciesCacheImpl(private val project: Project) : LibraryDepend val platform = libraryInfo.platform - for (module in getLibraryUsageIndex().modulesLibraryIsUsedIn[libraryInfo.library]) { + for (module in getLibraryUsageIndex().getModulesLibraryIsUsedIn(libraryInfo)) { if (!processedModules.add(module)) continue ModuleRootManager.getInstance(module).orderEntries().recursively().satisfying(condition).process(object : RootPolicy() { @@ -109,7 +110,7 @@ class LibraryDependenciesCacheImpl(private val project: Project) : LibraryDepend } private inner class LibraryUsageIndex { - val modulesLibraryIsUsedIn: MultiMap = MultiMap.createSet() + private val modulesLibraryIsUsedIn: MultiMap = MultiMap.createSet() init { for (module in ModuleManager.getInstance(project).modules) { @@ -123,5 +124,15 @@ class LibraryDependenciesCacheImpl(private val project: Project) : LibraryDepend } } } + + fun getModulesLibraryIsUsedIn(libraryInfo: LibraryInfo) = sequence { + val ideaModelInfosCache = getIdeaModelInfosCache(project) + for (module in modulesLibraryIsUsedIn[libraryInfo.library]) { + val mappedModuleInfos = ideaModelInfosCache.getModuleInfosForModule(module) + if (mappedModuleInfos.any { it.platform.canDependOn(libraryInfo, module.isHMPPEnabled) }) { + yield(module) + } + } + } } } diff --git a/idea/testData/multiplatform/platformDependencyInCommon/common/common.kt b/idea/testData/multiplatform/platformDependencyInCommon/common/common.kt new file mode 100644 index 00000000000..0f9a358d089 --- /dev/null +++ b/idea/testData/multiplatform/platformDependencyInCommon/common/common.kt @@ -0,0 +1,6 @@ +fun checkCloneableIsAbsent(array: Array) { + array.clone() +} + +@Metadata +class MetaUnresolved diff --git a/idea/testData/multiplatform/platformDependencyInCommon/dependencies.txt b/idea/testData/multiplatform/platformDependencyInCommon/dependencies.txt new file mode 100644 index 00000000000..1051b81e248 --- /dev/null +++ b/idea/testData/multiplatform/platformDependencyInCommon/dependencies.txt @@ -0,0 +1,10 @@ +// See KT-44638 + +MODULE jvm { platform=[JVM] } +MODULE js { platform=[JS] } +MODULE common { platform=[JVM, JS] } + +jvm -> STDLIB_JVM, MOCK_JDK { kind=DEPENDENCY } +js -> STDLIB_JS { kind=DEPENDENCY } +common -> STDLIB_COMMON, STDLIB_JVM { kind=DEPENDENCY } +jvm -> common { kind=DEPENDS_ON } diff --git a/idea/testData/multiplatform/platformDependencyInCommon/js/js.kt b/idea/testData/multiplatform/platformDependencyInCommon/js/js.kt new file mode 100644 index 00000000000..0f9a358d089 --- /dev/null +++ b/idea/testData/multiplatform/platformDependencyInCommon/js/js.kt @@ -0,0 +1,6 @@ +fun checkCloneableIsAbsent(array: Array) { + array.clone() +} + +@Metadata +class MetaUnresolved diff --git a/idea/testData/multiplatform/platformDependencyInCommon/jvm/jvm.kt b/idea/testData/multiplatform/platformDependencyInCommon/jvm/jvm.kt new file mode 100644 index 00000000000..9b401605271 --- /dev/null +++ b/idea/testData/multiplatform/platformDependencyInCommon/jvm/jvm.kt @@ -0,0 +1,6 @@ +fun checkCloneable(array: Array) { + array.clone() +} + +@Metadata +class MetaWithError diff --git a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/IdeaModuleInfoTest.kt b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/IdeaModuleInfoTest.kt index 0bf97db23ff..548f2d81074 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/IdeaModuleInfoTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/IdeaModuleInfoTest.kt @@ -26,10 +26,12 @@ import org.jetbrains.kotlin.idea.caches.project.ModuleTestSourceInfo import org.jetbrains.kotlin.idea.framework.CommonLibraryKind import org.jetbrains.kotlin.idea.framework.JSLibraryKind import org.jetbrains.kotlin.idea.framework.platform +import org.jetbrains.kotlin.idea.stubs.createMultiplatformFacetM3 import org.jetbrains.kotlin.idea.test.PluginTestCaseBase.* import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.idea.util.getProjectJdkTableSafe import org.jetbrains.kotlin.platform.TargetPlatform +import org.jetbrains.kotlin.platform.js.JsPlatforms import org.jetbrains.kotlin.test.JUnit3WithIdeaConfigurationRunner import org.jetbrains.kotlin.test.util.KtTestUtil import org.jetbrains.kotlin.test.util.addDependency @@ -316,6 +318,7 @@ class IdeaModuleInfoTest : ModuleTestCase() { a.addDependency(stdlibJvm) val b = module("b") + b.setUpPlatform(JsPlatforms.defaultJsPlatform) b.addDependency(stdlibCommon) b.addDependency(stdlibJs) @@ -480,6 +483,14 @@ class IdeaModuleInfoTest : ModuleTestCase() { kind = JSLibraryKind ) + private fun Module.setUpPlatform(targetPlatform: TargetPlatform) { + createMultiplatformFacetM3( + platformKind = targetPlatform, + dependsOnModuleNames = listOf(), + pureKotlinSourceFolders = listOf(), + ) + } + override fun setUp() { super.setUp() diff --git a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/MultiplatformAnalysisTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/MultiplatformAnalysisTestGenerated.java index 959cb5cc3ce..a0d86c053ff 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/MultiplatformAnalysisTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/MultiplatformAnalysisTestGenerated.java @@ -199,6 +199,11 @@ public class MultiplatformAnalysisTestGenerated extends AbstractMultiplatformAna runTest("idea/testData/multiplatform/overrideExpectWithCompositeType/"); } + @TestMetadata("platformDependencyInCommon") + public void testPlatformDependencyInCommon() throws Exception { + runTest("idea/testData/multiplatform/platformDependencyInCommon/"); + } + @TestMetadata("platformSpecificChecksInCommon") public void testPlatformSpecificChecksInCommon() throws Exception { runTest("idea/testData/multiplatform/platformSpecificChecksInCommon/");