K2/Native: support cinterop forward declarations
Support importing synthetic declarations from "magic" forward declaration packages: - cnames.structs - objcnames.classes - objcnames.protocols So this is a rough equivalent to the forward declarations module made of ForwardDeclarationsPackageFragmentDescriptor in K1. Unlike K1 implementation, this K2 one doesn't allow importing a declaration that wasn't actually forward-declared in a C/Objective-C header available through a cinterop klib dependency.
This commit is contained in:
committed by
Space Team
parent
1936efed11
commit
b19058caef
+8
@@ -38,8 +38,16 @@ object FirNativeSessionFactory : FirAbstractSessionFactory() {
|
||||
registerExtraComponents,
|
||||
createKotlinScopeProvider = { FirKotlinScopeProvider { _, declaredMemberScope, _, _ -> declaredMemberScope } },
|
||||
createProviders = { session, builtinsModuleData, kotlinScopeProvider ->
|
||||
val forwardDeclarationsModuleData = BinaryModuleData.createDependencyModuleData(
|
||||
Name.special("<forward declarations>"),
|
||||
moduleDataProvider.platform,
|
||||
moduleDataProvider.analyzerServices,
|
||||
).apply {
|
||||
bindSession(session)
|
||||
}
|
||||
listOf(
|
||||
KlibBasedSymbolProvider(session, moduleDataProvider, kotlinScopeProvider, resolvedLibraries),
|
||||
NativeForwardDeclarationsSymbolProvider(session, forwardDeclarationsModuleData, kotlinScopeProvider, resolvedLibraries),
|
||||
FirBuiltinSymbolProvider(session, builtinsModuleData, kotlinScopeProvider),
|
||||
FirExtensionSyntheticFunctionInterfaceProvider(session, builtinsModuleData, kotlinScopeProvider),
|
||||
FirCloneableSymbolProvider(session, builtinsModuleData, kotlinScopeProvider),
|
||||
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.session
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.FirModuleData
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.caches.createCache
|
||||
import org.jetbrains.kotlin.fir.caches.firCachesFactory
|
||||
import org.jetbrains.kotlin.fir.caches.getValue
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.getDeprecationsProvider
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals
|
||||
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.constructClassType
|
||||
import org.jetbrains.kotlin.library.includedForwardDeclarations
|
||||
import org.jetbrains.kotlin.library.isInterop
|
||||
import org.jetbrains.kotlin.library.metadata.impl.ForwardDeclarationKind
|
||||
import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class NativeForwardDeclarationsSymbolProvider(
|
||||
session: FirSession,
|
||||
private val forwardDeclarationsModuleData: FirModuleData,
|
||||
private val kotlinScopeProvider: FirKotlinScopeProvider,
|
||||
private val resolvedLibraries: Collection<KotlinResolvedLibrary>,
|
||||
) : FirSymbolProvider(session) {
|
||||
private companion object {
|
||||
private val validPackages = ForwardDeclarationKind.packageFqNameToKind.keys
|
||||
}
|
||||
|
||||
private val includedForwardDeclarations: Set<ClassId> by lazy {
|
||||
buildSet {
|
||||
for (resolvedLibrary in resolvedLibraries) {
|
||||
val library = resolvedLibrary.library
|
||||
if (!library.isInterop) continue
|
||||
|
||||
for (fqName in library.includedForwardDeclarations) {
|
||||
val classId = ClassId.topLevel(FqName(fqName))
|
||||
if (classId.packageFqName in validPackages) add(classId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val includedForwardDeclarationsByPackage: Map<FqName, Set<String>> by lazy {
|
||||
buildMap<FqName, MutableSet<String>> {
|
||||
for (classId in includedForwardDeclarations) {
|
||||
getOrPut(classId.packageFqName) { mutableSetOf() }
|
||||
.add(classId.shortClassName.asString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getClassLikeSymbolByClassId(classId: ClassId): FirClassLikeSymbol<*>? {
|
||||
if (classId !in includedForwardDeclarations) return null
|
||||
if (classId.isNestedClass) return null
|
||||
|
||||
return syntheticForwardDeclarationClassCache.getValue(classId)
|
||||
}
|
||||
|
||||
private val syntheticForwardDeclarationClassCache =
|
||||
session.firCachesFactory.createCache(::createSyntheticForwardDeclarationClass)
|
||||
|
||||
private fun createSyntheticForwardDeclarationClass(classId: ClassId): FirClassLikeSymbol<*>? {
|
||||
val forwardDeclarationKind = ForwardDeclarationKind.packageFqNameToKind[classId.packageFqName] ?: return null
|
||||
|
||||
val symbol = FirRegularClassSymbol(classId)
|
||||
|
||||
buildRegularClass {
|
||||
moduleData = forwardDeclarationsModuleData
|
||||
origin = FirDeclarationOrigin.Synthetic
|
||||
check(!classId.isNestedClass) { "Expected top-level class when building forward declaration, got $classId" }
|
||||
name = classId.shortClassName
|
||||
status = FirResolvedDeclarationStatusImpl(
|
||||
Visibilities.Public,
|
||||
Modality.FINAL,
|
||||
EffectiveVisibility.Public
|
||||
).apply {
|
||||
// This will be wrong if we support exported forward declarations.
|
||||
// See https://youtrack.jetbrains.com/issue/KT-51377 for more details.
|
||||
isExpect = false
|
||||
|
||||
isActual = false
|
||||
isCompanion = false
|
||||
isInner = false
|
||||
isData = false
|
||||
isInline = false
|
||||
isExternal = false
|
||||
isFun = false
|
||||
}
|
||||
classKind = forwardDeclarationKind.classKind
|
||||
scopeProvider = kotlinScopeProvider
|
||||
this.symbol = symbol
|
||||
|
||||
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
||||
|
||||
superTypeRefs += buildResolvedTypeRef {
|
||||
type = ConeClassLikeLookupTagImpl(forwardDeclarationKind.superClassId)
|
||||
.constructClassType(emptyArray(), isNullable = false)
|
||||
}
|
||||
}.apply {
|
||||
replaceDeprecationsProvider(getDeprecationsProvider(session))
|
||||
}
|
||||
|
||||
return symbol
|
||||
}
|
||||
|
||||
@FirSymbolProviderInternals
|
||||
override fun getTopLevelCallableSymbolsTo(destination: MutableList<FirCallableSymbol<*>>, packageFqName: FqName, name: Name) {
|
||||
}
|
||||
|
||||
@FirSymbolProviderInternals
|
||||
override fun getTopLevelFunctionSymbolsTo(destination: MutableList<FirNamedFunctionSymbol>, packageFqName: FqName, name: Name) {
|
||||
}
|
||||
|
||||
@FirSymbolProviderInternals
|
||||
override fun getTopLevelPropertySymbolsTo(destination: MutableList<FirPropertySymbol>, packageFqName: FqName, name: Name) {
|
||||
}
|
||||
|
||||
override fun getPackage(fqName: FqName): FqName? {
|
||||
if (fqName in includedForwardDeclarationsByPackage) {
|
||||
return fqName
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun knownTopLevelClassifiersInPackage(packageFqName: FqName): Set<String> {
|
||||
return includedForwardDeclarationsByPackage[packageFqName].orEmpty()
|
||||
}
|
||||
|
||||
override fun computePackageSetWithTopLevelCallables(): Set<String> = emptySet()
|
||||
|
||||
override fun computeCallableNamesInPackage(packageFqName: FqName): Set<Name> = emptySet()
|
||||
}
|
||||
+20
-9
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||
import org.jetbrains.kotlin.library.metadata.*
|
||||
import org.jetbrains.kotlin.library.metadata.resolver.KotlinLibraryResolveResult
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
@@ -120,22 +121,18 @@ class KlibResolvedModuleDescriptorsFactoryImpl(
|
||||
|
||||
val module = createDescriptorOptionalBuiltsIns(FORWARD_DECLARATIONS_MODULE_NAME, storageManager, builtIns, SyntheticModulesOrigin)
|
||||
|
||||
fun createPackage(fqName: FqName, supertypeName: String, classKind: ClassKind) =
|
||||
fun createPackage(forwardDeclarationKind: ForwardDeclarationKind) =
|
||||
ForwardDeclarationsPackageFragmentDescriptor(
|
||||
storageManager,
|
||||
module,
|
||||
fqName,
|
||||
Name.identifier(supertypeName),
|
||||
classKind,
|
||||
forwardDeclarationKind.packageFqName,
|
||||
Name.identifier(forwardDeclarationKind.superClassName),
|
||||
forwardDeclarationKind.classKind,
|
||||
isExpect
|
||||
)
|
||||
|
||||
val packageFragmentProvider = PackageFragmentProviderImpl(
|
||||
listOf(
|
||||
createPackage(ForwardDeclarationsFqNames.cNamesStructs, "COpaque", ClassKind.CLASS),
|
||||
createPackage(ForwardDeclarationsFqNames.objCNamesClasses, "ObjCObjectBase", ClassKind.CLASS),
|
||||
createPackage(ForwardDeclarationsFqNames.objCNamesProtocols, "ObjCObject", ClassKind.INTERFACE)
|
||||
)
|
||||
ForwardDeclarationKind.values().map { createPackage(it) }
|
||||
)
|
||||
|
||||
module.initialize(packageFragmentProvider)
|
||||
@@ -235,3 +232,17 @@ object ForwardDeclarationsFqNames {
|
||||
|
||||
val syntheticPackages = setOf(cNames, objCNames)
|
||||
}
|
||||
|
||||
enum class ForwardDeclarationKind(val packageFqName: FqName, val superClassName: String, val classKind: ClassKind) {
|
||||
CNAMES_STRUCTS(ForwardDeclarationsFqNames.cNamesStructs, "COpaque", ClassKind.CLASS),
|
||||
OBJCNAMES_CLASSES(ForwardDeclarationsFqNames.objCNamesClasses, "ObjCObjectBase", ClassKind.CLASS),
|
||||
OBJCNAMES_PROTOCOLS(ForwardDeclarationsFqNames.objCNamesProtocols, "ObjCObject", ClassKind.INTERFACE)
|
||||
|
||||
;
|
||||
|
||||
val superClassId = ClassId.topLevel(ForwardDeclarationsFqNames.cInterop.child(Name.identifier(superClassName)))
|
||||
|
||||
companion object {
|
||||
val packageFqNameToKind: Map<FqName, ForwardDeclarationKind> = ForwardDeclarationKind.values().associateBy { it.packageFqName }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user