Support forward declarations for Native via hack-ing into built-ins
diff --git a/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/NativePlatformKindResolution.kt b/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/NativePlatformKindResolution.kt
index 9c4e4a2..737cbea 100644
--- a/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/NativePlatformKindResolution.kt
+++ b/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/NativePlatformKindResolution.kt
@@ -17,6 +17,9 @@
 import org.jetbrains.kotlin.caches.resolve.IdePlatformKindResolution
 import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
 import org.jetbrains.kotlin.context.ProjectContext
+import org.jetbrains.kotlin.descriptors.ModuleDescriptor
+import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
+import org.jetbrains.kotlin.descriptors.konan.DeserializedKonanModuleOrigin
 import org.jetbrains.kotlin.ide.konan.analyzer.NativeAnalyzerFacade
 import org.jetbrains.kotlin.idea.caches.project.LibraryInfo
 import org.jetbrains.kotlin.idea.caches.project.getModuleInfosFromIdeaModel
@@ -25,6 +28,9 @@
 import org.jetbrains.kotlin.konan.library.*
 import org.jetbrains.kotlin.resolve.ImplicitIntegerCoercion
 import org.jetbrains.kotlin.resolve.konan.platform.KonanPlatform
+import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.konan.util.KonanFactories
 
 class NativePlatformKindResolution : IdePlatformKindResolution {
 
@@ -86,13 +92,45 @@
             metadataReader = CachingIdeMetadataReaderImpl
         )
 
-        val builtInsModule = DefaultDeserializedDescriptorFactory.createDescriptorAndNewBuiltIns(
-            library,
-            LanguageVersionSettingsImpl.DEFAULT,
-            projectContext.storageManager,
-            // This is to preserve "capabilities" from the original IntelliJ LibraryInfo:
-            customCapabilities = libraryInfo.capabilities
+        val libraryProto = library.moduleHeaderData
+
+        val moduleName = Name.special(libraryProto.moduleName)
+        val moduleOrigin = DeserializedKonanModuleOrigin(library)
+
+        val storageManager = projectContext.storageManager
+        val descriptorFactory = KonanFactories.DefaultDescriptorFactory
+
+        val builtInsModule = descriptorFactory.createDescriptorAndNewBuiltIns(
+            moduleName,
+            storageManager,
+            moduleOrigin,
+            libraryInfo.capabilities
         )
+
+        val deserializationConfiguration = CompilerDeserializationConfiguration(LanguageVersionSettingsImpl.DEFAULT)
+
+        val provider = KonanFactories.DefaultPackageFragmentsFactory.createPackageFragmentProvider(
+            library,
+            null,
+            libraryProto.packageFragmentNameList,
+            storageManager,
+            builtInsModule,
+            deserializationConfiguration
+        )
+
+
+        builtInsModule.initialize(
+            CompositePackageFragmentProvider(
+                listOf(
+                    provider,
+                    KonanFactories.DefaultPackageFragmentsFactory.createForwardDeclarationHackPackagePartProvider(
+                        storageManager,
+                        builtInsModule
+                    )
+                )
+            )
+        )
+
         builtInsModule.setDependencies(listOf(builtInsModule))
 
         return builtInsModule.builtIns
diff --git a/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/analyzer/NativeAnalyzerFacade.kt b/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/analyzer/NativeAnalyzerFacade.kt
index 2aee68a..0c7a596 100644
--- a/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/analyzer/NativeAnalyzerFacade.kt
+++ b/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/analyzer/NativeAnalyzerFacade.kt
@@ -70,7 +70,6 @@
                 )
 
             fragmentProviders.add(libPackageFragmentProvider)
-            //TODO: Forward declarations?
         }
 
         return ResolverForModule(CompositePackageFragmentProvider(fragmentProviders), container)
diff --git a/konan/library-reader/src/org/jetbrains/kotlin/serialization/konan/KonanDeserializedPackageFragmentsFactory.kt b/konan/library-reader/src/org/jetbrains/kotlin/serialization/konan/KonanDeserializedPackageFragmentsFactory.kt
index c74ff4d..b85ad56 100644
--- a/konan/library-reader/src/org/jetbrains/kotlin/serialization/konan/KonanDeserializedPackageFragmentsFactory.kt
+++ b/konan/library-reader/src/org/jetbrains/kotlin/serialization/konan/KonanDeserializedPackageFragmentsFactory.kt
@@ -5,9 +5,8 @@
 
 package org.jetbrains.kotlin.serialization.konan
 
-import org.jetbrains.kotlin.descriptors.ModuleDescriptor
-import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
-import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
+import org.jetbrains.kotlin.descriptors.*
+import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
 import org.jetbrains.kotlin.konan.library.KonanLibrary
 import org.jetbrains.kotlin.konan.library.resolver.PackageAccessedHandler
 import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
@@ -37,4 +36,9 @@
         moduleDescriptor: ModuleDescriptor,
         configuration: DeserializationConfiguration
     ): PackageFragmentProvider
+
+    fun createForwardDeclarationHackPackagePartProvider(
+        storageManager: StorageManager,
+        module: ModuleDescriptorImpl
+    ): PackageFragmentProviderImpl
 }
diff --git a/konan/library-reader/src/org/jetbrains/kotlin/serialization/konan/impl/KonanDeserializedPackageFragmentsFactoryImpl.kt b/konan/library-reader/src/org/jetbrains/kotlin/serialization/konan/impl/KonanDeserializedPackageFragmentsFactoryImpl.kt
index 424113a..0bdb4a8 100644
--- a/konan/library-reader/src/org/jetbrains/kotlin/serialization/konan/impl/KonanDeserializedPackageFragmentsFactoryImpl.kt
+++ b/konan/library-reader/src/org/jetbrains/kotlin/serialization/konan/impl/KonanDeserializedPackageFragmentsFactoryImpl.kt
@@ -6,9 +6,12 @@
 package org.jetbrains.kotlin.serialization.konan.impl
 
 import org.jetbrains.kotlin.descriptors.*
+import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
+import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
 import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl
 import org.jetbrains.kotlin.incremental.components.LookupLocation
 import org.jetbrains.kotlin.incremental.components.LookupTracker
+import org.jetbrains.kotlin.incremental.components.NoLookupLocation
 import org.jetbrains.kotlin.konan.library.KonanLibrary
 import org.jetbrains.kotlin.konan.library.exportForwardDeclarations
 import org.jetbrains.kotlin.konan.library.isInterop
@@ -16,6 +19,7 @@
 import org.jetbrains.kotlin.konan.library.resolver.PackageAccessedHandler
 import org.jetbrains.kotlin.name.FqName
 import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
 import org.jetbrains.kotlin.resolve.scopes.MemberScope
 import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl
 import org.jetbrains.kotlin.serialization.deserialization.*
@@ -23,7 +27,9 @@
 import org.jetbrains.kotlin.serialization.konan.KonanPackageFragment
 import org.jetbrains.kotlin.serialization.konan.KonanSerializerProtocol
 import org.jetbrains.kotlin.serialization.konan.NullFlexibleTypeDeserializer
+import org.jetbrains.kotlin.storage.LockBasedStorageManager
 import org.jetbrains.kotlin.storage.StorageManager
+import org.jetbrains.kotlin.storage.getValue
 import org.jetbrains.kotlin.utils.Printer
 import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
 
@@ -122,6 +128,29 @@
 
         return provider
     }
+
+    override fun createForwardDeclarationHackPackagePartProvider(
+        storageManager: StorageManager,
+        module: ModuleDescriptorImpl
+    ): PackageFragmentProviderImpl {
+        fun createPackage(fqName: FqName, supertypeName: String, classKind: ClassKind) =
+            ForwardDeclarationsPackageFragmentDescriptor(
+                storageManager,
+                module,
+                fqName,
+                Name.identifier(supertypeName),
+                classKind
+            )
+
+        val packageFragmentProvider = PackageFragmentProviderImpl(
+            listOf(
+                createPackage(ForwardDeclarationsFqNames.cNamesStructs, "COpaque", ClassKind.CLASS),
+                createPackage(ForwardDeclarationsFqNames.objCNamesClasses, "ObjCObjectBase", ClassKind.CLASS),
+                createPackage(ForwardDeclarationsFqNames.objCNamesProtocols, "ObjCObject", ClassKind.INTERFACE)
+            )
+        )
+        return packageFragmentProvider
+    }
 }
 
 /**
@@ -193,3 +222,52 @@
 
     override fun getMemberScope(): MemberScope = memberScope
 }
+
+
+/**
+ * Package fragment which creates descriptors for forward declarations on demand.
+ */
+private class ForwardDeclarationsPackageFragmentDescriptor(
+    storageManager: StorageManager,
+    module: ModuleDescriptor,
+    fqName: FqName,
+    supertypeName: Name,
+    classKind: ClassKind
+) : PackageFragmentDescriptorImpl(module, fqName) {
+
+    private val memberScope = object : MemberScopeImpl() {
+
+        private val declarations = storageManager.createMemoizedFunction(this::createDeclaration)
+
+        private val supertype by storageManager.createLazyValue {
+            val descriptor = builtIns.builtInsModule.getPackage(ForwardDeclarationsFqNames.packageName)
+                .memberScope
+                .getContributedClassifier(supertypeName, NoLookupLocation.FROM_BACKEND) as ClassDescriptor
+
+            descriptor.defaultType
+        }
+
+        private fun createDeclaration(name: Name): ClassDescriptor {
+            return ClassDescriptorImpl(
+                this@ForwardDeclarationsPackageFragmentDescriptor,
+                name,
+                Modality.FINAL,
+                classKind,
+                listOf(supertype),
+                SourceElement.NO_SOURCE,
+                false,
+                LockBasedStorageManager.NO_LOCKS
+            ).apply {
+                this.initialize(MemberScope.Empty, emptySet(), null)
+            }
+        }
+
+        override fun getContributedClassifier(name: Name, location: LookupLocation) = declarations(name)
+
+        override fun printScopeStructure(p: Printer) {
+            p.println(this::class.java.simpleName, "{}")
+        }
+    }
+
+    override fun getMemberScope(): MemberScope = memberScope
+}
\ No newline at end of file
diff --git a/konan/library-reader/src/org/jetbrains/kotlin/serialization/konan/impl/KonanResolvedModuleDescriptorsFactoryImpl.kt b/konan/library-reader/src/org/jetbrains/kotlin/serialization/konan/impl/KonanResolvedModuleDescriptorsFactoryImpl.kt
index 9aacb35..dce5692 100644
--- a/konan/library-reader/src/org/jetbrains/kotlin/serialization/konan/impl/KonanResolvedModuleDescriptorsFactoryImpl.kt
+++ b/konan/library-reader/src/org/jetbrains/kotlin/serialization/konan/impl/KonanResolvedModuleDescriptorsFactoryImpl.kt
@@ -85,22 +85,8 @@
         val name = Name.special("<forward declarations>")
         val module = createDescriptorOptionalBuiltsIns(name, storageManager, builtIns, SyntheticModulesOrigin)
 
-        fun createPackage(fqName: FqName, supertypeName: String, classKind: ClassKind) =
-            ForwardDeclarationsPackageFragmentDescriptor(
-                storageManager,
-                module,
-                fqName,
-                Name.identifier(supertypeName),
-                classKind
-            )
-
-        val packageFragmentProvider = PackageFragmentProviderImpl(
-            listOf(
-                createPackage(ForwardDeclarationsFqNames.cNamesStructs, "COpaque", ClassKind.CLASS),
-                createPackage(ForwardDeclarationsFqNames.objCNamesClasses, "ObjCObjectBase", ClassKind.CLASS),
-                createPackage(ForwardDeclarationsFqNames.objCNamesProtocols, "ObjCObject", ClassKind.INTERFACE)
-            )
-        )
+        val packageFragmentProvider =
+            moduleDescriptorFactory.packageFragmentsFactory.createForwardDeclarationHackPackagePartProvider(storageManager, module)
 
         module.initialize(packageFragmentProvider)
         module.setDependencies(module)
@@ -144,54 +130,6 @@
         )
 }
 
-/**
- * Package fragment which creates descriptors for forward declarations on demand.
- */
-private class ForwardDeclarationsPackageFragmentDescriptor(
-    storageManager: StorageManager,
-    module: ModuleDescriptor,
-    fqName: FqName,
-    supertypeName: Name,
-    classKind: ClassKind
-) : PackageFragmentDescriptorImpl(module, fqName) {
-
-    private val memberScope = object : MemberScopeImpl() {
-
-        private val declarations = storageManager.createMemoizedFunction(this::createDeclaration)
-
-        private val supertype by storageManager.createLazyValue {
-            val descriptor = builtIns.builtInsModule.getPackage(ForwardDeclarationsFqNames.packageName)
-                .memberScope
-                .getContributedClassifier(supertypeName, NoLookupLocation.FROM_BACKEND) as ClassDescriptor
-
-            descriptor.defaultType
-        }
-
-        private fun createDeclaration(name: Name): ClassDescriptor {
-            return ClassDescriptorImpl(
-                this@ForwardDeclarationsPackageFragmentDescriptor,
-                name,
-                Modality.FINAL,
-                classKind,
-                listOf(supertype),
-                SourceElement.NO_SOURCE,
-                false,
-                LockBasedStorageManager.NO_LOCKS
-            ).apply {
-                this.initialize(MemberScope.Empty, emptySet(), null)
-            }
-        }
-
-        override fun getContributedClassifier(name: Name, location: LookupLocation) = declarations(name)
-
-        override fun printScopeStructure(p: Printer) {
-            p.println(this::class.java.simpleName, "{}")
-        }
-    }
-
-    override fun getMemberScope(): MemberScope = memberScope
-}
-
 // FIXME(ddol): decouple and move interop-specific logic back to Kotlin/Native.
 internal object ForwardDeclarationsFqNames {