diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/TopDownAnalyzerFacadeForJVM.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/TopDownAnalyzerFacadeForJVM.kt index 684b5d7907c..a8421b4a9e5 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/TopDownAnalyzerFacadeForJVM.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/TopDownAnalyzerFacadeForJVM.kt @@ -227,10 +227,10 @@ object TopDownAnalyzerFacadeForJVM { } // TODO: remove dependencyModule from friends - module.setDependencies(ModuleDependenciesImpl( + module.setDependencies( listOfNotNull(module, dependencyModule, optionalBuiltInsModule), if (dependencyModule != null) setOf(dependencyModule) else emptySet() - )) + ) module.initialize(CompositePackageFragmentProvider( listOf(container.get().packageFragmentProvider) + additionalProviders diff --git a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt index 82178086c8b..3ef7d72b057 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt @@ -44,6 +44,7 @@ import org.jetbrains.kotlin.resolve.MultiTargetPlatform import org.jetbrains.kotlin.resolve.TargetEnvironment import org.jetbrains.kotlin.resolve.TargetPlatform import org.jetbrains.kotlin.storage.StorageManager +import org.jetbrains.kotlin.storage.getValue import java.util.* import kotlin.coroutines.experimental.buildSequence @@ -307,6 +308,10 @@ class LazyModuleDependencies( override val allDependencies: List get() = dependencies() + override val expectedByDependency by storageManager.createNullableLazyValue { + module.expectedBy?.let { resolverForProject.descriptorForModule(it as M) } + } + override val modulesWhoseInternalsAreVisible: Set get() = module.modulesWhoseInternalsAreVisible().mapTo(LinkedHashSet()) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExpectedActualDeclarationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExpectedActualDeclarationChecker.kt index 72a6fa60419..9e8ab2ca4a0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExpectedActualDeclarationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExpectedActualDeclarationChecker.kt @@ -110,10 +110,12 @@ object ExpectedActualDeclarationChecker : DeclarationChecker { private fun checkActualDeclarationHasExpected( reportOn: KtNamedDeclaration, descriptor: MemberDescriptor, trace: BindingTrace, checkActual: Boolean ) { - // Using the platform module instead of the common module is sort of fine here because the former always depends on the latter. - // However, it would be clearer to find the common module this platform module implements and look for expected there instead. - // TODO: use common module here - val compatibility = ExpectedActualResolver.findExpectedForActual(descriptor, descriptor.module) ?: return + // TODO: ideally, we should always use common module here + // However, in compiler context platform & common modules are joined into one module, + // so there is yet no "common module" in this situation. + // So yet we are using own module in compiler context and common module in IDE context. + val commonOrOwnModule = descriptor.module.expectedByModule ?: descriptor.module + val compatibility = ExpectedActualResolver.findExpectedForActual(descriptor, commonOrOwnModule) ?: return val hasActualModifier = descriptor.isActual && reportOn.hasActualModifier() if (!hasActualModifier) { diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ModuleDescriptor.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ModuleDescriptor.kt index d5a2164a41a..7035dfabb8f 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ModuleDescriptor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ModuleDescriptor.kt @@ -40,6 +40,8 @@ interface ModuleDescriptor : DeclarationDescriptor { */ val allDependencyModules: List + val expectedByModule: ModuleDescriptor? + fun getCapability(capability: Capability): T? class Capability(val name: String) { diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ModuleDescriptorImpl.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ModuleDescriptorImpl.kt index e7c6862df9f..8c7dce58219 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ModuleDescriptorImpl.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ModuleDescriptorImpl.kt @@ -66,6 +66,9 @@ class ModuleDescriptorImpl @JvmOverloads constructor( override val allDependencyModules: List get() = this.dependencies.sure { "Dependencies of module $id were not set" }.allDependencies.filter { it != this } + override val expectedByModule: ModuleDescriptor? + get() = this.dependencies.sure { "Dependencies of module $id were not set" }.expectedByDependency + override fun getPackage(fqName: FqName): PackageViewDescriptor { assertValid() return packages(fqName) @@ -104,11 +107,11 @@ class ModuleDescriptorImpl @JvmOverloads constructor( } fun setDependencies(descriptors: List) { - setDependencies(ModuleDependenciesImpl(descriptors, emptySet())) + setDependencies(descriptors, emptySet()) } fun setDependencies(descriptors: List, friends: Set) { - setDependencies(ModuleDependenciesImpl(descriptors, friends)) + setDependencies(ModuleDependenciesImpl(descriptors, friends, null)) } override fun shouldSeeInternalsOf(targetModule: ModuleDescriptor): Boolean { @@ -147,9 +150,11 @@ class ModuleDescriptorImpl @JvmOverloads constructor( interface ModuleDependencies { val allDependencies: List val modulesWhoseInternalsAreVisible: Set + val expectedByDependency: ModuleDescriptorImpl? } class ModuleDependenciesImpl( - override val allDependencies: List, - override val modulesWhoseInternalsAreVisible: Set + override val allDependencies: List, + override val modulesWhoseInternalsAreVisible: Set, + override val expectedByDependency: ModuleDescriptorImpl? ) : ModuleDependencies diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/ErrorUtils.java b/core/descriptors/src/org/jetbrains/kotlin/types/ErrorUtils.java index 9216637bc9a..ae2bd983b6a 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/ErrorUtils.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/ErrorUtils.java @@ -85,6 +85,12 @@ public class ErrorUtils { return emptyList(); } + @Nullable + @Override + public ModuleDescriptor getExpectedByModule() { + return null; + } + @Override public R accept(@NotNull DeclarationDescriptorVisitor visitor, D data) { return null; diff --git a/idea/testData/multiModuleHighlighting/multiplatform/basic/jvm/jvm.kt b/idea/testData/multiModuleHighlighting/multiplatform/basic/jvm/jvm.kt index 2634e8e96bf..d513b858280 100644 --- a/idea/testData/multiModuleHighlighting/multiplatform/basic/jvm/jvm.kt +++ b/idea/testData/multiModuleHighlighting/multiplatform/basic/jvm/jvm.kt @@ -10,6 +10,6 @@ expect class Their { } -actual class Their { +actual class Their { } diff --git a/idea/testData/multiModuleHighlighting/multiplatform/depends/common/common.kt b/idea/testData/multiModuleHighlighting/multiplatform/depends/common/common.kt new file mode 100644 index 00000000000..2b091d063d1 --- /dev/null +++ b/idea/testData/multiModuleHighlighting/multiplatform/depends/common/common.kt @@ -0,0 +1 @@ +expect class My diff --git a/idea/testData/multiModuleHighlighting/multiplatform/depends/jvm/jvm.kt b/idea/testData/multiModuleHighlighting/multiplatform/depends/jvm/jvm.kt new file mode 100644 index 00000000000..43ec49aaf7a --- /dev/null +++ b/idea/testData/multiModuleHighlighting/multiplatform/depends/jvm/jvm.kt @@ -0,0 +1 @@ +class My \ No newline at end of file diff --git a/idea/testData/multiModuleHighlighting/multiplatform/triangle/common_base/My.kt b/idea/testData/multiModuleHighlighting/multiplatform/triangle/common_base/My.kt new file mode 100644 index 00000000000..023d50bcba5 --- /dev/null +++ b/idea/testData/multiModuleHighlighting/multiplatform/triangle/common_base/My.kt @@ -0,0 +1 @@ +expect class My \ No newline at end of file diff --git a/idea/testData/multiModuleHighlighting/multiplatform/triangle/common_derived/foo.kt b/idea/testData/multiModuleHighlighting/multiplatform/triangle/common_derived/foo.kt new file mode 100644 index 00000000000..32ace5627a5 --- /dev/null +++ b/idea/testData/multiModuleHighlighting/multiplatform/triangle/common_derived/foo.kt @@ -0,0 +1 @@ +expect fun foo(my: Any) \ No newline at end of file diff --git a/idea/testData/multiModuleHighlighting/multiplatform/triangle/jvm_derived/impl.kt b/idea/testData/multiModuleHighlighting/multiplatform/triangle/jvm_derived/impl.kt new file mode 100644 index 00000000000..24e8106e93f --- /dev/null +++ b/idea/testData/multiModuleHighlighting/multiplatform/triangle/jvm_derived/impl.kt @@ -0,0 +1,3 @@ +class My + +actual fun foo(my: Any) {} \ No newline at end of file diff --git a/idea/testData/multiModuleHighlighting/multiplatform/triangleWithDependency/common_base/My.kt b/idea/testData/multiModuleHighlighting/multiplatform/triangleWithDependency/common_base/My.kt new file mode 100644 index 00000000000..023d50bcba5 --- /dev/null +++ b/idea/testData/multiModuleHighlighting/multiplatform/triangleWithDependency/common_base/My.kt @@ -0,0 +1 @@ +expect class My \ No newline at end of file diff --git a/idea/testData/multiModuleHighlighting/multiplatform/triangleWithDependency/common_derived/foo.kt b/idea/testData/multiModuleHighlighting/multiplatform/triangleWithDependency/common_derived/foo.kt new file mode 100644 index 00000000000..a8508a1a779 --- /dev/null +++ b/idea/testData/multiModuleHighlighting/multiplatform/triangleWithDependency/common_derived/foo.kt @@ -0,0 +1 @@ +expect fun foo(my: My) \ No newline at end of file diff --git a/idea/testData/multiModuleHighlighting/multiplatform/triangleWithDependency/jvm_derived/impl.kt b/idea/testData/multiModuleHighlighting/multiplatform/triangleWithDependency/jvm_derived/impl.kt new file mode 100644 index 00000000000..c79e944e0ce --- /dev/null +++ b/idea/testData/multiModuleHighlighting/multiplatform/triangleWithDependency/jvm_derived/impl.kt @@ -0,0 +1,3 @@ +class My + +actual fun foo(my: My) {} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/MultiPlatformHighlightingTest.kt b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/MultiPlatformHighlightingTest.kt index f742dd3d10c..d71c7a943c5 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/MultiPlatformHighlightingTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/MultiPlatformHighlightingTest.kt @@ -33,6 +33,20 @@ class MultiPlatformHighlightingTest : AbstractMultiModuleHighlightingTest() { doMultiPlatformTest(TargetPlatformKind.Jvm[JvmTarget.JVM_1_6]) } + fun testDepends() { + val commonModule = module("common", TestJdkKind.MOCK_JDK) + commonModule.createFacet(TargetPlatformKind.Common) + commonModule.enableMultiPlatform() + + val jvmPlatform = TargetPlatformKind.Jvm[JvmTarget.JVM_1_6] + val jvmModule = module("jvm", TestJdkKind.MOCK_JDK) + jvmModule.createFacet(jvmPlatform) + jvmModule.enableMultiPlatform() + jvmModule.addDependency(commonModule) + + checkHighlightingInAllFiles() + } + fun testHeaderClass() { doMultiPlatformTest(TargetPlatformKind.Jvm[JvmTarget.JVM_1_6]) } @@ -106,4 +120,40 @@ class MultiPlatformHighlightingTest : AbstractMultiModuleHighlightingTest() { checkHighlightingInAllFiles() } + fun testTriangle() { + val commonModule = module("common_base", TestJdkKind.MOCK_JDK) + commonModule.createFacet(TargetPlatformKind.Common, false) + + val derivedModule = module("common_derived", TestJdkKind.MOCK_JDK) + derivedModule.createFacet(TargetPlatformKind.Common) + derivedModule.enableMultiPlatform() + + val jvmPlatform = TargetPlatformKind.Jvm[JvmTarget.JVM_1_6] + val jvmModule = module("jvm_derived", TestJdkKind.MOCK_JDK) + jvmModule.createFacet(jvmPlatform, implementedModuleName = "common_derived") + jvmModule.enableMultiPlatform() + jvmModule.addDependency(commonModule) + jvmModule.addDependency(derivedModule) + + checkHighlightingInAllFiles() + } + + fun testTriangleWithDependency() { + val commonModule = module("common_base", TestJdkKind.MOCK_JDK) + commonModule.createFacet(TargetPlatformKind.Common, false) + + val derivedModule = module("common_derived", TestJdkKind.MOCK_JDK) + derivedModule.createFacet(TargetPlatformKind.Common) + derivedModule.enableMultiPlatform() + derivedModule.addDependency(commonModule) + + val jvmPlatform = TargetPlatformKind.Jvm[JvmTarget.JVM_1_6] + val jvmModule = module("jvm_derived", TestJdkKind.MOCK_JDK) + jvmModule.createFacet(jvmPlatform, implementedModuleName = "common_derived") + jvmModule.enableMultiPlatform() + jvmModule.addDependency(commonModule) + jvmModule.addDependency(derivedModule) + + checkHighlightingInAllFiles() + } } \ No newline at end of file